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; +