diff --git a/src/backend/columnar/columnar_metadata_tables.c b/src/backend/columnar/columnar_metadata_tables.c index 92e655a3e..d7c253862 100644 --- a/src/backend/columnar/columnar_metadata_tables.c +++ b/src/backend/columnar/columnar_metadata_tables.c @@ -1029,9 +1029,10 @@ DeleteStorageFromColumnarMetadataTable(Oid metadataTableId, heapTuple = systable_getnext(scanDescriptor); } + systable_endscan_ordered(scanDescriptor); + FinishModifyRelation(modifyState); - systable_endscan_ordered(scanDescriptor); index_close(index, AccessShareLock); table_close(metadataTable, AccessShareLock); } diff --git a/src/backend/columnar/columnar_tableam.c b/src/backend/columnar/columnar_tableam.c index baf31bf9f..c3ed1bb07 100644 --- a/src/backend/columnar/columnar_tableam.c +++ b/src/backend/columnar/columnar_tableam.c @@ -552,10 +552,10 @@ columnar_relation_set_new_filenode(Relation rel, TransactionId *freezeXid, MultiXactId *minmulti) { - if (persistence != RELPERSISTENCE_PERMANENT) + if (persistence == RELPERSISTENCE_UNLOGGED) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("only permanent columnar tables are supported"))); + errmsg("unlogged columnar tables are not supported"))); } Oid oldRelfilenode = rel->rd_node.relNode; @@ -565,7 +565,6 @@ columnar_relation_set_new_filenode(Relation rel, /* delete old relfilenode metadata */ DeleteMetadataRows(rel->rd_node); - Assert(persistence == RELPERSISTENCE_PERMANENT); *freezeXid = RecentXmin; *minmulti = GetOldestMultiXactId(); SMgrRelation srel = RelationCreateStorage(*newrnode, persistence); diff --git a/src/test/regress/columnar_isolation_schedule b/src/test/regress/columnar_isolation_schedule index 93ede5825..eb00bf5b7 100644 --- a/src/test/regress/columnar_isolation_schedule +++ b/src/test/regress/columnar_isolation_schedule @@ -1,2 +1,3 @@ test: columnar_write_concurrency test: columnar_vacuum_vs_insert +test: columnar_temp_tables diff --git a/src/test/regress/expected/columnar_create.out b/src/test/regress/expected/columnar_create.out index 60058aa48..23d21ac5e 100644 --- a/src/test/regress/expected/columnar_create.out +++ b/src/test/regress/expected/columnar_create.out @@ -23,10 +23,7 @@ SELECT count(*) FROM contestant; -- Should fail: unlogged tables not supported CREATE UNLOGGED TABLE columnar_unlogged(i int) USING columnar; -ERROR: only permanent columnar tables are supported --- Should fail: temporary tables not supported -CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; -ERROR: only permanent columnar tables are supported +ERROR: unlogged columnar tables are not supported -- -- Utility functions to be used throughout tests -- @@ -129,3 +126,110 @@ SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id); f (1 row) +-- test temporary columnar tables +-- Should work: temporary tables are supported +CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; +-- reserve some chunks and a stripe +INSERT INTO columnar_temp SELECT i FROM generate_series(1,5) i; +SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id +FROM pg_class WHERE relname='columnar_temp' \gset +\c - - - :master_port +-- show that temporary table itself and it's metadata is removed +SELECT COUNT(*)=0 FROM pg_class WHERE relname='columnar_temp'; + ?column? +--------------------------------------------------------------------- + t +(1 row) + +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + +-- connect to another session and create a temp table with same name +CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; +-- reserve some chunks and a stripe +INSERT INTO columnar_temp SELECT i FROM generate_series(1,5) i; +-- test basic select +SELECT COUNT(*) FROM columnar_temp WHERE i < 5; + count +--------------------------------------------------------------------- + 4 +(1 row) + +SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id +FROM pg_class WHERE relname='columnar_temp' \gset +BEGIN; + DROP TABLE columnar_temp; + -- show that we drop stripes properly + SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + +ROLLBACK; +-- make sure that table is not dropped yet since we rollbacked above xact +SELECT COUNT(*)=1 FROM pg_class WHERE relname='columnar_temp'; + ?column? +--------------------------------------------------------------------- + t +(1 row) + +-- show that we preserve the stripe of the temp columanar table after rollback +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + t +(1 row) + +-- drop it for next tests +DROP TABLE columnar_temp; +BEGIN; + CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar ON COMMIT DROP; + -- force flushing stripe + INSERT INTO columnar_temp SELECT i FROM generate_series(1,150000) i; + SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id + FROM pg_class WHERE relname='columnar_temp' \gset +COMMIT; +-- make sure that table & it's stripe is dropped after commiting above xact +SELECT COUNT(*)=0 FROM pg_class WHERE relname='columnar_temp'; + ?column? +--------------------------------------------------------------------- + t +(1 row) + +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + +BEGIN; + CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar ON COMMIT DELETE ROWS; + -- force flushing stripe + INSERT INTO columnar_temp SELECT i FROM generate_series(1,150000) i; + SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id + FROM pg_class WHERE relname='columnar_temp' \gset +COMMIT; +-- make sure that table is not dropped but it's rows's are deleted after commiting above xact +SELECT COUNT(*)=1 FROM pg_class WHERE relname='columnar_temp'; + ?column? +--------------------------------------------------------------------- + t +(1 row) + +SELECT COUNT(*)=0 FROM columnar_temp; + ?column? +--------------------------------------------------------------------- + t +(1 row) + +-- since we deleted all the rows, we shouldn't have any stripes for table +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + columnar_metadata_has_storage_id +--------------------------------------------------------------------- + f +(1 row) + diff --git a/src/test/regress/expected/columnar_temp_tables.out b/src/test/regress/expected/columnar_temp_tables.out new file mode 100644 index 000000000..11b1be348 --- /dev/null +++ b/src/test/regress/expected/columnar_temp_tables.out @@ -0,0 +1,27 @@ +Parsed test spec with 2 sessions + +starting permutation: s1-begin s2-begin s1-create-temp s1-insert s2-create-temp s2-insert s1-commit s2-commit +step s1-begin: + BEGIN; + +step s2-begin: + BEGIN; + +step s1-create-temp: + CREATE TEMPORARY TABLE columnar_temp (a int, b text, c int) USING columnar; + +step s1-insert: + INSERT INTO columnar_temp VALUES (1, '1', 1); + +step s2-create-temp: + CREATE TEMPORARY TABLE columnar_temp (a int, b text, c int) USING columnar; + +step s2-insert: + INSERT INTO columnar_temp VALUES (1, '1', 1); + +step s1-commit: + COMMIT; + +step s2-commit: + COMMIT; + diff --git a/src/test/regress/spec/columnar_temp_tables.spec b/src/test/regress/spec/columnar_temp_tables.spec new file mode 100644 index 000000000..bffce93cb --- /dev/null +++ b/src/test/regress/spec/columnar_temp_tables.spec @@ -0,0 +1,47 @@ +session "s1" + +step "s1-begin" +{ + BEGIN; +} + +step "s1-create-temp" +{ + CREATE TEMPORARY TABLE columnar_temp (a int, b text, c int) USING columnar; +} + +step "s1-insert" +{ + INSERT INTO columnar_temp VALUES (1, '1', 1); +} + +step "s1-commit" +{ + COMMIT; +} + +session "s2" + +step "s2-begin" +{ + BEGIN; +} + +step "s2-create-temp" +{ + CREATE TEMPORARY TABLE columnar_temp (a int, b text, c int) USING columnar; +} + +step "s2-insert" +{ + INSERT INTO columnar_temp VALUES (1, '1', 1); +} + +step "s2-commit" +{ + COMMIT; +} + +# make sure that we allow creating same-named temporary columnar tables in different sessions +# also make sure that they don't block each other +permutation "s1-begin" "s2-begin" "s1-create-temp" "s1-insert" "s2-create-temp" "s2-insert" "s1-commit" "s2-commit" diff --git a/src/test/regress/sql/columnar_create.sql b/src/test/regress/sql/columnar_create.sql index 00bcc4fc8..2a3263233 100644 --- a/src/test/regress/sql/columnar_create.sql +++ b/src/test/regress/sql/columnar_create.sql @@ -24,9 +24,6 @@ SELECT count(*) FROM contestant; -- Should fail: unlogged tables not supported CREATE UNLOGGED TABLE columnar_unlogged(i int) USING columnar; --- Should fail: temporary tables not supported -CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; - -- -- Utility functions to be used throughout tests -- @@ -121,3 +118,74 @@ 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); + +-- test temporary columnar tables + +-- Should work: temporary tables are supported +CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; + +-- reserve some chunks and a stripe +INSERT INTO columnar_temp SELECT i FROM generate_series(1,5) i; + +SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id +FROM pg_class WHERE relname='columnar_temp' \gset + +\c - - - :master_port + +-- show that temporary table itself and it's metadata is removed +SELECT COUNT(*)=0 FROM pg_class WHERE relname='columnar_temp'; +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + +-- connect to another session and create a temp table with same name +CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar; + +-- reserve some chunks and a stripe +INSERT INTO columnar_temp SELECT i FROM generate_series(1,5) i; + +-- test basic select +SELECT COUNT(*) FROM columnar_temp WHERE i < 5; + +SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id +FROM pg_class WHERE relname='columnar_temp' \gset + +BEGIN; + DROP TABLE columnar_temp; + -- show that we drop stripes properly + SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); +ROLLBACK; + +-- make sure that table is not dropped yet since we rollbacked above xact +SELECT COUNT(*)=1 FROM pg_class WHERE relname='columnar_temp'; +-- show that we preserve the stripe of the temp columanar table after rollback +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + +-- drop it for next tests +DROP TABLE columnar_temp; + +BEGIN; + CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar ON COMMIT DROP; + -- force flushing stripe + INSERT INTO columnar_temp SELECT i FROM generate_series(1,150000) i; + + SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id + FROM pg_class WHERE relname='columnar_temp' \gset +COMMIT; + +-- make sure that table & it's stripe is dropped after commiting above xact +SELECT COUNT(*)=0 FROM pg_class WHERE relname='columnar_temp'; +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id); + +BEGIN; + CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar ON COMMIT DELETE ROWS; + -- force flushing stripe + INSERT INTO columnar_temp SELECT i FROM generate_series(1,150000) i; + + SELECT columnar_relation_storageid(oid) AS columnar_temp_storage_id + FROM pg_class WHERE relname='columnar_temp' \gset +COMMIT; + +-- make sure that table is not dropped but it's rows's are deleted after commiting above xact +SELECT COUNT(*)=1 FROM pg_class WHERE relname='columnar_temp'; +SELECT COUNT(*)=0 FROM columnar_temp; +-- since we deleted all the rows, we shouldn't have any stripes for table +SELECT columnar_metadata_has_storage_id(:columnar_temp_storage_id);