mirror of https://github.com/citusdata/citus.git
Implement nontransactional truncate
parent
b72a4d8d19
commit
62fc59202c
2
cstore.h
2
cstore.h
|
@ -283,7 +283,7 @@ extern StringInfo DecompressBuffer(StringInfo buffer, CompressionType compressio
|
|||
extern void DeleteDataFileMetadataRowIfExists(Oid relfilenode);
|
||||
extern void InitCStoreDataFileMetadata(Oid relfilenode, int blockRowCount);
|
||||
extern void InsertStripeMetadataRow(Oid relfilenode, StripeMetadata *stripe);
|
||||
extern DataFileMetadata * ReadDataFileMetadata(Oid relfilenode);
|
||||
extern DataFileMetadata * ReadDataFileMetadata(Oid relfilenode, bool missingOk);
|
||||
extern void SaveStripeSkipList(Oid relfilenode, uint64 stripe,
|
||||
StripeSkipList *stripeSkipList,
|
||||
TupleDesc tupleDescriptor);
|
||||
|
|
|
@ -343,7 +343,7 @@ InsertStripeMetadataRow(Oid relfilenode, StripeMetadata *stripe)
|
|||
* from cstore_data_files and cstore_stripes.
|
||||
*/
|
||||
DataFileMetadata *
|
||||
ReadDataFileMetadata(Oid relfilenode)
|
||||
ReadDataFileMetadata(Oid relfilenode, bool missingOk)
|
||||
{
|
||||
Oid cstoreStripesOid = InvalidOid;
|
||||
Relation cstoreStripes = NULL;
|
||||
|
@ -357,10 +357,17 @@ ReadDataFileMetadata(Oid relfilenode)
|
|||
DataFileMetadata *datafileMetadata = palloc0(sizeof(DataFileMetadata));
|
||||
found = ReadCStoreDataFiles(relfilenode, &datafileMetadata->blockRowCount);
|
||||
if (!found)
|
||||
{
|
||||
if (!missingOk)
|
||||
{
|
||||
ereport(ERROR, (errmsg("Relfilenode %d doesn't belong to a cstore table.",
|
||||
relfilenode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ScanKeyInit(&scanKey[0], Anum_cstore_stripes_relfilenode,
|
||||
BTEqualStrategyNumber, F_OIDEQ, Int32GetDatum(relfilenode));
|
||||
|
|
|
@ -88,7 +88,7 @@ CStoreBeginRead(Relation relation, TupleDesc tupleDescriptor,
|
|||
MemoryContext stripeReadContext = NULL;
|
||||
Oid relNode = relation->rd_node.relNode;
|
||||
|
||||
datafileMetadata = ReadDataFileMetadata(relNode);
|
||||
datafileMetadata = ReadDataFileMetadata(relNode, false);
|
||||
|
||||
/*
|
||||
* We allocate all stripe specific data in the stripeReadContext, and reset
|
||||
|
@ -309,7 +309,7 @@ CStoreTableRowCount(Relation relation)
|
|||
ListCell *stripeMetadataCell = NULL;
|
||||
uint64 totalRowCount = 0;
|
||||
|
||||
datafileMetadata = ReadDataFileMetadata(relation->rd_node.relNode);
|
||||
datafileMetadata = ReadDataFileMetadata(relation->rd_node.relNode, false);
|
||||
|
||||
foreach(stripeMetadataCell, datafileMetadata->stripeMetadataList)
|
||||
{
|
||||
|
|
|
@ -443,7 +443,20 @@ cstore_relation_set_new_filenode(Relation rel,
|
|||
MultiXactId *minmulti)
|
||||
{
|
||||
SMgrRelation srel;
|
||||
DataFileMetadata *metadata = ReadDataFileMetadata(rel->rd_node.relNode, true);
|
||||
uint64 blockRowCount = 0;
|
||||
|
||||
if (metadata != NULL)
|
||||
{
|
||||
/* existing table (e.g. TRUNCATE), use existing blockRowCount */
|
||||
blockRowCount = metadata->blockRowCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* new table, use options */
|
||||
CStoreOptions *options = CStoreTableAMGetOptions();
|
||||
blockRowCount = options->blockRowCount;
|
||||
}
|
||||
|
||||
/* delete old relfilenode metadata */
|
||||
DeleteDataFileMetadataRowIfExists(rel->rd_node.relNode);
|
||||
|
@ -452,7 +465,7 @@ cstore_relation_set_new_filenode(Relation rel,
|
|||
*freezeXid = RecentXmin;
|
||||
*minmulti = GetOldestMultiXactId();
|
||||
srel = RelationCreateStorage(*newrnode, persistence);
|
||||
InitCStoreDataFileMetadata(newrnode->relNode, options->blockRowCount);
|
||||
InitCStoreDataFileMetadata(newrnode->relNode, blockRowCount);
|
||||
smgrclose(srel);
|
||||
}
|
||||
|
||||
|
@ -460,7 +473,20 @@ cstore_relation_set_new_filenode(Relation rel,
|
|||
static void
|
||||
cstore_relation_nontransactional_truncate(Relation rel)
|
||||
{
|
||||
elog(ERROR, "cstore_relation_nontransactional_truncate not implemented");
|
||||
DataFileMetadata *metadata = ReadDataFileMetadata(rel->rd_node.relNode, false);
|
||||
|
||||
/*
|
||||
* No need to set new relfilenode, since the table was created in this
|
||||
* transaction and no other transaction can see this relation yet. We
|
||||
* can just truncate the relation.
|
||||
*
|
||||
* This is similar to what is done in heapam_relation_nontransactional_truncate.
|
||||
*/
|
||||
RelationTruncate(rel, 0);
|
||||
|
||||
/* Delete old relfilenode metadata and recreate it */
|
||||
DeleteDataFileMetadataRowIfExists(rel->rd_node.relNode);
|
||||
InitCStoreDataFileMetadata(rel->rd_node.relNode, metadata->blockRowCount);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ CStoreBeginWrite(Relation relation,
|
|||
uint64 currentStripeId = 0;
|
||||
Oid relNode = relation->rd_node.relNode;
|
||||
|
||||
datafileMetadata = ReadDataFileMetadata(relNode);
|
||||
datafileMetadata = ReadDataFileMetadata(relNode, false);
|
||||
|
||||
/*
|
||||
* If stripeMetadataList is not empty, jump to the position right after
|
||||
|
|
|
@ -153,6 +153,30 @@ SELECT :cstore_data_files_before_truncate - count(*) FROM cstore.cstore_data_fil
|
|||
0
|
||||
(1 row)
|
||||
|
||||
-- test if truncation in the same transaction that created the table works properly
|
||||
BEGIN;
|
||||
CREATE TABLE cstore_same_transaction_truncate(a int) USING cstore_tableam;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(1, 100);
|
||||
TRUNCATE cstore_same_transaction_truncate;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(20, 23);
|
||||
COMMIT;
|
||||
-- should output "1" for the newly created relation
|
||||
SELECT count(*) - :cstore_data_files_before_truncate FROM cstore.cstore_data_files;
|
||||
?column?
|
||||
----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM cstore_same_transaction_truncate;
|
||||
a
|
||||
----
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
(4 rows)
|
||||
|
||||
DROP TABLE cstore_same_transaction_truncate;
|
||||
-- test if a cached truncate from a pl/pgsql function works
|
||||
CREATE FUNCTION cstore_truncate_test_regular_func() RETURNS void AS $$
|
||||
BEGIN
|
||||
|
|
|
@ -150,6 +150,30 @@ SELECT :cstore_data_files_before_truncate - count(*) FROM cstore.cstore_data_fil
|
|||
0
|
||||
(1 row)
|
||||
|
||||
-- test if truncation in the same transaction that created the table works properly
|
||||
BEGIN;
|
||||
CREATE FOREIGN TABLE cstore_same_transaction_truncate(a int) SERVER cstore_server;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(1, 100);
|
||||
TRUNCATE cstore_same_transaction_truncate;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(20, 23);
|
||||
COMMIT;
|
||||
-- should output "1" for the newly created relation
|
||||
SELECT count(*) - :cstore_data_files_before_truncate FROM cstore.cstore_data_files;
|
||||
?column?
|
||||
----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM cstore_same_transaction_truncate;
|
||||
a
|
||||
----
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
(4 rows)
|
||||
|
||||
DROP FOREIGN TABLE cstore_same_transaction_truncate;
|
||||
-- test if a cached truncate from a pl/pgsql function works
|
||||
CREATE FUNCTION cstore_truncate_test_regular_func() RETURNS void AS $$
|
||||
BEGIN
|
||||
|
|
|
@ -65,6 +65,20 @@ SELECT * from cstore_truncate_test;
|
|||
-- make sure TRUNATE deletes metadata for old relfilenode
|
||||
SELECT :cstore_data_files_before_truncate - count(*) FROM cstore.cstore_data_files;
|
||||
|
||||
-- test if truncation in the same transaction that created the table works properly
|
||||
BEGIN;
|
||||
CREATE TABLE cstore_same_transaction_truncate(a int) USING cstore_tableam;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(1, 100);
|
||||
TRUNCATE cstore_same_transaction_truncate;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(20, 23);
|
||||
COMMIT;
|
||||
|
||||
-- should output "1" for the newly created relation
|
||||
SELECT count(*) - :cstore_data_files_before_truncate FROM cstore.cstore_data_files;
|
||||
SELECT * FROM cstore_same_transaction_truncate;
|
||||
|
||||
DROP TABLE cstore_same_transaction_truncate;
|
||||
|
||||
-- test if a cached truncate from a pl/pgsql function works
|
||||
CREATE FUNCTION cstore_truncate_test_regular_func() RETURNS void AS $$
|
||||
BEGIN
|
||||
|
|
|
@ -62,6 +62,20 @@ SELECT * from cstore_truncate_test;
|
|||
-- make sure TRUNATE deletes metadata for old relfilenode
|
||||
SELECT :cstore_data_files_before_truncate - count(*) FROM cstore.cstore_data_files;
|
||||
|
||||
-- test if truncation in the same transaction that created the table works properly
|
||||
BEGIN;
|
||||
CREATE FOREIGN TABLE cstore_same_transaction_truncate(a int) SERVER cstore_server;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(1, 100);
|
||||
TRUNCATE cstore_same_transaction_truncate;
|
||||
INSERT INTO cstore_same_transaction_truncate SELECT * FROM generate_series(20, 23);
|
||||
COMMIT;
|
||||
|
||||
-- should output "1" for the newly created relation
|
||||
SELECT count(*) - :cstore_data_files_before_truncate FROM cstore.cstore_data_files;
|
||||
SELECT * FROM cstore_same_transaction_truncate;
|
||||
|
||||
DROP FOREIGN TABLE cstore_same_transaction_truncate;
|
||||
|
||||
-- test if a cached truncate from a pl/pgsql function works
|
||||
CREATE FUNCTION cstore_truncate_test_regular_func() RETURNS void AS $$
|
||||
BEGIN
|
||||
|
|
Loading…
Reference in New Issue