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
(cherry picked from commit f8b1ff7214)
pull/5315/head
Onur Tirtir 2021-09-20 17:26:41 +03:00
parent 7da6d68675
commit 9cde3d4122
3 changed files with 107 additions and 0 deletions

View File

@ -173,6 +173,8 @@ columnar_beginscan(Relation relation, Snapshot snapshot,
ParallelTableScanDesc parallel_scan, ParallelTableScanDesc parallel_scan,
uint32 flags) uint32 flags)
{ {
CheckCitusVersion(ERROR);
int natts = relation->rd_att->natts; int natts = relation->rd_att->natts;
/* attr_needed represents 0-indexed attribute numbers */ /* attr_needed represents 0-indexed attribute numbers */
@ -418,6 +420,8 @@ columnar_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
static IndexFetchTableData * static IndexFetchTableData *
columnar_index_fetch_begin(Relation rel) columnar_index_fetch_begin(Relation rel)
{ {
CheckCitusVersion(ERROR);
Oid relfilenode = rel->rd_node.relNode; Oid relfilenode = rel->rd_node.relNode;
if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId())) if (PendingWritesInUpperTransactions(relfilenode, GetCurrentSubTransactionId()))
{ {
@ -638,6 +642,8 @@ static bool
columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot, columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
Snapshot snapshot) Snapshot snapshot)
{ {
CheckCitusVersion(ERROR);
uint64 rowNumber = tid_to_row_number(slot->tts_tid); uint64 rowNumber = tid_to_row_number(slot->tts_tid);
StripeMetadata *stripeMetadata = FindStripeByRowNumber(rel, rowNumber, snapshot); StripeMetadata *stripeMetadata = FindStripeByRowNumber(rel, rowNumber, snapshot);
return stripeMetadata != NULL; return stripeMetadata != NULL;
@ -670,6 +676,8 @@ static void
columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid, columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
int options, BulkInsertState bistate) int options, BulkInsertState bistate)
{ {
CheckCitusVersion(ERROR);
/* /*
* columnar_init_write_state allocates the write state in a longer * columnar_init_write_state allocates the write state in a longer
* lasting context, so no need to worry about it. * lasting context, so no need to worry about it.
@ -716,6 +724,8 @@ static void
columnar_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, columnar_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
CommandId cid, int options, BulkInsertState bistate) CommandId cid, int options, BulkInsertState bistate)
{ {
CheckCitusVersion(ERROR);
ColumnarWriteState *writeState = columnar_init_write_state(relation, ColumnarWriteState *writeState = columnar_init_write_state(relation,
RelationGetDescr(relation), RelationGetDescr(relation),
GetCurrentSubTransactionId()); GetCurrentSubTransactionId());
@ -790,6 +800,8 @@ columnar_relation_set_new_filenode(Relation rel,
TransactionId *freezeXid, TransactionId *freezeXid,
MultiXactId *minmulti) MultiXactId *minmulti)
{ {
CheckCitusVersion(ERROR);
if (persistence == RELPERSISTENCE_UNLOGGED) if (persistence == RELPERSISTENCE_UNLOGGED)
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -825,6 +837,8 @@ columnar_relation_set_new_filenode(Relation rel,
static void static void
columnar_relation_nontransactional_truncate(Relation rel) columnar_relation_nontransactional_truncate(Relation rel)
{ {
CheckCitusVersion(ERROR);
RelFileNode relfilenode = rel->rd_node; RelFileNode relfilenode = rel->rd_node;
NonTransactionDropWriteState(relfilenode.relNode); NonTransactionDropWriteState(relfilenode.relNode);
@ -871,6 +885,8 @@ columnar_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
double *tups_vacuumed, double *tups_vacuumed,
double *tups_recently_dead) double *tups_recently_dead)
{ {
CheckCitusVersion(ERROR);
TupleDesc sourceDesc = RelationGetDescr(OldHeap); TupleDesc sourceDesc = RelationGetDescr(OldHeap);
TupleDesc targetDesc = RelationGetDescr(NewHeap); TupleDesc targetDesc = RelationGetDescr(NewHeap);
@ -967,6 +983,15 @@ static void
columnar_vacuum_rel(Relation rel, VacuumParams *params, columnar_vacuum_rel(Relation rel, VacuumParams *params,
BufferAccessStrategy bstrategy) 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 * If metapage version of relation is older, then we hint users to VACUUM
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade * the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
@ -1276,6 +1301,8 @@ columnar_index_build_range_scan(Relation columnarRelation,
void *callback_state, void *callback_state,
TableScanDesc scan) TableScanDesc scan)
{ {
CheckCitusVersion(ERROR);
if (start_blockno != 0 || numblocks != InvalidBlockNumber) if (start_blockno != 0 || numblocks != InvalidBlockNumber)
{ {
/* /*
@ -1524,6 +1551,8 @@ columnar_index_validate_scan(Relation columnarRelation,
ValidateIndexState * ValidateIndexState *
validateIndexState) validateIndexState)
{ {
CheckCitusVersion(ERROR);
ColumnarReportTotalVirtualBlocks(columnarRelation, snapshot, ColumnarReportTotalVirtualBlocks(columnarRelation, snapshot,
PROGRESS_SCAN_BLOCKS_TOTAL); PROGRESS_SCAN_BLOCKS_TOTAL);
@ -1694,6 +1723,8 @@ TupleSortSkipSmallerItemPointers(Tuplesortstate *tupleSort, ItemPointer targetIt
static uint64 static uint64
columnar_relation_size(Relation rel, ForkNumber forkNumber) columnar_relation_size(Relation rel, ForkNumber forkNumber)
{ {
CheckCitusVersion(ERROR);
uint64 nblocks = 0; uint64 nblocks = 0;
/* Open it at the smgr level if not already done */ /* Open it at the smgr level if not already done */
@ -1719,6 +1750,8 @@ columnar_relation_size(Relation rel, ForkNumber forkNumber)
static bool static bool
columnar_relation_needs_toast_table(Relation rel) columnar_relation_needs_toast_table(Relation rel)
{ {
CheckCitusVersion(ERROR);
return false; return false;
} }
@ -1728,6 +1761,8 @@ columnar_estimate_rel_size(Relation rel, int32 *attr_widths,
BlockNumber *pages, double *tuples, BlockNumber *pages, double *tuples,
double *allvisfrac) double *allvisfrac)
{ {
CheckCitusVersion(ERROR);
RelationOpenSmgr(rel); RelationOpenSmgr(rel);
*pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM); *pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
*tuples = ColumnarTableRowCount(rel); *tuples = ColumnarTableRowCount(rel);
@ -1899,6 +1934,8 @@ ColumnarTableDropHook(Oid relid)
if (IsColumnarTableAmTable(relid)) if (IsColumnarTableAmTable(relid))
{ {
CheckCitusVersion(ERROR);
/* /*
* Drop metadata. No need to drop storage here since for * Drop metadata. No need to drop storage here since for
* tableam tables storage is managed by postgres. * tableam tables storage is managed by postgres.
@ -2020,6 +2057,8 @@ ColumnarProcessUtility(PlannedStmt *pstmt,
GetCreateIndexRelationLockMode(indexStmt)); GetCreateIndexRelationLockMode(indexStmt));
if (rel->rd_tableam == GetColumnarTableAmRoutine()) if (rel->rd_tableam == GetColumnarTableAmRoutine())
{ {
CheckCitusVersion(ERROR);
if (!ColumnarSupportsIndexAM(indexStmt->accessMethod)) if (!ColumnarSupportsIndexAM(indexStmt->accessMethod))
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -2356,6 +2395,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_set);
Datum Datum
alter_columnar_table_set(PG_FUNCTION_ARGS) alter_columnar_table_set(PG_FUNCTION_ARGS)
{ {
CheckCitusVersion(ERROR);
Oid relationId = PG_GETARG_OID(0); Oid relationId = PG_GETARG_OID(0);
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */ Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
@ -2483,6 +2524,8 @@ PG_FUNCTION_INFO_V1(alter_columnar_table_reset);
Datum Datum
alter_columnar_table_reset(PG_FUNCTION_ARGS) alter_columnar_table_reset(PG_FUNCTION_ARGS)
{ {
CheckCitusVersion(ERROR);
Oid relationId = PG_GETARG_OID(0); Oid relationId = PG_GETARG_OID(0);
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */ Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */

View File

@ -750,6 +750,41 @@ SELECT * FROM multi_extension.print_extension_changes();
| view public.citus_tables | view public.citus_tables
(2 rows) (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 -- Test downgrade to 10.0-4 from 10.1-1
ALTER EXTENSION citus UPDATE TO '10.1-1'; ALTER EXTENSION citus UPDATE TO '10.1-1';
ALTER EXTENSION citus UPDATE TO '10.0-4'; ALTER EXTENSION citus UPDATE TO '10.0-4';

View File

@ -297,6 +297,35 @@ ALTER EXTENSION citus UPDATE TO '9.5-1';
ALTER EXTENSION citus UPDATE TO '10.0-4'; ALTER EXTENSION citus UPDATE TO '10.0-4';
SELECT * FROM multi_extension.print_extension_changes(); 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 -- Test downgrade to 10.0-4 from 10.1-1
ALTER EXTENSION citus UPDATE TO '10.1-1'; ALTER EXTENSION citus UPDATE TO '10.1-1';
ALTER EXTENSION citus UPDATE TO '10.0-4'; ALTER EXTENSION citus UPDATE TO '10.0-4';