diff --git a/src/backend/columnar/columnar_metadata_tables.c b/src/backend/columnar/columnar_metadata_tables.c index 1c8a73335..92e655a3e 100644 --- a/src/backend/columnar/columnar_metadata_tables.c +++ b/src/backend/columnar/columnar_metadata_tables.c @@ -95,6 +95,10 @@ static Oid ColumnarChunkGroupRelationId(void); static Oid ColumnarChunkIndexRelationId(void); static Oid ColumnarChunkGroupIndexRelationId(void); static Oid ColumnarNamespaceId(void); +static void DeleteStorageFromColumnarMetadataTable(Oid metadataTableId, + AttrNumber storageIdAtrrNumber, + Oid storageIdIndexId, + uint64 storageId); static ModifyState * StartModifyRelation(Relation rel); static void InsertTupleAndEnforceConstraints(ModifyState *state, Datum *values, bool *nulls); @@ -951,13 +955,12 @@ ReadDataFileStripeList(uint64 storageId, Snapshot snapshot) /* - * DeleteMetadataRows removes the rows with given relfilenode from columnar.stripe. + * DeleteMetadataRows removes the rows with given relfilenode from columnar + * metadata tables. */ void DeleteMetadataRows(RelFileNode relfilenode) { - ScanKeyData scanKey[1]; - /* * During a restore for binary upgrade, metadata tables and indexes may or * may not exist. @@ -977,23 +980,47 @@ DeleteMetadataRows(RelFileNode relfilenode) return; } - ScanKeyInit(&scanKey[0], Anum_columnar_stripe_storageid, - BTEqualStrategyNumber, F_INT8EQ, UInt64GetDatum(metapage->storageId)); + DeleteStorageFromColumnarMetadataTable(ColumnarStripeRelationId(), + Anum_columnar_stripe_storageid, + ColumnarStripeIndexRelationId(), + metapage->storageId); + DeleteStorageFromColumnarMetadataTable(ColumnarChunkGroupRelationId(), + Anum_columnar_chunkgroup_storageid, + ColumnarChunkGroupIndexRelationId(), + metapage->storageId); + DeleteStorageFromColumnarMetadataTable(ColumnarChunkRelationId(), + Anum_columnar_chunk_storageid, + ColumnarChunkIndexRelationId(), + metapage->storageId); +} - Oid columnarStripesOid = ColumnarStripeRelationId(); - Relation columnarStripes = try_relation_open(columnarStripesOid, AccessShareLock); - if (columnarStripes == NULL) + +/* + * DeleteStorageFromColumnarMetadataTable removes the rows with given + * storageId from given columnar metadata table. + */ +static void +DeleteStorageFromColumnarMetadataTable(Oid metadataTableId, + AttrNumber storageIdAtrrNumber, + Oid storageIdIndexId, uint64 storageId) +{ + ScanKeyData scanKey[1]; + ScanKeyInit(&scanKey[0], storageIdAtrrNumber, BTEqualStrategyNumber, + F_INT8EQ, UInt64GetDatum(storageId)); + + Relation metadataTable = try_relation_open(metadataTableId, AccessShareLock); + if (metadataTable == NULL) { /* extension has been dropped */ return; } - Relation index = index_open(ColumnarStripeIndexRelationId(), AccessShareLock); + Relation index = index_open(storageIdIndexId, AccessShareLock); - SysScanDesc scanDescriptor = systable_beginscan_ordered(columnarStripes, index, NULL, + SysScanDesc scanDescriptor = systable_beginscan_ordered(metadataTable, index, NULL, 1, scanKey); - ModifyState *modifyState = StartModifyRelation(columnarStripes); + ModifyState *modifyState = StartModifyRelation(metadataTable); HeapTuple heapTuple = systable_getnext(scanDescriptor); while (HeapTupleIsValid(heapTuple)) @@ -1006,7 +1033,7 @@ DeleteMetadataRows(RelFileNode relfilenode) systable_endscan_ordered(scanDescriptor); index_close(index, AccessShareLock); - table_close(columnarStripes, AccessShareLock); + table_close(metadataTable, AccessShareLock); } diff --git a/src/backend/columnar/sql/columnar--10.0-3--10.1-1.sql b/src/backend/columnar/sql/columnar--10.0-3--10.1-1.sql new file mode 100644 index 000000000..e9c5f850e --- /dev/null +++ b/src/backend/columnar/sql/columnar--10.0-3--10.1-1.sql @@ -0,0 +1,18 @@ +/* columnar--10.0-3--10.1-1.sql */ + +-- Drop foreign keys between columnar metadata tables. +-- Postgres assigns different names to those foreign keys in PG11, so act accordingly. +DO $proc$ +BEGIN +IF substring(current_Setting('server_version'), '\d+')::int >= 12 THEN + EXECUTE $$ +ALTER TABLE columnar.chunk DROP CONSTRAINT chunk_storage_id_stripe_num_chunk_group_num_fkey; +ALTER TABLE columnar.chunk_group DROP CONSTRAINT chunk_group_storage_id_stripe_num_fkey; + $$; +ELSE + EXECUTE $$ +ALTER TABLE columnar.chunk DROP CONSTRAINT chunk_storage_id_fkey; +ALTER TABLE columnar.chunk_group DROP CONSTRAINT chunk_group_storage_id_fkey; + $$; +END IF; +END$proc$; diff --git a/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql b/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql new file mode 100644 index 000000000..de515e62c --- /dev/null +++ b/src/backend/columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql @@ -0,0 +1,10 @@ +/* columnar--10.1-1--10.0-3.sql */ + +-- define foreign keys between columnar metadata tables +ALTER TABLE columnar.chunk +ADD FOREIGN KEY (storage_id, stripe_num, chunk_group_num) +REFERENCES columnar.chunk_group(storage_id, stripe_num, chunk_group_num) ON DELETE CASCADE; + +ALTER TABLE columnar.chunk_group +ADD FOREIGN KEY (storage_id, stripe_num) +REFERENCES columnar.stripe(storage_id, stripe_num) ON DELETE CASCADE; diff --git a/src/backend/distributed/sql/citus--10.0-3--10.1-1.sql b/src/backend/distributed/sql/citus--10.0-3--10.1-1.sql index 0ffc957f4..867041e18 100644 --- a/src/backend/distributed/sql/citus--10.0-3--10.1-1.sql +++ b/src/backend/distributed/sql/citus--10.0-3--10.1-1.sql @@ -1,4 +1,3 @@ -- citus--10.0-3--10.1-1 --- bump version to 10.1-1 - +#include "../../columnar/sql/columnar--10.0-3--10.1-1.sql" diff --git a/src/backend/distributed/sql/downgrades/citus--10.1-1--10.0-3.sql b/src/backend/distributed/sql/downgrades/citus--10.1-1--10.0-3.sql index 85785da52..9612cf9d4 100644 --- a/src/backend/distributed/sql/downgrades/citus--10.1-1--10.0-3.sql +++ b/src/backend/distributed/sql/downgrades/citus--10.1-1--10.0-3.sql @@ -1,3 +1,3 @@ -- citus--10.1-1--10.0-2 --- this is an empty downgrade path since citus--10.0-3--10.1-1.sql is empty for now +#include "../../../columnar/sql/downgrades/columnar--10.1-1--10.0-3.sql" diff --git a/src/test/regress/expected/columnar_create.out b/src/test/regress/expected/columnar_create.out index cb0f4deb7..60058aa48 100644 --- a/src/test/regress/expected/columnar_create.out +++ b/src/test/regress/expected/columnar_create.out @@ -67,3 +67,65 @@ WITH a as ( ) SELECT (SELECT count(*) = 0 FROM c) AND (SELECT count(*) = 0 FROM f) as consistent; +CREATE FUNCTION columnar_metadata_has_storage_id(input_storage_id bigint) RETURNS boolean +AS $$ +DECLARE + union_storage_id_count integer; +BEGIN + SELECT count(*) INTO union_storage_id_count FROM + ( + SELECT storage_id FROM columnar.stripe UNION ALL + SELECT storage_id FROM columnar.chunk UNION ALL + SELECT storage_id FROM columnar.chunk_group + ) AS union_storage_id + WHERE storage_id=input_storage_id; + + IF union_storage_id_count > 0 THEN + RETURN true; + END IF; + + RETURN false; +END; +$$ LANGUAGE plpgsql; +CREATE TABLE columnar_table_1 (a int) USING columnar; +INSERT INTO columnar_table_1 VALUES (1); +CREATE MATERIALIZED VIEW columnar_table_1_mv USING columnar +AS SELECT * FROM columnar_table_1; +SELECT columnar_relation_storageid(oid) AS columnar_table_1_mv_storage_id +FROM pg_class WHERE relname='columnar_table_1_mv' \gset +-- test columnar_relation_set_new_filenode +REFRESH MATERIALIZED VIEW columnar_table_1_mv; +SELECT columnar_metadata_has_storage_id(:columnar_table_1_mv_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + +SELECT columnar_relation_storageid(oid) AS columnar_table_1_storage_id +FROM pg_class WHERE relname='columnar_table_1' \gset +BEGIN; + -- test columnar_relation_nontransactional_truncate + TRUNCATE columnar_table_1; + SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + +ROLLBACK; +-- since we rollback'ed above xact, should return true +SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + t +(1 row) + +-- test dropping columnar table +DROP TABLE columnar_table_1 CASCADE; +NOTICE: drop cascades to materialized view columnar_table_1_mv +SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + diff --git a/src/test/regress/sql/columnar_create.sql b/src/test/regress/sql/columnar_create.sql index e6de5a4ea..00bcc4fc8 100644 --- a/src/test/regress/sql/columnar_create.sql +++ b/src/test/regress/sql/columnar_create.sql @@ -71,3 +71,53 @@ WITH a as ( ) SELECT (SELECT count(*) = 0 FROM c) AND (SELECT count(*) = 0 FROM f) as consistent; + +CREATE FUNCTION columnar_metadata_has_storage_id(input_storage_id bigint) RETURNS boolean +AS $$ +DECLARE + union_storage_id_count integer; +BEGIN + SELECT count(*) INTO union_storage_id_count FROM + ( + SELECT storage_id FROM columnar.stripe UNION ALL + SELECT storage_id FROM columnar.chunk UNION ALL + SELECT storage_id FROM columnar.chunk_group + ) AS union_storage_id + WHERE storage_id=input_storage_id; + + IF union_storage_id_count > 0 THEN + RETURN true; + END IF; + + RETURN false; +END; +$$ LANGUAGE plpgsql; + +CREATE TABLE columnar_table_1 (a int) USING columnar; +INSERT INTO columnar_table_1 VALUES (1); + +CREATE MATERIALIZED VIEW columnar_table_1_mv USING columnar +AS SELECT * FROM columnar_table_1; + +SELECT columnar_relation_storageid(oid) AS columnar_table_1_mv_storage_id +FROM pg_class WHERE relname='columnar_table_1_mv' \gset + +-- test columnar_relation_set_new_filenode +REFRESH MATERIALIZED VIEW columnar_table_1_mv; +SELECT columnar_metadata_has_storage_id(:columnar_table_1_mv_storage_id); + +SELECT columnar_relation_storageid(oid) AS columnar_table_1_storage_id +FROM pg_class WHERE relname='columnar_table_1' \gset + +BEGIN; + -- test columnar_relation_nontransactional_truncate + TRUNCATE columnar_table_1; + SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); +ROLLBACK; + +-- since we rollback'ed above xact, should return true +SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); + +-- test dropping columnar table +DROP TABLE columnar_table_1 CASCADE; +SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id);