From ad919ff2206b7c31f53c7428d5093c4e1e46d2dd Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Mon, 7 Dec 2020 08:25:34 -0800 Subject: [PATCH] Tests for UPDATE and error message improvement. UPDATEs on partitioned tables that affect only row partitions should succeed, the rest should fail. Also rename CStoreScan to ColumnarScan to make the error message more relevant. --- src/backend/columnar/cstore_customscan.c | 13 ++++- src/test/regress/columnar_am_schedule | 1 + src/test/regress/expected/am_empty.out | 8 +-- src/test/regress/expected/am_join.out | 4 +- src/test/regress/expected/am_update.out | 67 ++++++++++++++++++++++ src/test/regress/sql/am_update.sql | 71 ++++++++++++++++++++++++ 6 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 src/test/regress/expected/am_update.out create mode 100644 src/test/regress/sql/am_update.sql diff --git a/src/backend/columnar/cstore_customscan.c b/src/backend/columnar/cstore_customscan.c index 0dfed65ea..97e86721e 100644 --- a/src/backend/columnar/cstore_customscan.c +++ b/src/backend/columnar/cstore_customscan.c @@ -76,17 +76,17 @@ static bool EnableCStoreCustomScan = true; const struct CustomPathMethods CStoreScanPathMethods = { - .CustomName = "CStoreScan", + .CustomName = "ColumnarScan", .PlanCustomPath = CStoreScanPath_PlanCustomPath, }; const struct CustomScanMethods CStoreScanScanMethods = { - .CustomName = "CStoreScan", + .CustomName = "ColumnarScan", .CreateCustomScanState = CStoreScan_CreateCustomScanState, }; const struct CustomExecMethods CStoreExecuteMethods = { - .CustomName = "CStoreScan", + .CustomName = "ColumnarScan", .BeginCustomScan = CStoreScan_BeginCustomScan, .ExecCustomScan = CStoreScan_ExecCustomScan, @@ -304,6 +304,13 @@ CStoreAttrNeeded(ScanState *ss) { Var *var = lfirst(lc); + if (var->varattno < 0) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg( + "UPDATE and CTID scans not supported for ColumnarScan"))); + } + if (var->varattno == 0) { elog(DEBUG1, "Need attribute: all"); diff --git a/src/test/regress/columnar_am_schedule b/src/test/regress/columnar_am_schedule index c951a555d..4ee21f862 100644 --- a/src/test/regress/columnar_am_schedule +++ b/src/test/regress/columnar_am_schedule @@ -10,6 +10,7 @@ test: am_data_types test: am_drop test: am_empty test: am_insert +test: am_update test: am_copyto test: am_alter test: am_alter_set_type diff --git a/src/test/regress/expected/am_empty.out b/src/test/regress/expected/am_empty.out index 43340731b..0bd9cf035 100644 --- a/src/test/regress/expected/am_empty.out +++ b/src/test/regress/expected/am_empty.out @@ -54,15 +54,15 @@ select count(*) from t_compressed; -- explain explain (costs off, summary off, timing off) select * from t_uncompressed; - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- - Custom Scan (CStoreScan) on t_uncompressed + Custom Scan (ColumnarScan) on t_uncompressed (1 row) explain (costs off, summary off, timing off) select * from t_compressed; - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- - Custom Scan (CStoreScan) on t_compressed + Custom Scan (ColumnarScan) on t_compressed (1 row) -- vacuum diff --git a/src/test/regress/expected/am_join.out b/src/test/regress/expected/am_join.out index 32ee99de6..dfd079551 100644 --- a/src/test/regress/expected/am_join.out +++ b/src/test/regress/expected/am_join.out @@ -28,9 +28,9 @@ WHERE things.id > 299990; Aggregate -> Nested Loop Join Filter: (users.id = things.user_id) - -> Custom Scan (CStoreScan) on things + -> Custom Scan (ColumnarScan) on things Filter: (id > 299990) - -> Custom Scan (CStoreScan) on users + -> Custom Scan (ColumnarScan) on users (6 rows) SET client_min_messages TO warning; diff --git a/src/test/regress/expected/am_update.out b/src/test/regress/expected/am_update.out new file mode 100644 index 000000000..84e137fe9 --- /dev/null +++ b/src/test/regress/expected/am_update.out @@ -0,0 +1,67 @@ +CREATE TABLE columnar_update(i int, j int) USING columnar; +INSERT INTO columnar_update VALUES (1, 10); +INSERT INTO columnar_update VALUES (2, 20); +INSERT INTO columnar_update VALUES (3, 30); +-- should fail +UPDATE columnar_update SET j = j+1 WHERE i = 2; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +-- should succeed because there's no target +INSERT INTO columnar_update VALUES + (3, 5), + (4, 5), + (5, 5) + ON CONFLICT DO NOTHING; +-- should fail because we can't create an index on columnar_update.i +INSERT INTO columnar_update VALUES + (3, 5), + (4, 5), + (5, 5) + ON CONFLICT (i) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- tuple locks should fail +SELECT * FROM columnar_update WHERE i = 2 FOR SHARE; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +SELECT * FROM columnar_update WHERE i = 2 FOR UPDATE; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +-- CTID scans should fail +SELECT * FROM columnar_update WHERE ctid = '(0,2)'; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +DROP TABLE columnar_update; +CREATE TABLE parent(ts timestamptz, i int, n numeric, s text) + PARTITION BY RANGE (ts); +CREATE TABLE p0 PARTITION OF parent + FOR VALUES FROM ('2020-01-01') TO ('2020-02-01') + USING COLUMNAR; +CREATE TABLE p1 PARTITION OF parent + FOR VALUES FROM ('2020-02-01') TO ('2020-03-01') + USING COLUMNAR; +CREATE TABLE p2 PARTITION OF parent + FOR VALUES FROM ('2020-03-01') TO ('2020-04-01'); +INSERT INTO parent VALUES('2020-01-15', 10, 100, 'one thousand'); -- columnar +INSERT INTO parent VALUES('2020-02-15', 20, 200, 'two thousand'); -- columnar +INSERT INTO parent VALUES('2020-03-15', 30, 300, 'three thousand'); -- row +SELECT * FROM parent; + ts | i | n | s +--------------------------------------------------------------------- + Wed Jan 15 00:00:00 2020 PST | 10 | 100 | one thousand + Sat Feb 15 00:00:00 2020 PST | 20 | 200 | two thousand + Sun Mar 15 00:00:00 2020 PDT | 30 | 300 | three thousand +(3 rows) + +-- update on specific row partition should succeed +UPDATE p2 SET i = i+1 WHERE ts = '2020-03-15'; +-- update on specific columnar partition should fail +UPDATE p1 SET i = i+1 WHERE ts = '2020-02-15'; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +-- partitioned updates that affect only row tables +-- should succeed +UPDATE parent SET i = i+1 WHERE ts = '2020-03-15'; +-- partitioned updates that affect columnar tables +-- should fail +UPDATE parent SET i = i+1 WHERE ts > '2020-02-15'; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +-- non-partitioned update should fail, even if it +-- only affects a row partition +UPDATE parent SET i = i+1 WHERE n = 300; +ERROR: UPDATE and CTID scans not supported for ColumnarScan +DROP TABLE parent; diff --git a/src/test/regress/sql/am_update.sql b/src/test/regress/sql/am_update.sql new file mode 100644 index 000000000..083478aa6 --- /dev/null +++ b/src/test/regress/sql/am_update.sql @@ -0,0 +1,71 @@ + +CREATE TABLE columnar_update(i int, j int) USING columnar; + +INSERT INTO columnar_update VALUES (1, 10); +INSERT INTO columnar_update VALUES (2, 20); +INSERT INTO columnar_update VALUES (3, 30); + +-- should fail +UPDATE columnar_update SET j = j+1 WHERE i = 2; + +-- should succeed because there's no target +INSERT INTO columnar_update VALUES + (3, 5), + (4, 5), + (5, 5) + ON CONFLICT DO NOTHING; + +-- should fail because we can't create an index on columnar_update.i +INSERT INTO columnar_update VALUES + (3, 5), + (4, 5), + (5, 5) + ON CONFLICT (i) DO NOTHING; + +-- tuple locks should fail +SELECT * FROM columnar_update WHERE i = 2 FOR SHARE; +SELECT * FROM columnar_update WHERE i = 2 FOR UPDATE; + +-- CTID scans should fail +SELECT * FROM columnar_update WHERE ctid = '(0,2)'; + +DROP TABLE columnar_update; + +CREATE TABLE parent(ts timestamptz, i int, n numeric, s text) + PARTITION BY RANGE (ts); + +CREATE TABLE p0 PARTITION OF parent + FOR VALUES FROM ('2020-01-01') TO ('2020-02-01') + USING COLUMNAR; +CREATE TABLE p1 PARTITION OF parent + FOR VALUES FROM ('2020-02-01') TO ('2020-03-01') + USING COLUMNAR; +CREATE TABLE p2 PARTITION OF parent + FOR VALUES FROM ('2020-03-01') TO ('2020-04-01'); + +INSERT INTO parent VALUES('2020-01-15', 10, 100, 'one thousand'); -- columnar +INSERT INTO parent VALUES('2020-02-15', 20, 200, 'two thousand'); -- columnar +INSERT INTO parent VALUES('2020-03-15', 30, 300, 'three thousand'); -- row + +SELECT * FROM parent; + +-- update on specific row partition should succeed +UPDATE p2 SET i = i+1 WHERE ts = '2020-03-15'; + +-- update on specific columnar partition should fail +UPDATE p1 SET i = i+1 WHERE ts = '2020-02-15'; + +-- partitioned updates that affect only row tables +-- should succeed +UPDATE parent SET i = i+1 WHERE ts = '2020-03-15'; + +-- partitioned updates that affect columnar tables +-- should fail +UPDATE parent SET i = i+1 WHERE ts > '2020-02-15'; + +-- non-partitioned update should fail, even if it +-- only affects a row partition +UPDATE parent SET i = i+1 WHERE n = 300; + +DROP TABLE parent; +