mirror of https://github.com/citusdata/citus.git
Support temporary columnar tables (#4766)
parent
56245d232d
commit
1d3e075e62
|
@ -1029,9 +1029,10 @@ DeleteStorageFromColumnarMetadataTable(Oid metadataTableId,
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
heapTuple = systable_getnext(scanDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systable_endscan_ordered(scanDescriptor);
|
||||||
|
|
||||||
FinishModifyRelation(modifyState);
|
FinishModifyRelation(modifyState);
|
||||||
|
|
||||||
systable_endscan_ordered(scanDescriptor);
|
|
||||||
index_close(index, AccessShareLock);
|
index_close(index, AccessShareLock);
|
||||||
table_close(metadataTable, AccessShareLock);
|
table_close(metadataTable, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,10 +552,10 @@ columnar_relation_set_new_filenode(Relation rel,
|
||||||
TransactionId *freezeXid,
|
TransactionId *freezeXid,
|
||||||
MultiXactId *minmulti)
|
MultiXactId *minmulti)
|
||||||
{
|
{
|
||||||
if (persistence != RELPERSISTENCE_PERMANENT)
|
if (persistence == RELPERSISTENCE_UNLOGGED)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
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;
|
Oid oldRelfilenode = rel->rd_node.relNode;
|
||||||
|
@ -565,7 +565,6 @@ columnar_relation_set_new_filenode(Relation rel,
|
||||||
/* delete old relfilenode metadata */
|
/* delete old relfilenode metadata */
|
||||||
DeleteMetadataRows(rel->rd_node);
|
DeleteMetadataRows(rel->rd_node);
|
||||||
|
|
||||||
Assert(persistence == RELPERSISTENCE_PERMANENT);
|
|
||||||
*freezeXid = RecentXmin;
|
*freezeXid = RecentXmin;
|
||||||
*minmulti = GetOldestMultiXactId();
|
*minmulti = GetOldestMultiXactId();
|
||||||
SMgrRelation srel = RelationCreateStorage(*newrnode, persistence);
|
SMgrRelation srel = RelationCreateStorage(*newrnode, persistence);
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
test: columnar_write_concurrency
|
test: columnar_write_concurrency
|
||||||
test: columnar_vacuum_vs_insert
|
test: columnar_vacuum_vs_insert
|
||||||
|
test: columnar_temp_tables
|
||||||
|
|
|
@ -23,10 +23,7 @@ SELECT count(*) FROM contestant;
|
||||||
|
|
||||||
-- Should fail: unlogged tables not supported
|
-- Should fail: unlogged tables not supported
|
||||||
CREATE UNLOGGED TABLE columnar_unlogged(i int) USING columnar;
|
CREATE UNLOGGED TABLE columnar_unlogged(i int) USING columnar;
|
||||||
ERROR: only permanent columnar tables are supported
|
ERROR: unlogged columnar tables are not supported
|
||||||
-- Should fail: temporary tables not supported
|
|
||||||
CREATE TEMPORARY TABLE columnar_temp(i int) USING columnar;
|
|
||||||
ERROR: only permanent columnar tables are supported
|
|
||||||
--
|
--
|
||||||
-- Utility functions to be used throughout tests
|
-- Utility functions to be used throughout tests
|
||||||
--
|
--
|
||||||
|
@ -129,3 +126,110 @@ SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id);
|
||||||
f
|
f
|
||||||
(1 row)
|
(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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
|
@ -24,9 +24,6 @@ SELECT count(*) FROM contestant;
|
||||||
-- Should fail: unlogged tables not supported
|
-- Should fail: unlogged tables not supported
|
||||||
CREATE UNLOGGED TABLE columnar_unlogged(i int) USING columnar;
|
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
|
-- 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
|
-- test dropping columnar table
|
||||||
DROP TABLE columnar_table_1 CASCADE;
|
DROP TABLE columnar_table_1 CASCADE;
|
||||||
SELECT columnar_metadata_has_storage_id(:columnar_table_1_storage_id);
|
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);
|
||||||
|
|
Loading…
Reference in New Issue