From 8d6d62d802116c4cafdcd61570bcd13e108c7bf9 Mon Sep 17 00:00:00 2001 From: velioglu Date: Thu, 4 Apr 2019 14:45:35 +0300 Subject: [PATCH] Make 8.1 compilable with PG 9.6 and make tests pass --- src/backend/distributed/Makefile | 5 +- src/backend/distributed/commands/table.c | 2 + .../distributed/commands/utility_hook.c | 7 +- .../distributed/executor/multi_executor.c | 9 + src/include/distributed/multi_executor.h | 9 +- .../regress/expected/multi_partitioning_1.out | 115 +++++- .../expected/multi_utility_statements_0.out | 373 ++++++++++++++++++ 7 files changed, 512 insertions(+), 8 deletions(-) create mode 100644 src/test/regress/expected/multi_utility_statements_0.out diff --git a/src/backend/distributed/Makefile b/src/backend/distributed/Makefile index 603888082..7d53c5e13 100644 --- a/src/backend/distributed/Makefile +++ b/src/backend/distributed/Makefile @@ -17,7 +17,8 @@ EXTVERSIONS = 5.0 5.0-1 5.0-2 \ 7.3-1 7.3-2 7.3-3 \ 7.4-1 7.4-2 7.4-3 \ 7.5-1 7.5-2 7.5-3 7.5-4 7.5-5 7.5-6 7.5-7 \ - 8.0-1 8.0-2 8.0-3 8.0-4 8.0-5 8.0-6 8.0-7 8.0-8 8.0-9 8.0-10 8.0-11 8.0-12 8.0-13 + 8.0-1 8.0-2 8.0-3 8.0-4 8.0-5 8.0-6 8.0-7 8.0-8 8.0-9 8.0-10 8.0-11 8.0-12 8.0-13 \ + 8.1-1 # All citus--*.sql files in the source directory DATA = $(patsubst $(citus_abs_srcdir)/%.sql,%.sql,$(wildcard $(citus_abs_srcdir)/$(EXTENSION)--*--*.sql)) @@ -241,6 +242,8 @@ $(EXTENSION)--8.0-12.sql: $(EXTENSION)--8.0-11.sql $(EXTENSION)--8.0-11--8.0-12. cat $^ > $@ $(EXTENSION)--8.0-13.sql: $(EXTENSION)--8.0-12.sql $(EXTENSION)--8.0-12--8.0-13.sql cat $^ > $@ +$(EXTENSION)--8.1-1.sql: $(EXTENSION)--8.0-13.sql $(EXTENSION)--8.0-13--8.1-1.sql + cat $^ > $@ NO_PGXS = 1 diff --git a/src/backend/distributed/commands/table.c b/src/backend/distributed/commands/table.c index 6e2336443..25d68201e 100644 --- a/src/backend/distributed/commands/table.c +++ b/src/backend/distributed/commands/table.c @@ -1194,6 +1194,7 @@ SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command) } } } + #if (PG_VERSION_NUM >= 100000) else if (alterTableType == AT_DetachPartition || alterTableType == AT_AttachPartition) { /* check if there are foreign constraints to reference tables */ @@ -1202,6 +1203,7 @@ SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command) executeSequentially = true; } } + #endif /* * If there has already been a parallel query executed, the sequential mode diff --git a/src/backend/distributed/commands/utility_hook.c b/src/backend/distributed/commands/utility_hook.c index 23f05d49d..66e6628f7 100644 --- a/src/backend/distributed/commands/utility_hook.c +++ b/src/backend/distributed/commands/utility_hook.c @@ -458,7 +458,6 @@ multi_ProcessUtility(PlannedStmt *pstmt, } } -#if (PG_VERSION_NUM >= 100000) pstmt->utilityStmt = parsetree; PG_TRY(); @@ -468,14 +467,14 @@ multi_ProcessUtility(PlannedStmt *pstmt, activeAlterTables++; } +#if (PG_VERSION_NUM >= 100000) standard_ProcessUtility(pstmt, queryString, context, params, queryEnv, dest, completionTag); #else - standard_ProcessUtility(parsetree, queryString, context, - params, dest, completionTag); + standard_ProcessUtility(parsetree, queryString, context, + params, dest, completionTag); #endif - if (IsA(parsetree, AlterTableStmt)) { activeAlterTables--; diff --git a/src/backend/distributed/executor/multi_executor.c b/src/backend/distributed/executor/multi_executor.c index 62ff000d7..f3b593cff 100644 --- a/src/backend/distributed/executor/multi_executor.c +++ b/src/backend/distributed/executor/multi_executor.c @@ -102,8 +102,13 @@ CitusExecutorStart(QueryDesc *queryDesc, int eflags) * executes a query. */ void +#if (PG_VERSION_NUM >= 100000) CitusExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once) +#else +CitusExecutorRun(QueryDesc * queryDesc, + ScanDirection direction, uint64 count) +#endif { /* * Disable execution of ALTER TABLE constraint validation queries. These @@ -133,7 +138,11 @@ CitusExecutorRun(QueryDesc *queryDesc, } else { + #if (PG_VERSION_NUM >= 100000) standard_ExecutorRun(queryDesc, direction, count, execute_once); + #else + standard_ExecutorRun(queryDesc, direction, count); + #endif } } diff --git a/src/include/distributed/multi_executor.h b/src/include/distributed/multi_executor.h index c7283d15f..0d393b225 100644 --- a/src/include/distributed/multi_executor.h +++ b/src/include/distributed/multi_executor.h @@ -32,8 +32,13 @@ extern bool WritableStandbyCoordinator; extern void CitusExecutorStart(QueryDesc *queryDesc, int eflags); -extern void CitusExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, - bool execute_once); +extern void +#if (PG_VERSION_NUM >= 100000) +CitusExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, + bool execute_once); +#else +CitusExecutorRun(QueryDesc * queryDesc, ScanDirection direction, uint64 count); +#endif extern TupleTableSlot * ReturnTupleFromTuplestore(CitusScanState *scanState); extern void LoadTuplesIntoTupleStore(CitusScanState *citusScanState, Job *workerJob); extern void ReadFileIntoTupleStore(char *fileName, char *copyFormat, TupleDesc diff --git a/src/test/regress/expected/multi_partitioning_1.out b/src/test/regress/expected/multi_partitioning_1.out index 12dacd4ab..1c12977f1 100644 --- a/src/test/regress/expected/multi_partitioning_1.out +++ b/src/test/regress/expected/multi_partitioning_1.out @@ -1691,8 +1691,121 @@ ORDER BY ERROR: relation "partitioning_schema.schema-test" does not exist LINE 6: logicalrelid IN ('partitioning_schema."schema-test"'::re... ^ +-- test we don't deadlock when attaching and detaching partitions from partitioned +-- tables with foreign keys +CREATE TABLE reference_table(id int PRIMARY KEY); +SELECT create_reference_table('reference_table'); + create_reference_table +------------------------ + +(1 row) + +CREATE TABLE reference_table_2(id int PRIMARY KEY); +SELECT create_reference_table('reference_table_2'); + create_reference_table +------------------------ + +(1 row) + +CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time); +ERROR: syntax error at or near "PARTITION" +LINE 1: CREATE TABLE partitioning_test(id int, time date) PARTITION ... + ^ +CREATE TABLE partitioning_test_2008 PARTITION OF partitioning_test FOR VALUES FROM ('2008-01-01') TO ('2009-01-01'); +ERROR: syntax error at or near "PARTITION" +LINE 1: CREATE TABLE partitioning_test_2008 PARTITION OF partitionin... + ^ +CREATE TABLE partitioning_test_2009 (LIKE partitioning_test); +ERROR: relation "partitioning_test" does not exist +LINE 1: CREATE TABLE partitioning_test_2009 (LIKE partitioning_test)... + ^ +CREATE TABLE partitioning_test_2010 (LIKE partitioning_test); +ERROR: relation "partitioning_test" does not exist +LINE 1: CREATE TABLE partitioning_test_2010 (LIKE partitioning_test)... + ^ +CREATE TABLE partitioning_test_2011 (LIKE partitioning_test); +ERROR: relation "partitioning_test" does not exist +LINE 1: CREATE TABLE partitioning_test_2011 (LIKE partitioning_test)... + ^ +-- distributing partitioning_test will also distribute partitioning_test_2008 +SELECT create_distributed_table('partitioning_test', 'id'); +ERROR: relation "partitioning_test" does not exist +LINE 1: SELECT create_distributed_table('partitioning_test', 'id'); + ^ +SELECT create_distributed_table('partitioning_test_2009', 'id'); +ERROR: relation "partitioning_test_2009" does not exist +LINE 1: SELECT create_distributed_table('partitioning_test_2009', 'i... + ^ +SELECT create_distributed_table('partitioning_test_2010', 'id'); +ERROR: relation "partitioning_test_2010" does not exist +LINE 1: SELECT create_distributed_table('partitioning_test_2010', 'i... + ^ +SELECT create_distributed_table('partitioning_test_2011', 'id'); +ERROR: relation "partitioning_test_2011" does not exist +LINE 1: SELECT create_distributed_table('partitioning_test_2011', 'i... + ^ +ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey + FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE; +ERROR: relation "partitioning_test" does not exist +ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009 + FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE; +ERROR: relation "partitioning_test_2009" does not exist +INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01'); +ERROR: relation "partitioning_test_2010" does not exist +LINE 1: INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01'); + ^ +-- This should fail because of foreign key constraint violation +ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 + FOR VALUES FROM ('2010-01-01') TO ('2011-01-01'); +ERROR: syntax error at or near "ATTACH" +LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_... + ^ +-- Truncate, so attaching again won't fail +TRUNCATE partitioning_test_2010; +ERROR: relation "partitioning_test_2010" does not exist +-- Attach a table which already has the same constraint +ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 + FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); +ERROR: syntax error at or near "ATTACH" +LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_... + ^ +-- Attach a table which doesn't have the constraint +ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 + FOR VALUES FROM ('2010-01-01') TO ('2011-01-01'); +ERROR: syntax error at or near "ATTACH" +LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_... + ^ +-- Attach a table which has a different constraint +ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2011 + FOR VALUES FROM ('2011-01-01') TO ('2012-01-01'); +ERROR: syntax error at or near "ATTACH" +LINE 1: ALTER TABLE partitioning_test ATTACH PARTITION partitioning_... + ^ +ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2008; +ERROR: syntax error at or near "DETACH" +LINE 1: ALTER TABLE partitioning_test DETACH PARTITION partitioning_... + ^ +ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009; +ERROR: syntax error at or near "DETACH" +LINE 1: ALTER TABLE partitioning_test DETACH PARTITION partitioning_... + ^ +ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2010; +ERROR: syntax error at or near "DETACH" +LINE 1: ALTER TABLE partitioning_test DETACH PARTITION partitioning_... + ^ +ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011; +ERROR: syntax error at or near "DETACH" +LINE 1: ALTER TABLE partitioning_test DETACH PARTITION partitioning_... + ^ +DROP TABLE partitioning_test, partitioning_test_2008, partitioning_test_2009, + partitioning_test_2010, partitioning_test_2011, + reference_table, reference_table_2; +ERROR: table "partitioning_test" does not exist DROP SCHEMA partitioning_schema CASCADE; -NOTICE: drop cascades to table "schema-test_2009" +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table "schema-test_2009" +drop cascades to table reference_table +drop cascades to table reference_table_2 RESET SEARCH_PATH; DROP TABLE IF EXISTS partitioning_hash_test, diff --git a/src/test/regress/expected/multi_utility_statements_0.out b/src/test/regress/expected/multi_utility_statements_0.out new file mode 100644 index 000000000..9600c4d71 --- /dev/null +++ b/src/test/regress/expected/multi_utility_statements_0.out @@ -0,0 +1,373 @@ +-- +-- MULTI_UTILITY_STATEMENTS +-- +-- Check that we can run utility statements with embedded SELECT statements on +-- distributed tables. Currently we only support CREATE TABLE AS (SELECT..), +-- DECLARE CURSOR, and COPY ... TO statements. +SET citus.next_shard_id TO 1000000; +CREATE TEMP TABLE lineitem_pricing_summary AS +( + SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order + FROM + lineitem + WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' + GROUP BY + l_returnflag, + l_linestatus + ORDER BY + l_returnflag, + l_linestatus +); +SELECT * FROM lineitem_pricing_summary ORDER BY l_returnflag, l_linestatus; + l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order +--------------+--------------+-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+------------- + A | F | 75465.00 | 113619873.63 | 107841287.0728 | 112171153.245923 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 2944 + N | F | 2022.00 | 3102551.45 | 2952540.7118 | 3072642.770652 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 76 + N | O | 149778.00 | 224706948.16 | 213634857.6854 | 222134071.929801 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 5883 + R | F | 73156.00 | 108937979.73 | 103516623.6698 | 107743533.784328 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 2901 +(4 rows) + +-- Test we can handle joins +CREATE TABLE shipping_priority AS +( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +); +SELECT * FROM shipping_priority; + l_orderkey | revenue | o_orderdate | o_shippriority +------------+-------------+-------------+---------------- + 1637 | 268170.6408 | 02-08-1995 | 0 + 9696 | 252014.5497 | 02-20-1995 | 0 + 10916 | 242749.1996 | 03-11-1995 | 0 + 450 | 221012.3165 | 03-05-1995 | 0 + 5347 | 198353.7942 | 02-22-1995 | 0 + 10691 | 112800.1020 | 03-14-1995 | 0 + 386 | 104975.2484 | 01-25-1995 | 0 + 5765 | 88222.7556 | 12-15-1994 | 0 + 4707 | 88143.7774 | 02-27-1995 | 0 + 5312 | 83750.7028 | 02-24-1995 | 0 + 5728 | 70101.6400 | 12-11-1994 | 0 + 577 | 57986.6224 | 12-19-1994 | 0 + 12706 | 16636.6368 | 11-21-1994 | 0 + 3844 | 8851.3200 | 12-29-1994 | 0 + 11073 | 7433.6295 | 12-02-1994 | 0 + 13924 | 3111.4970 | 12-20-1994 | 0 +(16 rows) + +DROP TABLE shipping_priority; +-- Check COPY against distributed tables works both when specifying a +-- query as the source, and when directly naming a table. +COPY ( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +) TO stdout; +1637 268170.6408 02-08-1995 0 +9696 252014.5497 02-20-1995 0 +10916 242749.1996 03-11-1995 0 +450 221012.3165 03-05-1995 0 +5347 198353.7942 02-22-1995 0 +10691 112800.1020 03-14-1995 0 +386 104975.2484 01-25-1995 0 +5765 88222.7556 12-15-1994 0 +4707 88143.7774 02-27-1995 0 +5312 83750.7028 02-24-1995 0 +5728 70101.6400 12-11-1994 0 +577 57986.6224 12-19-1994 0 +12706 16636.6368 11-21-1994 0 +3844 8851.3200 12-29-1994 0 +11073 7433.6295 12-02-1994 0 +13924 3111.4970 12-20-1994 0 +-- check copying to file +-- (quiet off to force number of copied records to be displayed) +\set QUIET off +COPY nation TO :'dev_null'; +COPY 25 +\set QUIET on +-- stdout +COPY nation TO STDOUT; +0 ALGERIA 0 haggle. carefully final deposits detect slyly agai +1 ARGENTINA 1 al foxes promise slyly according to the regular accounts. bold requests alon +2 BRAZIL 1 y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special +3 CANADA 1 eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold +4 EGYPT 4 y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d +5 ETHIOPIA 0 ven packages wake quickly. regu +6 FRANCE 3 refully final requests. regular, ironi +7 GERMANY 3 l platelets. regular accounts x-ray: unusual, regular acco +8 INDIA 2 ss excuses cajole slyly across the packages. deposits print aroun +9 INDONESIA 2 slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull +10 IRAN 4 efully alongside of the slyly final dependencies. +11 IRAQ 4 nic deposits boost atop the quickly final requests? quickly regula +12 JAPAN 2 ously. final, express gifts cajole a +13 JORDAN 4 ic deposits are blithely about the carefully regular pa +14 KENYA 0 pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t +15 MOROCCO 0 rns. blithely bold courts among the closely regular packages use furiously bold platelets? +16 MOZAMBIQUE 0 s. ironic, unusual asymptotes wake blithely r +17 PERU 1 platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun +18 CHINA 2 c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos +19 ROMANIA 3 ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account +20 SAUDI ARABIA 4 ts. silent requests haggle. closely express packages sleep across the blithely +21 VIETNAM 2 hely enticingly express accounts. even, final +22 RUSSIA 3 requests against the platelets use never according to the quickly regular pint +23 UNITED KINGDOM 3 eans boost carefully special requests. accounts are. carefull +24 UNITED STATES 1 y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be +-- ensure individual cols can be copied out, too +COPY nation(n_name) TO STDOUT; +ALGERIA +ARGENTINA +BRAZIL +CANADA +EGYPT +ETHIOPIA +FRANCE +GERMANY +INDIA +INDONESIA +IRAN +IRAQ +JAPAN +JORDAN +KENYA +MOROCCO +MOZAMBIQUE +PERU +CHINA +ROMANIA +SAUDI ARABIA +VIETNAM +RUSSIA +UNITED KINGDOM +UNITED STATES +-- Test that we can create on-commit drop tables, and also test creating with +-- oids, along with changing column names +BEGIN; +CREATE TEMP TABLE customer_few (customer_key) WITH (OIDS) ON COMMIT DROP AS + (SELECT * FROM customer WHERE c_nationkey = 1 ORDER BY c_custkey LIMIT 10); +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; + customer_key | c_name | c_address +--------------+--------------------+----------------------------------------- + 3 | Customer#000000003 | MG9kdTD2WBHm + 14 | Customer#000000014 | KXkletMlL2JQEA + 30 | Customer#000000030 | nJDsELGAavU63Jl0c5NKsKfL8rIJQQkQnYL2QJY + 59 | Customer#000000059 | zLOCP0wh92OtBihgspOGl4 + 106 | Customer#000000106 | xGCOEAUjUNG +(5 rows) + +COMMIT; +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; +ERROR: relation "customer_few" does not exist +LINE 2: FROM customer_few ORDER BY customer_key LIMIT 5; + ^ +-- Test DECLARE CURSOR .. WITH HOLD without parameters that calls ReScan on the top-level CustomScan +CREATE TABLE cursor_me (x int, y int); +SELECT create_distributed_table('cursor_me', 'x'); + create_distributed_table +-------------------------- + +(1 row) + +INSERT INTO cursor_me SELECT s/10, s FROM generate_series(1, 100) s; +DECLARE holdCursor CURSOR WITH HOLD FOR + SELECT * FROM cursor_me WHERE x = 1 ORDER BY y; +FETCH NEXT FROM holdCursor; + x | y +---+---- + 1 | 10 +(1 row) + +FETCH FORWARD 3 FROM holdCursor; + x | y +---+---- + 1 | 11 + 1 | 12 + 1 | 13 +(3 rows) + +FETCH LAST FROM holdCursor; + x | y +---+---- + 1 | 19 +(1 row) + +FETCH BACKWARD 3 FROM holdCursor; + x | y +---+---- + 1 | 18 + 1 | 17 + 1 | 16 +(3 rows) + +FETCH FORWARD 3 FROM holdCursor; + x | y +---+---- + 1 | 17 + 1 | 18 + 1 | 19 +(3 rows) + +CLOSE holdCursor; +-- Test DECLARE CURSOR .. WITH HOLD with parameter +CREATE OR REPLACE FUNCTION declares_cursor(p int) +RETURNS void AS $$ + DECLARE c CURSOR WITH HOLD FOR SELECT * FROM cursor_me WHERE x = $1; +$$ LANGUAGE SQL; +SELECT declares_cursor(5); +ERROR: could not create distributed plan +DETAIL: Possibly this is caused by the use of parameters in SQL functions, which is not supported in Citus. +HINT: Consider using PL/pgSQL functions instead. +CONTEXT: SQL function "declares_cursor" statement 1 +CREATE OR REPLACE FUNCTION cursor_plpgsql(p int) +RETURNS SETOF int AS $$ +DECLARE + val int; + my_cursor CURSOR (a INTEGER) FOR SELECT y FROM cursor_me WHERE x = $1 ORDER BY y; +BEGIN + -- Open the cursor + OPEN my_cursor(p); + + LOOP + FETCH my_cursor INTO val; + EXIT WHEN NOT FOUND; + + RETURN NEXT val; + END LOOP; + + -- Close the cursor + CLOSE my_cursor; +END; $$ +LANGUAGE plpgsql; +SELECT cursor_plpgsql(4); + cursor_plpgsql +---------------- + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 +(10 rows) + +DROP FUNCTION declares_cursor(int); +DROP FUNCTION cursor_plpgsql(int); +DROP TABLE cursor_me; +-- Test DECLARE CURSOR statement with SCROLL +DECLARE holdCursor SCROLL CURSOR WITH HOLD FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; +FETCH NEXT FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 1 | 17.00 | 0.04 +(1 row) + +FETCH FORWARD 5 FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 2 | 36.00 | 0.09 + 1 | 3 | 8.00 | 0.10 + 1 | 4 | 28.00 | 0.09 + 1 | 5 | 24.00 | 0.10 + 1 | 6 | 32.00 | 0.07 +(5 rows) + +FETCH LAST FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 14947 | 2 | 29.00 | 0.04 +(1 row) + +FETCH BACKWARD 5 FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 14947 | 1 | 14.00 | 0.09 + 14946 | 2 | 37.00 | 0.01 + 14946 | 1 | 38.00 | 0.00 + 14945 | 6 | 37.00 | 0.05 + 14945 | 5 | 44.00 | 0.08 +(5 rows) + +-- Test WITHOUT HOLD cursors inside transactions +BEGIN; +DECLARE noHoldCursor SCROLL CURSOR FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; +FETCH ABSOLUTE 5 FROM noHoldCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 5 | 24.00 | 0.10 +(1 row) + +FETCH BACKWARD noHoldCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 4 | 28.00 | 0.09 +(1 row) + +COMMIT; +FETCH ABSOLUTE 5 FROM noHoldCursor; +ERROR: cursor "noholdcursor" does not exist +-- Test we don't throw an error for DROP IF EXISTS +DROP DATABASE IF EXISTS not_existing_database; +NOTICE: database "not_existing_database" does not exist, skipping +DROP TABLE IF EXISTS not_existing_table; +NOTICE: table "not_existing_table" does not exist, skipping +DROP SCHEMA IF EXISTS not_existing_schema; +NOTICE: schema "not_existing_schema" does not exist, skipping