From f8b1ff72148c48b4bef17f9e6a632a45dd10ce90 Mon Sep 17 00:00:00 2001 From: Onur Tirtir Date: Mon, 20 Sep 2021 17:26:41 +0300 Subject: [PATCH] Add CheckCitusVersion() calls to columnarAM (#5308) Considering all code-paths that we might interact with a columnar table, add `CheckCitusVersion` calls to tableAM callbacks: - initializing table scan (`columnar_beginscan` & `columnar_index_fetch_begin`) - setting a new filenode for a relation (storage initializiation or a table rewrite) - truncating the storage - inserting tuple (single and multi) Also add `CheckCitusVersion` call to: - drop hook (`ColumnarTableDropHook`) - `alter_columnar_table_set` & `alter_columnar_table_reset` UDFs --- src/backend/columnar/columnar_tableam.c | 43 +++++++++++++++++++ src/test/regress/expected/multi_extension.out | 35 +++++++++++++++ src/test/regress/sql/multi_extension.sql | 29 +++++++++++++ 3 files changed, 107 insertions(+) diff --git a/src/backend/columnar/columnar_tableam.c b/src/backend/columnar/columnar_tableam.c index 9c59258ec..1e767458f 100644 --- a/src/backend/columnar/columnar_tableam.c +++ b/src/backend/columnar/columnar_tableam.c @@ -173,6 +173,8 @@ columnar_beginscan(Relation relation, Snapshot snapshot, ParallelTableScanDesc parallel_scan, uint32 flags) { + CheckCitusVersion(ERROR); + int natts = relation->rd_att->natts; /* attr_needed represents 0-indexed attribute numbers */ @@ -418,6 +420,8 @@ columnar_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan) static IndexFetchTableData * columnar_index_fetch_begin(Relation rel) { + CheckCitusVersion(ERROR); + Oid relfilenode = rel->rd_node.relNode; if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId())) { @@ -638,6 +642,8 @@ static bool columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot, Snapshot snapshot) { + CheckCitusVersion(ERROR); + uint64 rowNumber = tid_to_row_number(slot->tts_tid); StripeMetadata *stripeMetadata = FindStripeByRowNumber(rel, rowNumber, snapshot); return stripeMetadata != NULL; @@ -670,6 +676,8 @@ static void columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid, int options, BulkInsertState bistate) { + CheckCitusVersion(ERROR); + /* * columnar_init_write_state allocates the write state in a longer * lasting context, so no need to worry about it. @@ -716,6 +724,8 @@ static void columnar_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, CommandId cid, int options, BulkInsertState bistate) { + CheckCitusVersion(ERROR); + ColumnarWriteState *writeState = columnar_init_write_state(relation, RelationGetDescr(relation), GetCurrentSubTransactionId()); @@ -790,6 +800,8 @@ columnar_relation_set_new_filenode(Relation rel, TransactionId *freezeXid, MultiXactId *minmulti) { + CheckCitusVersion(ERROR); + if (persistence == RELPERSISTENCE_UNLOGGED) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -825,6 +837,8 @@ columnar_relation_set_new_filenode(Relation rel, static void columnar_relation_nontransactional_truncate(Relation rel) { + CheckCitusVersion(ERROR); + RelFileNode relfilenode = rel->rd_node; NonTransactionDropWriteState(relfilenode.relNode); @@ -871,6 +885,8 @@ columnar_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, double *tups_vacuumed, double *tups_recently_dead) { + CheckCitusVersion(ERROR); + TupleDesc sourceDesc = RelationGetDescr(OldHeap); TupleDesc targetDesc = RelationGetDescr(NewHeap); @@ -967,6 +983,15 @@ static void columnar_vacuum_rel(Relation rel, VacuumParams *params, BufferAccessStrategy bstrategy) { + if (!CheckCitusVersion(WARNING)) + { + /* + * Skip if the extension catalogs are not up-to-date, but avoid + * erroring during auto-vacuum. + */ + return; + } + /* * If metapage version of relation is older, then we hint users to VACUUM * the relation in ColumnarMetapageCheckVersion. So if needed, upgrade @@ -1276,6 +1301,8 @@ columnar_index_build_range_scan(Relation columnarRelation, void *callback_state, TableScanDesc scan) { + CheckCitusVersion(ERROR); + if (start_blockno != 0 || numblocks != InvalidBlockNumber) { /* @@ -1524,6 +1551,8 @@ columnar_index_validate_scan(Relation columnarRelation, ValidateIndexState * validateIndexState) { + CheckCitusVersion(ERROR); + ColumnarReportTotalVirtualBlocks(columnarRelation, snapshot, PROGRESS_SCAN_BLOCKS_TOTAL); @@ -1694,6 +1723,8 @@ TupleSortSkipSmallerItemPointers(Tuplesortstate *tupleSort, ItemPointer targetIt static uint64 columnar_relation_size(Relation rel, ForkNumber forkNumber) { + CheckCitusVersion(ERROR); + uint64 nblocks = 0; /* Open it at the smgr level if not already done */ @@ -1719,6 +1750,8 @@ columnar_relation_size(Relation rel, ForkNumber forkNumber) static bool columnar_relation_needs_toast_table(Relation rel) { + CheckCitusVersion(ERROR); + return false; } @@ -1728,6 +1761,8 @@ columnar_estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac) { + CheckCitusVersion(ERROR); + RelationOpenSmgr(rel); *pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM); *tuples = ColumnarTableRowCount(rel); @@ -1899,6 +1934,8 @@ ColumnarTableDropHook(Oid relid) if (IsColumnarTableAmTable(relid)) { + CheckCitusVersion(ERROR); + /* * Drop metadata. No need to drop storage here since for * tableam tables storage is managed by postgres. @@ -2020,6 +2057,8 @@ ColumnarProcessUtility(PlannedStmt *pstmt, GetCreateIndexRelationLockMode(indexStmt)); if (rel->rd_tableam == GetColumnarTableAmRoutine()) { + CheckCitusVersion(ERROR); + if (!ColumnarSupportsIndexAM(indexStmt->accessMethod)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -2356,6 +2395,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_set); Datum alter_columnar_table_set(PG_FUNCTION_ARGS) { + CheckCitusVersion(ERROR); + Oid relationId = PG_GETARG_OID(0); Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */ @@ -2483,6 +2524,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_reset); Datum alter_columnar_table_reset(PG_FUNCTION_ARGS) { + CheckCitusVersion(ERROR); + Oid relationId = PG_GETARG_OID(0); Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */ diff --git a/src/test/regress/expected/multi_extension.out b/src/test/regress/expected/multi_extension.out index 0a6ca29a6..4411a2b85 100644 --- a/src/test/regress/expected/multi_extension.out +++ b/src/test/regress/expected/multi_extension.out @@ -750,6 +750,41 @@ SELECT * FROM multi_extension.print_extension_changes(); | view public.citus_tables (2 rows) +-- not print "HINT: " to hide current lib version +\set VERBOSITY terse +CREATE TABLE columnar_table(a INT, b INT) USING columnar; +SET citus.enable_version_checks TO ON; +-- all should throw an error due to version mismatch +VACUUM FULL columnar_table; +ERROR: loaded Citus library version differs from installed extension version +INSERT INTO columnar_table SELECT i FROM generate_series(1, 10) i; +ERROR: loaded Citus library version differs from installed extension version +VACUUM columnar_table; +WARNING: loaded Citus library version differs from installed extension version +TRUNCATE columnar_table; +ERROR: loaded Citus library version differs from installed extension version +DROP TABLE columnar_table; +ERROR: loaded Citus library version differs from installed extension version +CREATE INDEX ON columnar_table (a); +ERROR: loaded Citus library version differs from installed extension version +SELECT alter_columnar_table_set('columnar_table', compression => 'pglz'); +ERROR: loaded Citus library version differs from installed extension version +SELECT alter_columnar_table_reset('columnar_table'); +ERROR: loaded Citus library version differs from installed extension version +INSERT INTO columnar_table SELECT * FROM columnar_table; +ERROR: loaded Citus library version differs from installed extension version +SELECT 1 FROM columnar_table; -- columnar custom scan +ERROR: loaded Citus library version differs from installed extension version +SET columnar.enable_custom_scan TO OFF; +SELECT 1 FROM columnar_table; -- seq scan +ERROR: loaded Citus library version differs from installed extension version +CREATE TABLE new_columnar_table (a int) USING columnar; +ERROR: loaded Citus library version differs from installed extension version +-- do cleanup for the rest of the tests +SET citus.enable_version_checks TO OFF; +DROP TABLE columnar_table; +RESET columnar.enable_custom_scan; +\set VERBOSITY default -- Test downgrade to 10.0-4 from 10.1-1 ALTER EXTENSION citus UPDATE TO '10.1-1'; ALTER EXTENSION citus UPDATE TO '10.0-4'; diff --git a/src/test/regress/sql/multi_extension.sql b/src/test/regress/sql/multi_extension.sql index 8c54452bb..1312ec8a6 100644 --- a/src/test/regress/sql/multi_extension.sql +++ b/src/test/regress/sql/multi_extension.sql @@ -297,6 +297,35 @@ ALTER EXTENSION citus UPDATE TO '9.5-1'; ALTER EXTENSION citus UPDATE TO '10.0-4'; SELECT * FROM multi_extension.print_extension_changes(); +-- not print "HINT: " to hide current lib version +\set VERBOSITY terse +CREATE TABLE columnar_table(a INT, b INT) USING columnar; +SET citus.enable_version_checks TO ON; + +-- all should throw an error due to version mismatch +VACUUM FULL columnar_table; +INSERT INTO columnar_table SELECT i FROM generate_series(1, 10) i; +VACUUM columnar_table; +TRUNCATE columnar_table; +DROP TABLE columnar_table; +CREATE INDEX ON columnar_table (a); +SELECT alter_columnar_table_set('columnar_table', compression => 'pglz'); +SELECT alter_columnar_table_reset('columnar_table'); +INSERT INTO columnar_table SELECT * FROM columnar_table; + +SELECT 1 FROM columnar_table; -- columnar custom scan + +SET columnar.enable_custom_scan TO OFF; +SELECT 1 FROM columnar_table; -- seq scan + +CREATE TABLE new_columnar_table (a int) USING columnar; + +-- do cleanup for the rest of the tests +SET citus.enable_version_checks TO OFF; +DROP TABLE columnar_table; +RESET columnar.enable_custom_scan; +\set VERBOSITY default + -- Test downgrade to 10.0-4 from 10.1-1 ALTER EXTENSION citus UPDATE TO '10.1-1'; ALTER EXTENSION citus UPDATE TO '10.0-4';