summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPallavi Sontakke2015-08-25 08:13:31 +0000
committerPallavi Sontakke2015-08-25 08:13:31 +0000
commit8a7b7af30cbc659c54941521095ef429550f192b (patch)
treed5c7ecf318a9b057f422c8da12ad83418cf98f20
parent64fe8795534050a4db32db3f0e3c6f2bc612fc88 (diff)
Tests related to user-defined-functions and not-supported features in Postgres-XL
-rwxr-xr-x[-rw-r--r--]src/test/regress/expected/xl_alter_table.out8
-rwxr-xr-xsrc/test/regress/expected/xl_plan_pushdown.out36
-rw-r--r--src/test/regress/expected/xl_plpgsql.out1048
-rw-r--r--src/test/regress/serial_schedule1
-rwxr-xr-x[-rw-r--r--]src/test/regress/sql/xl_alter_table.sql8
-rwxr-xr-xsrc/test/regress/sql/xl_plpgsql.sql545
6 files changed, 1620 insertions, 26 deletions
diff --git a/src/test/regress/expected/xl_alter_table.out b/src/test/regress/expected/xl_alter_table.out
index c3dd967af7..c6285fae23 100644..100755
--- a/src/test/regress/expected/xl_alter_table.out
+++ b/src/test/regress/expected/xl_alter_table.out
@@ -74,8 +74,8 @@ ALTER TABLE xl_at2h ALTER COLUMN product_id DROP DEFAULT;
ALTER TABLE xl_at2h RENAME COLUMN product_no TO product_number;
ALTER TABLE xl_at2h RENAME COLUMN product_id TO product_identifier;
ALTER TABLE xl_at2h RENAME TO xl_at3h;
-ALTER TABLE xl_at3h DELETE NODE (datanode2);
-ALTER TABLE xl_at3h ADD NODE (datanode2);
+ALTER TABLE xl_at3h DELETE NODE (datanode_2);
+ALTER TABLE xl_at3h ADD NODE (datanode_2);
ALTER TABLE xl_at3h DISTRIBUTE BY REPLICATION;
-- MODULO Distributed table:
-- Distribution column cannot be dropped (BUG: It can be dropped now. Test Fails).
@@ -98,8 +98,8 @@ ALTER TABLE xl_at2m ALTER COLUMN product_id DROP DEFAULT;
ALTER TABLE xl_at2m RENAME COLUMN product_no TO product_number;
ALTER TABLE xl_at2m RENAME COLUMN product_id TO product_identifier;
ALTER TABLE xl_at2m RENAME TO xl_at3m;
-ALTER TABLE xl_at3m DELETE NODE (datanode2);
-ALTER TABLE xl_at3m ADD NODE (datanode2);
+ALTER TABLE xl_at3m DELETE NODE (datanode_2);
+ALTER TABLE xl_at3m ADD NODE (datanode_2);
ALTER TABLE xl_at3m DROP COLUMN product_identifier;--fail - distribution column cannot be dropped.
ERROR: Distribution column cannot be dropped
ALTER TABLE xl_at3m DISTRIBUTE BY REPLICATION;
diff --git a/src/test/regress/expected/xl_plan_pushdown.out b/src/test/regress/expected/xl_plan_pushdown.out
index 51580b7ed5..720c631200 100755
--- a/src/test/regress/expected/xl_plan_pushdown.out
+++ b/src/test/regress/expected/xl_plan_pushdown.out
@@ -5,7 +5,7 @@ INSERT INTO xl_pp SELECT generate_series(1,100), 20;
EXPLAIN VERBOSE SELECT * FROM xl_pp WHERE a = 100;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode2) (cost=0.00..35.50 rows=10 width=12)
+ Remote Subquery Scan on all (datanode_2) (cost=0.00..35.50 rows=10 width=12)
Output: a, b
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=12)
Output: a, b
@@ -16,7 +16,7 @@ EXPLAIN VERBOSE SELECT * FROM xl_pp WHERE a = 100;
EXPLAIN VERBOSE SELECT * FROM xl_pp WHERE a = 100::bigint;
QUERY PLAN
------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode2) (cost=0.00..35.50 rows=10 width=12)
+ Remote Subquery Scan on all (datanode_2) (cost=0.00..35.50 rows=10 width=12)
Output: a, b
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=12)
Output: a, b
@@ -31,7 +31,7 @@ EXPLAIN VERBOSE SELECT * FROM xl_pp WHERE a = 100::bigint;
EXPLAIN VERBOSE INSERT INTO xl_pp (a, b) VALUES (200, 1) ;
QUERY PLAN
----------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..0.01 rows=1 width=0)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..0.01 rows=1 width=0)
-> Insert on public.xl_pp (cost=0.00..0.01 rows=1 width=0)
-> Remote Subquery Scan on local node (cost=0.00..0.01 rows=1 width=0)
Output: '200'::bigint, 1
@@ -43,7 +43,7 @@ EXPLAIN VERBOSE INSERT INTO xl_pp (a, b) VALUES (200, 1) ;
EXPLAIN VERBOSE INSERT INTO xl_pp (a, b) VALUES (201::bigint, 1) ;
QUERY PLAN
----------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..0.01 rows=1 width=0)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..0.01 rows=1 width=0)
-> Insert on public.xl_pp (cost=0.00..0.01 rows=1 width=0)
-> Remote Subquery Scan on local node (cost=0.00..0.01 rows=1 width=0)
Output: '201'::bigint, 1
@@ -55,7 +55,7 @@ EXPLAIN VERBOSE INSERT INTO xl_pp (a, b) VALUES (201::bigint, 1) ;
EXPLAIN VERBOSE UPDATE xl_pp SET b=2 where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..35.50 rows=10 width=18)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..35.50 rows=10 width=18)
-> Update on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
Output: a, 2, a, xc_node_id, ctid
@@ -65,7 +65,7 @@ EXPLAIN VERBOSE UPDATE xl_pp SET b=2 where a=200;
EXPLAIN VERBOSE UPDATE xl_pp SET b=2 where a=200::bigint;
QUERY PLAN
------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..35.50 rows=10 width=18)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..35.50 rows=10 width=18)
-> Update on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
Output: a, 2, a, xc_node_id, ctid
@@ -75,7 +75,7 @@ EXPLAIN VERBOSE UPDATE xl_pp SET b=2 where a=200::bigint;
EXPLAIN VERBOSE DELETE FROM xl_pp where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..35.50 rows=10 width=18)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..35.50 rows=10 width=18)
-> Delete on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
Output: a, xc_node_id, ctid, a
@@ -95,7 +95,7 @@ SELECT * from xl_pp where a=200::bigint;
EXPLAIN VERBOSE DELETE FROM xl_pp where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..35.50 rows=10 width=18)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..35.50 rows=10 width=18)
-> Delete on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
Output: a, xc_node_id, ctid, a
@@ -105,7 +105,7 @@ EXPLAIN VERBOSE DELETE FROM xl_pp where a=200;
EXPLAIN VERBOSE DELETE FROM xl_pp where a=200::bigint;
QUERY PLAN
------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..35.50 rows=10 width=18)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..35.50 rows=10 width=18)
-> Delete on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
-> Seq Scan on public.xl_pp (cost=0.00..35.50 rows=10 width=18)
Output: a, xc_node_id, ctid, a
@@ -118,7 +118,7 @@ INSERT INTO xl_ppm SELECT generate_series(1,100), 20;
EXPLAIN VERBOSE SELECT * FROM xl_ppm WHERE a = 100;
QUERY PLAN
---------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=6)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=6)
Output: a, b
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=6)
Output: a, b
@@ -129,7 +129,7 @@ EXPLAIN VERBOSE SELECT * FROM xl_ppm WHERE a = 100;
EXPLAIN VERBOSE SELECT * FROM xl_ppm WHERE a = 100::INT2;
QUERY PLAN
-----------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=6)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=6)
Output: a, b
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=6)
Output: a, b
@@ -144,7 +144,7 @@ EXPLAIN VERBOSE SELECT * FROM xl_ppm WHERE a = 100::INT2;
EXPLAIN VERBOSE INSERT INTO xl_ppm (a, b) VALUES (200, 1) ;
QUERY PLAN
----------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..0.01 rows=1 width=0)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..0.01 rows=1 width=0)
-> Insert on public.xl_ppm (cost=0.00..0.01 rows=1 width=0)
-> Remote Subquery Scan on local node (cost=0.00..0.01 rows=1 width=0)
Output: '200'::smallint, 1
@@ -156,7 +156,7 @@ EXPLAIN VERBOSE INSERT INTO xl_ppm (a, b) VALUES (200, 1) ;
EXPLAIN VERBOSE INSERT INTO xl_ppm (a, b) VALUES (201::INT2, 1) ;
QUERY PLAN
----------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode2) (cost=0.00..0.01 rows=1 width=0)
+ Remote Subquery Scan on all (datanode_2) (cost=0.00..0.01 rows=1 width=0)
-> Insert on public.xl_ppm (cost=0.00..0.01 rows=1 width=0)
-> Remote Subquery Scan on local node (cost=0.00..0.01 rows=1 width=0)
Output: '201'::smallint, 1
@@ -168,7 +168,7 @@ EXPLAIN VERBOSE INSERT INTO xl_ppm (a, b) VALUES (201::INT2, 1) ;
EXPLAIN VERBOSE UPDATE xl_ppm SET b=2 where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=12)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=12)
-> Update on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
Output: a, 2, a, xc_node_id, ctid
@@ -178,7 +178,7 @@ EXPLAIN VERBOSE UPDATE xl_ppm SET b=2 where a=200;
EXPLAIN VERBOSE UPDATE xl_ppm SET b=2 where a=200::INT2;
QUERY PLAN
------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=12)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=12)
-> Update on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
Output: a, 2, a, xc_node_id, ctid
@@ -188,7 +188,7 @@ EXPLAIN VERBOSE UPDATE xl_ppm SET b=2 where a=200::INT2;
EXPLAIN VERBOSE DELETE FROM xl_ppm where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=12)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=12)
-> Delete on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
Output: a, xc_node_id, ctid, a
@@ -208,7 +208,7 @@ SELECT * from xl_ppm where a=200::INT2;
EXPLAIN VERBOSE DELETE FROM xl_ppm where a=200;
QUERY PLAN
----------------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=12)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=12)
-> Delete on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
Output: a, xc_node_id, ctid, a
@@ -218,7 +218,7 @@ EXPLAIN VERBOSE DELETE FROM xl_ppm where a=200;
EXPLAIN VERBOSE DELETE FROM xl_ppm where a=200::INT2;
QUERY PLAN
------------------------------------------------------------------------------
- Remote Subquery Scan on all (datanode1) (cost=0.00..40.00 rows=12 width=12)
+ Remote Subquery Scan on all (datanode_1) (cost=0.00..40.00 rows=12 width=12)
-> Delete on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
-> Seq Scan on public.xl_ppm (cost=0.00..40.00 rows=12 width=12)
Output: a, xc_node_id, ctid, a
diff --git a/src/test/regress/expected/xl_plpgsql.out b/src/test/regress/expected/xl_plpgsql.out
new file mode 100644
index 0000000000..b2776aa544
--- /dev/null
+++ b/src/test/regress/expected/xl_plpgsql.out
@@ -0,0 +1,1048 @@
+--User defined functions have several limitations
+--
+-- PLPGSQL
+-- Table xl_room default distributed by Hash(roomno) on all nodes.
+create table xl_Room (
+ roomno char(8),
+ comment text
+);
+create unique index xl_Room_rno on xl_Room using btree (roomno bpchar_ops);
+-- Table xl_wslot default distributed by Hash(slotname) on all nodes.
+create table xl_WSlot (
+ slotname char(20),
+ roomno char(8),
+ slotlink char(20),
+ backlink char(20)
+);
+create unique index xl_WSlot_name on xl_WSlot using btree (slotname bpchar_ops);
+--default distributed by HASH(slotname)
+create table xl_PLine (
+ slotname char(20),
+ phonenumber char(20),
+ comment text,
+ backlink char(20)
+);
+create unique index xl_PLine_name on xl_PLine using btree (slotname bpchar_ops);
+-- ************************************************************
+-- *
+-- * Trigger procedures and functions for the patchfield
+-- * test of PL/pgSQL
+-- *
+-- ************************************************************
+-- ************************************************************
+-- * AFTER UPDATE on Room
+-- * - If room no changes let wall slots follow
+-- ************************************************************
+create function xl_room_au() returns trigger as '
+begin
+ if new.roomno != old.roomno then
+ update xl_WSlot set roomno = new.roomno where roomno = old.roomno;
+ end if;
+ return new;
+end;
+' language plpgsql;
+--BEFORE/AFTER TRIGGERs are not supported in Postgres-XL - below would fail
+create trigger tg_room_bu before update
+ on xl_Room for each row execute procedure xl_room_au();
+ERROR: Postgres-XL does not support TRIGGER yet
+DETAIL: The feature is not currently supported
+create trigger xl_room_au after update
+ on xl_Room for each row execute procedure xl_room_au();
+ERROR: Postgres-XL does not support TRIGGER yet
+DETAIL: The feature is not currently supported
+--
+-- Test error trapping
+--
+--Internal subtransactions (exception clause within a function)
+-- calling below function would fail.
+create function xl_trap_zero_divide(int) returns int as $$
+declare x int;
+ sx smallint;
+begin
+ begin -- start a subtransaction
+ raise notice 'should see this';
+ x := 100 / $1;
+ raise notice 'should see this only if % <> 0', $1;
+ sx := $1;
+ raise notice 'should see this only if % fits in smallint', $1;
+ if $1 < 0 then
+ raise exception '% is less than zero', $1;
+ end if;
+ exception
+ when division_by_zero then
+ raise notice 'caught division_by_zero';
+ x := -1;
+ when NUMERIC_VALUE_OUT_OF_RANGE then
+ raise notice 'caught numeric_value_out_of_range';
+ x := -2;
+ end;
+ return x;
+end$$ language plpgsql;
+select xl_trap_zero_divide(50);
+ERROR: Internal subtransactions not supported in Postgres-XL
+CONTEXT: PL/pgSQL function xl_trap_zero_divide(integer) line 5 during statement block entry
+--SERIALIZABLE TRANSACTIONs are not supported. Isolation level SERIALIZABLE is converted to REPEATABLE READ internally silently.
+-- ALTER OPERATOR FAMILY ... ADD/DROP
+-- Should work. Textbook case of CREATE / ALTER ADD / ALTER DROP / DROP
+BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+CREATE OPERATOR FAMILY alt_opf4 USING btree;
+ALTER OPERATOR FAMILY alt_opf4 USING btree ADD
+ -- int4 vs int2
+ OPERATOR 1 < (int4, int2) ,
+ OPERATOR 2 <= (int4, int2) ,
+ OPERATOR 3 = (int4, int2) ,
+ OPERATOR 4 >= (int4, int2) ,
+ OPERATOR 5 > (int4, int2) ,
+ FUNCTION 1 btint42cmp(int4, int2);
+ALTER OPERATOR FAMILY alt_opf4 USING btree DROP
+ -- int4 vs int2
+ OPERATOR 1 (int4, int2) ,
+ OPERATOR 2 (int4, int2) ,
+ OPERATOR 3 (int4, int2) ,
+ OPERATOR 4 (int4, int2) ,
+ OPERATOR 5 (int4, int2) ,
+ FUNCTION 1 (int4, int2) ;
+DROP OPERATOR FAMILY alt_opf4 USING btree;
+ROLLBACK;
+create function xl_nodename_from_id(integer) returns name as $$
+declare
+ n name;
+BEGIN
+ select node_name into n from pgxc_node where node_id = $1;
+ RETURN n;
+END;$$ language plpgsql;
+--insert Plines
+insert into xl_PLine values ('PL.001', '-0', 'Central call', 'PS.base.ta1');
+insert into xl_PLine values ('PL.002', '-101', '', 'PS.base.ta2');
+insert into xl_PLine values ('PL.003', '-102', '', 'PS.base.ta3');
+insert into xl_PLine values ('PL.004', '-103', '', 'PS.base.ta5');
+insert into xl_PLine values ('PL.005', '-104', '', 'PS.base.ta6');
+insert into xl_PLine values ('PL.006', '-106', '', 'PS.base.tb2');
+insert into xl_PLine values ('PL.007', '-108', '', 'PS.base.tb3');
+insert into xl_PLine values ('PL.008', '-109', '', 'PS.base.tb4');
+insert into xl_PLine values ('PL.009', '-121', '', 'PS.base.tb5');
+insert into xl_PLine values ('PL.010', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.011', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.012', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.013', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.014', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.015', '-134', '', 'PS.first.ta1');
+insert into xl_PLine values ('PL.016', '-137', '', 'PS.first.ta3');
+insert into xl_PLine values ('PL.017', '-139', '', 'PS.first.ta4');
+insert into xl_PLine values ('PL.018', '-362', '', 'PS.first.tb1');
+insert into xl_PLine values ('PL.019', '-363', '', 'PS.first.tb2');
+insert into xl_PLine values ('PL.020', '-364', '', 'PS.first.tb3');
+insert into xl_PLine values ('PL.021', '-365', '', 'PS.first.tb5');
+insert into xl_PLine values ('PL.022', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.023', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.024', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.025', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.026', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.027', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.028', '-501', 'Fax entrance', 'PS.base.ta2');
+insert into xl_PLine values ('PL.029', '-502', 'Fax first floor', 'PS.first.ta1');
+--INSENSITIVE/SCROLL/WITH HOLD cursors are not supported
+-- if INSENSITIVE is not allowed then what is the default for Postgres-XL for cursor ?
+-- May also check over here - FETCH and WHERE CURRENT OF conditions
+-- WHERE CURRENT OF is not supported
+--Many forms of FETCH are not supported such as those involving PRIOR, FIRST, LAST, ABSOLUTE, BACKWARD
+--Basic test with data spannig on multiple nodes is working fine.
+--scroll cursor would be insensitive to updates happening to the table
+BEGIN;
+declare xl_scroll_cursor SCROLL CURSOR for select * from xl_Pline order by slotname;
+FETCH ALL FROM xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.001 | -0 | Central call | PS.base.ta1
+ PL.002 | -101 | | PS.base.ta2
+ PL.003 | -102 | | PS.base.ta3
+ PL.004 | -103 | | PS.base.ta5
+ PL.005 | -104 | | PS.base.ta6
+ PL.006 | -106 | | PS.base.tb2
+ PL.007 | -108 | | PS.base.tb3
+ PL.008 | -109 | | PS.base.tb4
+ PL.009 | -121 | | PS.base.tb5
+ PL.010 | -122 | | PS.base.tb6
+ PL.011 | -122 | | PS.base.tb6
+ PL.012 | -122 | | PS.base.tb6
+ PL.013 | -122 | | PS.base.tb6
+ PL.014 | -122 | | PS.base.tb6
+ PL.015 | -134 | | PS.first.ta1
+ PL.016 | -137 | | PS.first.ta3
+ PL.017 | -139 | | PS.first.ta4
+ PL.018 | -362 | | PS.first.tb1
+ PL.019 | -363 | | PS.first.tb2
+ PL.020 | -364 | | PS.first.tb3
+ PL.021 | -365 | | PS.first.tb5
+ PL.022 | -367 | | PS.first.tb6
+ PL.023 | -367 | | PS.first.tb6
+ PL.024 | -367 | | PS.first.tb6
+ PL.025 | -367 | | PS.first.tb6
+ PL.026 | -367 | | PS.first.tb6
+ PL.027 | -367 | | PS.first.tb6
+ PL.028 | -501 | Fax entrance | PS.base.ta2
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(29 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.001 | -0 | Central call | PS.base.ta1
+ datanode_2 | PL.002 | -101 | | PS.base.ta2
+ datanode_2 | PL.003 | -102 | | PS.base.ta3
+ datanode_1 | PL.004 | -103 | | PS.base.ta5
+ datanode_1 | PL.005 | -104 | | PS.base.ta6
+ datanode_2 | PL.006 | -106 | | PS.base.tb2
+ datanode_2 | PL.007 | -108 | | PS.base.tb3
+ datanode_2 | PL.008 | -109 | | PS.base.tb4
+ datanode_2 | PL.009 | -121 | | PS.base.tb5
+ datanode_2 | PL.010 | -122 | | PS.base.tb6
+ datanode_1 | PL.011 | -122 | | PS.base.tb6
+ datanode_2 | PL.012 | -122 | | PS.base.tb6
+ datanode_1 | PL.013 | -122 | | PS.base.tb6
+ datanode_2 | PL.014 | -122 | | PS.base.tb6
+ datanode_2 | PL.015 | -134 | | PS.first.ta1
+ datanode_2 | PL.016 | -137 | | PS.first.ta3
+ datanode_2 | PL.017 | -139 | | PS.first.ta4
+ datanode_1 | PL.018 | -362 | | PS.first.tb1
+ datanode_2 | PL.019 | -363 | | PS.first.tb2
+ datanode_1 | PL.020 | -364 | | PS.first.tb3
+ datanode_1 | PL.021 | -365 | | PS.first.tb5
+ datanode_2 | PL.022 | -367 | | PS.first.tb6
+ datanode_2 | PL.023 | -367 | | PS.first.tb6
+ datanode_2 | PL.024 | -367 | | PS.first.tb6
+ datanode_2 | PL.025 | -367 | | PS.first.tb6
+ datanode_2 | PL.026 | -367 | | PS.first.tb6
+ datanode_1 | PL.027 | -367 | | PS.first.tb6
+ datanode_1 | PL.028 | -501 | Fax entrance | PS.base.ta2
+ datanode_1 | PL.029 | -502 | Fax first floor | PS.first.ta1
+(29 rows)
+
+FETCH FIRST xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.001 | -0 | Central call | PS.base.ta1
+(1 row)
+
+FETCH LAST xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+FETCH LAST xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034') order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+---------+----------------------
+ datanode_1 | PL.030 | -367 | | PS.first.tb6
+ datanode_1 | PL.031 | -367 | | PS.first.tb6
+ datanode_1 | PL.032 | -367 | | PS.first.tb6
+ datanode_2 | PL.033 | -367 | | PS.first.tb6
+ datanode_2 | PL.034 | -367 | | PS.first.tb6
+(5 rows)
+
+delete from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034');
+FETCH LAST xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+delete from xl_Pline where slotname in ('PL.029');
+FETCH LAST xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH PRIOR xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.028 | -501 | Fax entrance | PS.base.ta2
+(1 row)
+
+FETCH ABSOLUTE 5 xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.005 | -104 | | PS.base.ta6
+(1 row)
+
+FETCH BACKWARD 2 xl_scroll_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.004 | -103 | | PS.base.ta5
+ PL.003 | -102 | | PS.base.ta3
+(2 rows)
+
+DELETE FROM xl_Pline WHERE CURRENT OF xl_scroll_cursor;
+ERROR: WHERE CURRENT OF clause not yet supported
+COMMIT;
+--scroll cursor would be insensitive to updates happening to the table
+BEGIN;
+declare xl_scroll_cursor1 SCROLL CURSOR for select * from xl_Pline order by slotname desc;
+FETCH ALL FROM xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+ PL.028 | -501 | Fax entrance | PS.base.ta2
+ PL.027 | -367 | | PS.first.tb6
+ PL.026 | -367 | | PS.first.tb6
+ PL.025 | -367 | | PS.first.tb6
+ PL.024 | -367 | | PS.first.tb6
+ PL.023 | -367 | | PS.first.tb6
+ PL.022 | -367 | | PS.first.tb6
+ PL.021 | -365 | | PS.first.tb5
+ PL.020 | -364 | | PS.first.tb3
+ PL.019 | -363 | | PS.first.tb2
+ PL.018 | -362 | | PS.first.tb1
+ PL.017 | -139 | | PS.first.ta4
+ PL.016 | -137 | | PS.first.ta3
+ PL.015 | -134 | | PS.first.ta1
+ PL.014 | -122 | | PS.base.tb6
+ PL.013 | -122 | | PS.base.tb6
+ PL.012 | -122 | | PS.base.tb6
+ PL.011 | -122 | | PS.base.tb6
+ PL.010 | -122 | | PS.base.tb6
+ PL.009 | -121 | | PS.base.tb5
+ PL.008 | -109 | | PS.base.tb4
+ PL.007 | -108 | | PS.base.tb3
+ PL.006 | -106 | | PS.base.tb2
+ PL.005 | -104 | | PS.base.ta6
+ PL.004 | -103 | | PS.base.ta5
+ PL.003 | -102 | | PS.base.ta3
+ PL.002 | -101 | | PS.base.ta2
+ PL.001 | -0 | Central call | PS.base.ta1
+(29 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname desc;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.029 | -502 | Fax first floor | PS.first.ta1
+ datanode_1 | PL.028 | -501 | Fax entrance | PS.base.ta2
+ datanode_1 | PL.027 | -367 | | PS.first.tb6
+ datanode_2 | PL.026 | -367 | | PS.first.tb6
+ datanode_2 | PL.025 | -367 | | PS.first.tb6
+ datanode_2 | PL.024 | -367 | | PS.first.tb6
+ datanode_2 | PL.023 | -367 | | PS.first.tb6
+ datanode_2 | PL.022 | -367 | | PS.first.tb6
+ datanode_1 | PL.021 | -365 | | PS.first.tb5
+ datanode_1 | PL.020 | -364 | | PS.first.tb3
+ datanode_2 | PL.019 | -363 | | PS.first.tb2
+ datanode_1 | PL.018 | -362 | | PS.first.tb1
+ datanode_2 | PL.017 | -139 | | PS.first.ta4
+ datanode_2 | PL.016 | -137 | | PS.first.ta3
+ datanode_2 | PL.015 | -134 | | PS.first.ta1
+ datanode_2 | PL.014 | -122 | | PS.base.tb6
+ datanode_1 | PL.013 | -122 | | PS.base.tb6
+ datanode_2 | PL.012 | -122 | | PS.base.tb6
+ datanode_1 | PL.011 | -122 | | PS.base.tb6
+ datanode_2 | PL.010 | -122 | | PS.base.tb6
+ datanode_2 | PL.009 | -121 | | PS.base.tb5
+ datanode_2 | PL.008 | -109 | | PS.base.tb4
+ datanode_2 | PL.007 | -108 | | PS.base.tb3
+ datanode_2 | PL.006 | -106 | | PS.base.tb2
+ datanode_1 | PL.005 | -104 | | PS.base.ta6
+ datanode_1 | PL.004 | -103 | | PS.base.ta5
+ datanode_2 | PL.003 | -102 | | PS.base.ta3
+ datanode_2 | PL.002 | -101 | | PS.base.ta2
+ datanode_1 | PL.001 | -0 | Central call | PS.base.ta1
+(29 rows)
+
+FETCH FIRST xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+FETCH FIRST xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034') order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+---------+----------------------
+ datanode_1 | PL.030 | -367 | | PS.first.tb6
+ datanode_1 | PL.031 | -367 | | PS.first.tb6
+ datanode_1 | PL.032 | -367 | | PS.first.tb6
+ datanode_2 | PL.033 | -367 | | PS.first.tb6
+ datanode_2 | PL.034 | -367 | | PS.first.tb6
+(5 rows)
+
+delete from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034');
+FETCH FIRST xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+delete from xl_Pline where slotname in ('PL.029');
+FETCH FIRST xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+FETCH LAST xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.001 | -0 | Central call | PS.base.ta1
+(1 row)
+
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH PRIOR xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.002 | -101 | | PS.base.ta2
+(1 row)
+
+FETCH ABSOLUTE 5 xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.025 | -367 | | PS.first.tb6
+(1 row)
+
+FETCH BACKWARD 2 xl_scroll_cursor1;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.026 | -367 | | PS.first.tb6
+ PL.027 | -367 | | PS.first.tb6
+(2 rows)
+
+DELETE FROM xl_Pline WHERE CURRENT OF xl_scroll_cursor1;
+ERROR: WHERE CURRENT OF clause not yet supported
+COMMIT;
+--insensitive cursor would be insensitive to updates happening to the table
+BEGIN;
+declare xl_ins_cursor INSENSITIVE CURSOR for select * from xl_Pline order by slotname desc;
+FETCH FIRST xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(1 row)
+
+FETCH ABSOLUTE 5 xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.025 | -367 | | PS.first.tb6
+(1 row)
+
+update xl_Pline set phonenumber='-503' where slotname = 'PL.029';
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+FETCH FIRST xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.030 | -367 | | PS.first.tb6
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.029') order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.029 | -503 | Fax first floor | PS.first.ta1
+ datanode_1 | PL.030 | -367 | | PS.first.tb6
+(2 rows)
+
+delete from xl_Pline where slotname in ('PL.030');
+FETCH FIRST xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.029 | -503 | Fax first floor | PS.first.ta1
+(1 row)
+
+delete from xl_Pline where slotname in ('PL.029');
+FETCH FIRST xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.028 | -501 | Fax entrance | PS.base.ta2
+(1 row)
+
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH ALL FROM xl_ins_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.027 | -367 | | PS.first.tb6
+ PL.026 | -367 | | PS.first.tb6
+ PL.025 | -367 | | PS.first.tb6
+ PL.024 | -367 | | PS.first.tb6
+ PL.023 | -367 | | PS.first.tb6
+ PL.022 | -367 | | PS.first.tb6
+ PL.021 | -365 | | PS.first.tb5
+ PL.020 | -364 | | PS.first.tb3
+ PL.019 | -363 | | PS.first.tb2
+ PL.018 | -362 | | PS.first.tb1
+ PL.017 | -139 | | PS.first.ta4
+ PL.016 | -137 | | PS.first.ta3
+ PL.015 | -134 | | PS.first.ta1
+ PL.014 | -122 | | PS.base.tb6
+ PL.013 | -122 | | PS.base.tb6
+ PL.012 | -122 | | PS.base.tb6
+ PL.011 | -122 | | PS.base.tb6
+ PL.010 | -122 | | PS.base.tb6
+ PL.009 | -121 | | PS.base.tb5
+ PL.008 | -109 | | PS.base.tb4
+ PL.007 | -108 | | PS.base.tb3
+ PL.006 | -106 | | PS.base.tb2
+ PL.005 | -104 | | PS.base.ta6
+ PL.004 | -103 | | PS.base.ta5
+ PL.003 | -102 | | PS.base.ta3
+ PL.002 | -101 | | PS.base.ta2
+ PL.001 | -0 | Central call | PS.base.ta1
+(27 rows)
+
+DELETE FROM xl_Pline WHERE CURRENT OF xl_ins_cursor;
+ERROR: WHERE CURRENT OF clause not yet supported
+COMMIT;
+--with hold cursor wold be available after the transaction that successfully committed it is gone
+BEGIN;
+declare xl_with_hold_cursor CURSOR WITH HOLD for select * from xl_Pline order by slotname;
+FETCH FIRST xl_with_hold_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.001 | -0 | Central call | PS.base.ta1
+(1 row)
+
+FETCH ABSOLUTE 5 xl_with_hold_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+---------+----------------------
+ PL.005 | -104 | | PS.base.ta6
+(1 row)
+
+FETCH ALL FROM xl_with_hold_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+-----------------+----------------------
+ PL.006 | -106 | | PS.base.tb2
+ PL.007 | -108 | | PS.base.tb3
+ PL.008 | -109 | | PS.base.tb4
+ PL.009 | -121 | | PS.base.tb5
+ PL.010 | -122 | | PS.base.tb6
+ PL.011 | -122 | | PS.base.tb6
+ PL.012 | -122 | | PS.base.tb6
+ PL.013 | -122 | | PS.base.tb6
+ PL.014 | -122 | | PS.base.tb6
+ PL.015 | -134 | | PS.first.ta1
+ PL.016 | -137 | | PS.first.ta3
+ PL.017 | -139 | | PS.first.ta4
+ PL.018 | -362 | | PS.first.tb1
+ PL.019 | -363 | | PS.first.tb2
+ PL.020 | -364 | | PS.first.tb3
+ PL.021 | -365 | | PS.first.tb5
+ PL.022 | -367 | | PS.first.tb6
+ PL.023 | -367 | | PS.first.tb6
+ PL.024 | -367 | | PS.first.tb6
+ PL.025 | -367 | | PS.first.tb6
+ PL.026 | -367 | | PS.first.tb6
+ PL.027 | -367 | | PS.first.tb6
+ PL.028 | -501 | Fax entrance | PS.base.ta2
+ PL.029 | -502 | Fax first floor | PS.first.ta1
+(24 rows)
+
+COMMIT;
+FETCH FIRST xl_with_hold_cursor;
+ slotname | phonenumber | comment | backlink
+----------------------+----------------------+--------------+----------------------
+ PL.001 | -0 | Central call | PS.base.ta1
+(1 row)
+
+--SAVEPOINTs are not supported
+begin;
+ set constraints all deferred;
+ savepoint x;
+ERROR: SAVEPOINT is not yet supported.
+ set constraints all immediate; -- fails
+ERROR: current transaction is aborted, commands ignored until end of transaction block
+ rollback to x;
+ERROR: no such savepoint
+commit; -- still fails
+--User defined functions have several limitations
+--Basic insert, update, delete test on multiple datanodes using plpgsql function is passing.
+create function xl_insert_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.035', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.036', '-367', '', 'PS.first.tb6');
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+select xl_insert_Pline_test(1);
+ xl_insert_pline_test
+----------------------
+ t
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.001 | -0 | Central call | PS.base.ta1
+ datanode_2 | PL.002 | -101 | | PS.base.ta2
+ datanode_2 | PL.003 | -102 | | PS.base.ta3
+ datanode_1 | PL.004 | -103 | | PS.base.ta5
+ datanode_1 | PL.005 | -104 | | PS.base.ta6
+ datanode_2 | PL.006 | -106 | | PS.base.tb2
+ datanode_2 | PL.007 | -108 | | PS.base.tb3
+ datanode_2 | PL.008 | -109 | | PS.base.tb4
+ datanode_2 | PL.009 | -121 | | PS.base.tb5
+ datanode_2 | PL.010 | -122 | | PS.base.tb6
+ datanode_1 | PL.011 | -122 | | PS.base.tb6
+ datanode_2 | PL.012 | -122 | | PS.base.tb6
+ datanode_1 | PL.013 | -122 | | PS.base.tb6
+ datanode_2 | PL.014 | -122 | | PS.base.tb6
+ datanode_2 | PL.015 | -134 | | PS.first.ta1
+ datanode_2 | PL.016 | -137 | | PS.first.ta3
+ datanode_2 | PL.017 | -139 | | PS.first.ta4
+ datanode_1 | PL.018 | -362 | | PS.first.tb1
+ datanode_2 | PL.019 | -363 | | PS.first.tb2
+ datanode_1 | PL.020 | -364 | | PS.first.tb3
+ datanode_1 | PL.021 | -365 | | PS.first.tb5
+ datanode_2 | PL.022 | -367 | | PS.first.tb6
+ datanode_2 | PL.023 | -367 | | PS.first.tb6
+ datanode_2 | PL.024 | -367 | | PS.first.tb6
+ datanode_2 | PL.025 | -367 | | PS.first.tb6
+ datanode_2 | PL.026 | -367 | | PS.first.tb6
+ datanode_1 | PL.027 | -367 | | PS.first.tb6
+ datanode_1 | PL.028 | -501 | Fax entrance | PS.base.ta2
+ datanode_1 | PL.029 | -502 | Fax first floor | PS.first.ta1
+ datanode_1 | PL.030 | -367 | | PS.first.tb6
+ datanode_1 | PL.031 | -367 | | PS.first.tb6
+ datanode_1 | PL.032 | -367 | | PS.first.tb6
+ datanode_2 | PL.033 | -367 | | PS.first.tb6
+ datanode_2 | PL.034 | -367 | | PS.first.tb6
+ datanode_1 | PL.035 | -367 | | PS.first.tb6
+ datanode_1 | PL.036 | -367 | | PS.first.tb6
+(36 rows)
+
+create function xl_update_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.030';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.031';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.032';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.033';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.034';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.035';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.036';
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+select xl_update_Pline_test(1);
+ xl_update_pline_test
+----------------------
+ t
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.001 | -0 | Central call | PS.base.ta1
+ datanode_2 | PL.002 | -101 | | PS.base.ta2
+ datanode_2 | PL.003 | -102 | | PS.base.ta3
+ datanode_1 | PL.004 | -103 | | PS.base.ta5
+ datanode_1 | PL.005 | -104 | | PS.base.ta6
+ datanode_2 | PL.006 | -106 | | PS.base.tb2
+ datanode_2 | PL.007 | -108 | | PS.base.tb3
+ datanode_2 | PL.008 | -109 | | PS.base.tb4
+ datanode_2 | PL.009 | -121 | | PS.base.tb5
+ datanode_2 | PL.010 | -122 | | PS.base.tb6
+ datanode_1 | PL.011 | -122 | | PS.base.tb6
+ datanode_2 | PL.012 | -122 | | PS.base.tb6
+ datanode_1 | PL.013 | -122 | | PS.base.tb6
+ datanode_2 | PL.014 | -122 | | PS.base.tb6
+ datanode_2 | PL.015 | -134 | | PS.first.ta1
+ datanode_2 | PL.016 | -137 | | PS.first.ta3
+ datanode_2 | PL.017 | -139 | | PS.first.ta4
+ datanode_1 | PL.018 | -362 | | PS.first.tb1
+ datanode_2 | PL.019 | -363 | | PS.first.tb2
+ datanode_1 | PL.020 | -364 | | PS.first.tb3
+ datanode_1 | PL.021 | -365 | | PS.first.tb5
+ datanode_2 | PL.022 | -367 | | PS.first.tb6
+ datanode_2 | PL.023 | -367 | | PS.first.tb6
+ datanode_2 | PL.024 | -367 | | PS.first.tb6
+ datanode_2 | PL.025 | -367 | | PS.first.tb6
+ datanode_2 | PL.026 | -367 | | PS.first.tb6
+ datanode_1 | PL.027 | -367 | | PS.first.tb6
+ datanode_1 | PL.028 | -501 | Fax entrance | PS.base.ta2
+ datanode_1 | PL.029 | -502 | Fax first floor | PS.first.ta1
+ datanode_1 | PL.030 | 400 | | PS.first.tb6
+ datanode_1 | PL.031 | 400 | | PS.first.tb6
+ datanode_1 | PL.032 | 400 | | PS.first.tb6
+ datanode_2 | PL.033 | 400 | | PS.first.tb6
+ datanode_2 | PL.034 | 400 | | PS.first.tb6
+ datanode_1 | PL.035 | 400 | | PS.first.tb6
+ datanode_1 | PL.036 | 400 | | PS.first.tb6
+(36 rows)
+
+create function xl_delete_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ delete from xl_Pline where slotname = 'PL.030';
+ delete from xl_Pline where slotname = 'PL.031';
+ delete from xl_Pline where slotname = 'PL.032';
+ delete from xl_Pline where slotname = 'PL.033';
+ delete from xl_Pline where slotname = 'PL.034';
+ delete from xl_Pline where slotname = 'PL.035';
+ delete from xl_Pline where slotname = 'PL.036';
+
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+select xl_delete_Pline_test(1);
+ xl_delete_pline_test
+----------------------
+ t
+(1 row)
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+ xl_nodename_from_id | slotname | phonenumber | comment | backlink
+---------------------+----------------------+----------------------+-----------------+----------------------
+ datanode_1 | PL.001 | -0 | Central call | PS.base.ta1
+ datanode_2 | PL.002 | -101 | | PS.base.ta2
+ datanode_2 | PL.003 | -102 | | PS.base.ta3
+ datanode_1 | PL.004 | -103 | | PS.base.ta5
+ datanode_1 | PL.005 | -104 | | PS.base.ta6
+ datanode_2 | PL.006 | -106 | | PS.base.tb2
+ datanode_2 | PL.007 | -108 | | PS.base.tb3
+ datanode_2 | PL.008 | -109 | | PS.base.tb4
+ datanode_2 | PL.009 | -121 | | PS.base.tb5
+ datanode_2 | PL.010 | -122 | | PS.base.tb6
+ datanode_1 | PL.011 | -122 | | PS.base.tb6
+ datanode_2 | PL.012 | -122 | | PS.base.tb6
+ datanode_1 | PL.013 | -122 | | PS.base.tb6
+ datanode_2 | PL.014 | -122 | | PS.base.tb6
+ datanode_2 | PL.015 | -134 | | PS.first.ta1
+ datanode_2 | PL.016 | -137 | | PS.first.ta3
+ datanode_2 | PL.017 | -139 | | PS.first.ta4
+ datanode_1 | PL.018 | -362 | | PS.first.tb1
+ datanode_2 | PL.019 | -363 | | PS.first.tb2
+ datanode_1 | PL.020 | -364 | | PS.first.tb3
+ datanode_1 | PL.021 | -365 | | PS.first.tb5
+ datanode_2 | PL.022 | -367 | | PS.first.tb6
+ datanode_2 | PL.023 | -367 | | PS.first.tb6
+ datanode_2 | PL.024 | -367 | | PS.first.tb6
+ datanode_2 | PL.025 | -367 | | PS.first.tb6
+ datanode_2 | PL.026 | -367 | | PS.first.tb6
+ datanode_1 | PL.027 | -367 | | PS.first.tb6
+ datanode_1 | PL.028 | -501 | Fax entrance | PS.base.ta2
+ datanode_1 | PL.029 | -502 | Fax first floor | PS.first.ta1
+(29 rows)
+
+--Correlated UPDATE/DELETE is not supported.
+-- distributed by default ==> xl_t by HASH(no), xl_t1 by HASH(no1)
+CREATE TABLE xl_t("no" integer,"name" character varying);
+CREATE TABLE xl_t1(no1 integer,name1 character varying);
+create table xl_names("name" character varying, "name1" character varying);
+INSERT INTO xl_t("no", "name")VALUES (1, 'A');
+INSERT INTO xl_t("no", "name")VALUES (2, 'B');
+INSERT INTO xl_t("no", "name")VALUES (3, 'C');
+INSERT INTO xl_t("no", "name")VALUES (4, 'D');
+INSERT INTO xl_t1("no1", "name1")VALUES (1, 'Z');
+INSERT INTO xl_t1("no1", "name1")VALUES (2, 'Y');
+INSERT INTO xl_t1("no1", "name1")VALUES (3, 'X');
+INSERT INTO xl_t1("no1", "name1")VALUES (4, 'W');
+INSERT INTO xl_names("name", "name1")VALUES ('A', 'A1');
+INSERT INTO xl_names("name", "name1")VALUES ('B', 'B1');
+INSERT INTO xl_names("name", "name1")VALUES ('C', 'C1');
+INSERT INTO xl_names("name", "name1")VALUES ('D', 'D1');
+INSERT INTO xl_names("name", "name1")VALUES ('W', 'W1');
+INSERT INTO xl_names("name", "name1")VALUES ('X', 'X1');
+INSERT INTO xl_names("name", "name1")VALUES ('Y', 'Y1');
+INSERT INTO xl_names("name", "name1")VALUES ('Z', 'Z1');
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+ xl_nodename_from_id | no | name
+---------------------+----+------
+ datanode_1 | 1 | A
+ datanode_1 | 2 | B
+ datanode_2 | 3 | C
+ datanode_2 | 4 | D
+(4 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+ xl_nodename_from_id | no1 | name1
+---------------------+-----+-------
+ datanode_1 | 1 | Z
+ datanode_1 | 2 | Y
+ datanode_2 | 3 | X
+ datanode_2 | 4 | W
+(4 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_names order by name;
+ xl_nodename_from_id | name | name1
+---------------------+------+-------
+ datanode_1 | A | A1
+ datanode_2 | B | B1
+ datanode_1 | C | C1
+ datanode_1 | D | D1
+ datanode_1 | W | W1
+ datanode_1 | X | X1
+ datanode_1 | Y | Y1
+ datanode_2 | Z | Z1
+(8 rows)
+
+update xl_t set name = T1.name1
+from (select no1,name1 from xl_t1) T1
+where xl_t.no = T1.no1;
+--correlated update fails
+update xl_t1 set name1 = T1.name1
+from (select name,name1 from xl_names) T1
+where xl_t1.name1 = T1.name;
+ERROR: could not plan this distributed update
+DETAIL: correlated UPDATE or updating distribution column currently not supported in Postgres-XL.
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+ xl_nodename_from_id | no | name
+---------------------+----+------
+ datanode_1 | 1 | Z
+ datanode_1 | 2 | Y
+ datanode_2 | 3 | X
+ datanode_2 | 4 | W
+(4 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+ xl_nodename_from_id | no1 | name1
+---------------------+-----+-------
+ datanode_1 | 1 | Z
+ datanode_1 | 2 | Y
+ datanode_2 | 3 | X
+ datanode_2 | 4 | W
+(4 rows)
+
+--testing correlated delete:
+delete from xl_t
+where xl_t.no in (select no1 from xl_t1 where name1 in ('Z', 'X'))
+;
+--correlated delete fails
+delete from xl_t1
+where xl_t1.name1 in (select name1 from xl_names where name in ('Z', 'X'))
+;
+ERROR: could not plan this distributed delete
+DETAIL: correlated or complex DELETE is currently not supported in Postgres-XL.
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+ xl_nodename_from_id | no | name
+---------------------+----+------
+ datanode_1 | 2 | Y
+ datanode_2 | 4 | W
+(2 rows)
+
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+ xl_nodename_from_id | no1 | name1
+---------------------+-----+-------
+ datanode_1 | 1 | Z
+ datanode_1 | 2 | Y
+ datanode_2 | 3 | X
+ datanode_2 | 4 | W
+(4 rows)
+
+drop table xl_t;
+drop table xl_t1;
+drop table xl_names;
+--EXCLUSION CONSTRAINTS are not supported
+--The constraint is enforced when both rows map to the same datanode. But if they go into different datanodes, the constraint is not enforced
+CREATE TABLE xl_circles (
+ c circle,
+ EXCLUDE USING gist (c WITH &&)
+);
+CREATE TABLE xl_cons_hash (a int, c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY HASH(a);
+CREATE TABLE xl_cons_modulo (a int, c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY MODULO(a); error
+CREATE TABLE xl_cons_rr (c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY ROUNDROBIN;
+ERROR: syntax error at or near "error"
+LINE 1: error
+ ^
+CREATE TABLE xl_cons_hash2 (a int, b int, c circle, EXCLUDE USING btree (a WITH = , b WITH =)) DISTRIBUTE BY HASH(a);
+CREATE TABLE xl_cons_modulo2 (a int, b int, c circle, EXCLUDE USING btree (a WITH =, b WITH =)) DISTRIBUTE BY MODULO(a);
+-- xl_test1 is distributed by default on HASH(a)
+CREATE TABLE xl_test1 (a int, b int);
+INSERT INTO xl_test1 VALUES (1,2);
+INSERT INTO xl_test1 VALUES (2,2);
+INSERT INTO xl_test1 VALUES (3,2);
+INSERT INTO xl_test1 VALUES (4,2);
+INSERT INTO xl_test1 VALUES (5,2);
+INSERT INTO xl_test1 VALUES (6,2);
+INSERT INTO xl_test1 VALUES (7,2);
+select xl_nodename_from_id(xc_node_id),* from xl_test1 order by a;
+ xl_nodename_from_id | a | b
+---------------------+---+---
+ datanode_1 | 1 | 2
+ datanode_1 | 2 | 2
+ datanode_2 | 3 | 2
+ datanode_2 | 4 | 2
+ datanode_1 | 5 | 2
+ datanode_1 | 6 | 2
+ datanode_2 | 7 | 2
+(7 rows)
+
+-- this is to see how hash of integers key distributes among data nodes.
+-- xl_test is distributed by default on HASH(a)
+CREATE TABLE xl_test (a int, b int, EXCLUDE USING btree (b WITH =));
+INSERT INTO xl_test VALUES (1,2);
+INSERT INTO xl_test VALUES (2,2);
+ERROR: conflicting key value violates exclusion constraint "xl_test_b_excl"
+DETAIL: Key (b)=(2) conflicts with existing key (b)=(2).
+INSERT INTO xl_test VALUES (3,2);
+INSERT INTO xl_test VALUES (4,2);
+ERROR: conflicting key value violates exclusion constraint "xl_test_b_excl"
+DETAIL: Key (b)=(2) conflicts with existing key (b)=(2).
+INSERT INTO xl_test VALUES (5,2);
+ERROR: conflicting key value violates exclusion constraint "xl_test_b_excl"
+DETAIL: Key (b)=(2) conflicts with existing key (b)=(2).
+INSERT INTO xl_test VALUES (6,2);
+ERROR: conflicting key value violates exclusion constraint "xl_test_b_excl"
+DETAIL: Key (b)=(2) conflicts with existing key (b)=(2).
+INSERT INTO xl_test VALUES (7,2);
+ERROR: conflicting key value violates exclusion constraint "xl_test_b_excl"
+DETAIL: Key (b)=(2) conflicts with existing key (b)=(2).
+--the constraint is enforced when both rows map to the same datanode, e.g. when a=1, a=2
+--But if they go into different datanodes, the constraint is not enforced, e.g. when a=3
+drop table xl_circles;
+drop table xl_cons_hash;
+drop table xl_cons_modulo;
+drop table xl_cons_rr;
+ERROR: table "xl_cons_rr" does not exist
+drop table xl_test;
+drop table xl_test1;
+drop table xl_Room;
+drop table xl_WSlot;
+drop table xl_PLine;
+-- CREATE INDEX CONCURRENTLY is not supported
+--
+-- Try some concurrent index builds
+--
+-- Unfortunately this only tests about half the code paths because there are
+-- no concurrent updates happening to the table at the same time.
+CREATE TABLE xl_concur_heap (f1 text, f2 text);
+-- empty table
+CREATE INDEX CONCURRENTLY xl_concur_index1 ON xl_concur_heap(f2,f1);
+ERROR: PGXC does not support concurrent INDEX yet
+DETAIL: The feature is not currently supported
+CREATE INDEX CONCURRENTLY IF NOT EXISTS xl_concur_index1 ON xl_concur_heap(f2,f1);
+ERROR: PGXC does not support concurrent INDEX yet
+DETAIL: The feature is not currently supported
+INSERT INTO xl_concur_heap VALUES ('a','b');
+INSERT INTO xl_concur_heap VALUES ('b','b');
+drop index concurrently xl_concur_index1;
+ERROR: index "xl_concur_index1" does not exist
+drop table xl_concur_heap;
+--Large objects are not supported
+CREATE TABLE lotest_stash_values (loid oid, junk integer, fd integer);
+-- lo_creat(mode integer) returns oid
+-- The mode arg to lo_creat is unused, some vestigal holdover from ancient times
+-- returns the large object id
+INSERT INTO lotest_stash_values (loid) VALUES( lo_creat(42) );
+ERROR: Postgres-XL does not yet support large objects
+DETAIL: The feature is not currently supported
+drop table lotest_stash_values;
+--EVENT TRIGGERs are not supported
+CREATE FUNCTION xl_event_trigger_for_drops()
+ RETURNS event_trigger LANGUAGE plpgsql AS $$
+DECLARE
+ obj record;
+BEGIN
+ FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
+ LOOP
+ RAISE NOTICE '% dropped object: % %.% %',
+ tg_tag,
+ obj.object_type,
+ obj.schema_name,
+ obj.object_name,
+ obj.object_identity;
+ END LOOP;
+END
+$$;
+CREATE EVENT TRIGGER xl_event_trigger_for_drops
+ ON sql_drop
+ EXECUTE PROCEDURE xl_event_trigger_for_drops();
+ERROR: EVENT TRIGGER not yet supported in Postgres-XL
+drop function xl_event_trigger_for_drops();
+drop EVENT TRIGGER xl_event_trigger_for_drops;
+ERROR: event trigger "xl_event_trigger_for_drops" does not exist
+--Recursive queries are not supported
+WITH RECURSIVE t(n) AS (
+ VALUES (1)
+ UNION ALL
+ SELECT n+1 FROM t WHERE n < 100
+)
+SELECT sum(n) FROM t;
+ERROR: WITH RECURSIVE currently not supported on distributed tables.
+--FDWs are not supported
+CREATE FOREIGN DATA WRAPPER xl_foo; -- ERROR
+ERROR: Postgres-XL does not support FOREIGN DATA WRAPPER yet
+DETAIL: The feature is not currently supported
+RESET ROLE;
+CREATE FOREIGN DATA WRAPPER xl_foo VALIDATOR postgresql_fdw_validator;
+ERROR: Postgres-XL does not support FOREIGN DATA WRAPPER yet
+DETAIL: The feature is not currently supported
+--LISTEN/NOTIFY is not supported. Looks like they are supported now.
+--We would obviously have issues with LISTEN/NOTIFY if clients are connected to different coordinators. Need to test that manually as it is difficult via regression.
+--Should work. Send a valid message via a valid channel name
+--LISTEN notify_async1;
+-- commenting LISTEN as PIDs shown here would never match in regression.
+SELECT pg_notify('notify_async1','sample message1');
+ pg_notify
+-----------
+
+(1 row)
+
+SELECT pg_notify('notify_async1','');
+ pg_notify
+-----------
+
+(1 row)
+
+SELECT pg_notify('notify_async1',NULL);
+ pg_notify
+-----------
+
+(1 row)
+
+-- Should fail. Send a valid message via an invalid channel name
+SELECT pg_notify('','sample message1');
+ERROR: channel name cannot be empty
+SELECT pg_notify(NULL,'sample message1');
+ERROR: channel name cannot be empty
+SELECT pg_notify('notify_async_channel_name_too_long______________________________','sample_message1');
+ERROR: channel name too long
+--Should work. Valid NOTIFY/LISTEN/UNLISTEN commands
+NOTIFY notify_async2;
+LISTEN notify_async2;
+UNLISTEN notify_async2;
+UNLISTEN *;
+--LISTEN virtual;
+NOTIFY virtual;
+NOTIFY virtual, 'This is the payload';
+--LISTEN foo;
+SELECT pg_notify('fo' || 'o', 'pay' || 'load');
+ pg_notify
+-----------
+
+(1 row)
+
+drop function xl_room_au();
+drop function xl_trap_zero_divide(int);
+drop function xl_nodename_from_id(integer);
+drop function xl_insert_Pline_test(int);
+drop function xl_update_Pline_test(int);
+drop function xl_delete_Pline_test(int);
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 33a6dddec9..949d5dbeeb 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -183,3 +183,4 @@ test: xl_alter_table
test: xl_distribution_column_types_modulo
test: xl_plan_pushdown
test: xl_functions
+test: xl_plpgsql
diff --git a/src/test/regress/sql/xl_alter_table.sql b/src/test/regress/sql/xl_alter_table.sql
index 4fc2948e90..c056227760 100644..100755
--- a/src/test/regress/sql/xl_alter_table.sql
+++ b/src/test/regress/sql/xl_alter_table.sql
@@ -124,9 +124,9 @@ ALTER TABLE xl_at2h RENAME COLUMN product_id TO product_identifier;
ALTER TABLE xl_at2h RENAME TO xl_at3h;
-ALTER TABLE xl_at3h DELETE NODE (datanode2);
+ALTER TABLE xl_at3h DELETE NODE (datanode_2);
-ALTER TABLE xl_at3h ADD NODE (datanode2);
+ALTER TABLE xl_at3h ADD NODE (datanode_2);
ALTER TABLE xl_at3h DISTRIBUTE BY REPLICATION;
@@ -168,9 +168,9 @@ ALTER TABLE xl_at2m RENAME COLUMN product_id TO product_identifier;
ALTER TABLE xl_at2m RENAME TO xl_at3m;
-ALTER TABLE xl_at3m DELETE NODE (datanode2);
+ALTER TABLE xl_at3m DELETE NODE (datanode_2);
-ALTER TABLE xl_at3m ADD NODE (datanode2);
+ALTER TABLE xl_at3m ADD NODE (datanode_2);
ALTER TABLE xl_at3m DROP COLUMN product_identifier;--fail - distribution column cannot be dropped.
diff --git a/src/test/regress/sql/xl_plpgsql.sql b/src/test/regress/sql/xl_plpgsql.sql
new file mode 100755
index 0000000000..352354ea83
--- /dev/null
+++ b/src/test/regress/sql/xl_plpgsql.sql
@@ -0,0 +1,545 @@
+
+--User defined functions have several limitations
+--
+-- PLPGSQL
+
+-- Table xl_room default distributed by Hash(roomno) on all nodes.
+create table xl_Room (
+ roomno char(8),
+ comment text
+);
+
+create unique index xl_Room_rno on xl_Room using btree (roomno bpchar_ops);
+
+-- Table xl_wslot default distributed by Hash(slotname) on all nodes.
+create table xl_WSlot (
+ slotname char(20),
+ roomno char(8),
+ slotlink char(20),
+ backlink char(20)
+);
+
+create unique index xl_WSlot_name on xl_WSlot using btree (slotname bpchar_ops);
+
+--default distributed by HASH(slotname)
+create table xl_PLine (
+ slotname char(20),
+ phonenumber char(20),
+ comment text,
+ backlink char(20)
+);
+
+create unique index xl_PLine_name on xl_PLine using btree (slotname bpchar_ops);
+
+
+-- ************************************************************
+-- *
+-- * Trigger procedures and functions for the patchfield
+-- * test of PL/pgSQL
+-- *
+-- ************************************************************
+
+
+-- ************************************************************
+-- * AFTER UPDATE on Room
+-- * - If room no changes let wall slots follow
+-- ************************************************************
+create function xl_room_au() returns trigger as '
+begin
+ if new.roomno != old.roomno then
+ update xl_WSlot set roomno = new.roomno where roomno = old.roomno;
+ end if;
+ return new;
+end;
+' language plpgsql;
+
+--BEFORE/AFTER TRIGGERs are not supported in Postgres-XL - below would fail
+
+create trigger tg_room_bu before update
+ on xl_Room for each row execute procedure xl_room_au();
+
+create trigger xl_room_au after update
+ on xl_Room for each row execute procedure xl_room_au();
+
+
+--
+-- Test error trapping
+--
+--Internal subtransactions (exception clause within a function)
+-- calling below function would fail.
+create function xl_trap_zero_divide(int) returns int as $$
+declare x int;
+ sx smallint;
+begin
+ begin -- start a subtransaction
+ raise notice 'should see this';
+ x := 100 / $1;
+ raise notice 'should see this only if % <> 0', $1;
+ sx := $1;
+ raise notice 'should see this only if % fits in smallint', $1;
+ if $1 < 0 then
+ raise exception '% is less than zero', $1;
+ end if;
+ exception
+ when division_by_zero then
+ raise notice 'caught division_by_zero';
+ x := -1;
+ when NUMERIC_VALUE_OUT_OF_RANGE then
+ raise notice 'caught numeric_value_out_of_range';
+ x := -2;
+ end;
+ return x;
+end$$ language plpgsql;
+
+select xl_trap_zero_divide(50);
+
+
+--SERIALIZABLE TRANSACTIONs are not supported. Isolation level SERIALIZABLE is converted to REPEATABLE READ internally silently.
+
+-- ALTER OPERATOR FAMILY ... ADD/DROP
+
+-- Should work. Textbook case of CREATE / ALTER ADD / ALTER DROP / DROP
+BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+CREATE OPERATOR FAMILY alt_opf4 USING btree;
+ALTER OPERATOR FAMILY alt_opf4 USING btree ADD
+ -- int4 vs int2
+ OPERATOR 1 < (int4, int2) ,
+ OPERATOR 2 <= (int4, int2) ,
+ OPERATOR 3 = (int4, int2) ,
+ OPERATOR 4 >= (int4, int2) ,
+ OPERATOR 5 > (int4, int2) ,
+ FUNCTION 1 btint42cmp(int4, int2);
+
+ALTER OPERATOR FAMILY alt_opf4 USING btree DROP
+ -- int4 vs int2
+ OPERATOR 1 (int4, int2) ,
+ OPERATOR 2 (int4, int2) ,
+ OPERATOR 3 (int4, int2) ,
+ OPERATOR 4 (int4, int2) ,
+ OPERATOR 5 (int4, int2) ,
+ FUNCTION 1 (int4, int2) ;
+DROP OPERATOR FAMILY alt_opf4 USING btree;
+ROLLBACK;
+
+create function xl_nodename_from_id(integer) returns name as $$
+declare
+ n name;
+BEGIN
+ select node_name into n from pgxc_node where node_id = $1;
+ RETURN n;
+END;$$ language plpgsql;
+
+--insert Plines
+insert into xl_PLine values ('PL.001', '-0', 'Central call', 'PS.base.ta1');
+insert into xl_PLine values ('PL.002', '-101', '', 'PS.base.ta2');
+insert into xl_PLine values ('PL.003', '-102', '', 'PS.base.ta3');
+insert into xl_PLine values ('PL.004', '-103', '', 'PS.base.ta5');
+insert into xl_PLine values ('PL.005', '-104', '', 'PS.base.ta6');
+insert into xl_PLine values ('PL.006', '-106', '', 'PS.base.tb2');
+insert into xl_PLine values ('PL.007', '-108', '', 'PS.base.tb3');
+insert into xl_PLine values ('PL.008', '-109', '', 'PS.base.tb4');
+insert into xl_PLine values ('PL.009', '-121', '', 'PS.base.tb5');
+insert into xl_PLine values ('PL.010', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.011', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.012', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.013', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.014', '-122', '', 'PS.base.tb6');
+insert into xl_PLine values ('PL.015', '-134', '', 'PS.first.ta1');
+insert into xl_PLine values ('PL.016', '-137', '', 'PS.first.ta3');
+insert into xl_PLine values ('PL.017', '-139', '', 'PS.first.ta4');
+insert into xl_PLine values ('PL.018', '-362', '', 'PS.first.tb1');
+insert into xl_PLine values ('PL.019', '-363', '', 'PS.first.tb2');
+insert into xl_PLine values ('PL.020', '-364', '', 'PS.first.tb3');
+insert into xl_PLine values ('PL.021', '-365', '', 'PS.first.tb5');
+insert into xl_PLine values ('PL.022', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.023', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.024', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.025', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.026', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.027', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.028', '-501', 'Fax entrance', 'PS.base.ta2');
+insert into xl_PLine values ('PL.029', '-502', 'Fax first floor', 'PS.first.ta1');
+
+
+--INSENSITIVE/SCROLL/WITH HOLD cursors are not supported
+-- if INSENSITIVE is not allowed then what is the default for Postgres-XL for cursor ?
+
+-- May also check over here - FETCH and WHERE CURRENT OF conditions
+-- WHERE CURRENT OF is not supported
+--Many forms of FETCH are not supported such as those involving PRIOR, FIRST, LAST, ABSOLUTE, BACKWARD
+--Basic test with data spannig on multiple nodes is working fine.
+--scroll cursor would be insensitive to updates happening to the table
+BEGIN;
+
+declare xl_scroll_cursor SCROLL CURSOR for select * from xl_Pline order by slotname;
+
+FETCH ALL FROM xl_scroll_cursor;
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+FETCH FIRST xl_scroll_cursor;
+FETCH LAST xl_scroll_cursor;
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+FETCH LAST xl_scroll_cursor;
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034') order by slotname;
+delete from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034');
+FETCH LAST xl_scroll_cursor;
+delete from xl_Pline where slotname in ('PL.029');
+FETCH LAST xl_scroll_cursor;
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH PRIOR xl_scroll_cursor;
+FETCH ABSOLUTE 5 xl_scroll_cursor;
+FETCH BACKWARD 2 xl_scroll_cursor;
+DELETE FROM xl_Pline WHERE CURRENT OF xl_scroll_cursor;
+COMMIT;
+
+
+--scroll cursor would be insensitive to updates happening to the table
+BEGIN;
+
+declare xl_scroll_cursor1 SCROLL CURSOR for select * from xl_Pline order by slotname desc;
+
+FETCH ALL FROM xl_scroll_cursor1;
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname desc;
+FETCH FIRST xl_scroll_cursor1;
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+FETCH FIRST xl_scroll_cursor1;
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034') order by slotname;
+delete from xl_Pline where slotname in ('PL.030', 'PL.031', 'PL.032','PL.033', 'PL.034');
+FETCH FIRST xl_scroll_cursor1;
+delete from xl_Pline where slotname in ('PL.029');
+FETCH FIRST xl_scroll_cursor1;
+FETCH LAST xl_scroll_cursor1;
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH PRIOR xl_scroll_cursor1;
+FETCH ABSOLUTE 5 xl_scroll_cursor1;
+FETCH BACKWARD 2 xl_scroll_cursor1;
+DELETE FROM xl_Pline WHERE CURRENT OF xl_scroll_cursor1;
+COMMIT;
+
+--insensitive cursor would be insensitive to updates happening to the table
+BEGIN;
+declare xl_ins_cursor INSENSITIVE CURSOR for select * from xl_Pline order by slotname desc;
+
+FETCH FIRST xl_ins_cursor;
+FETCH ABSOLUTE 5 xl_ins_cursor;
+update xl_Pline set phonenumber='-503' where slotname = 'PL.029';
+insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+FETCH FIRST xl_ins_cursor;
+select xl_nodename_from_id(xc_node_id), * from xl_Pline where slotname in ('PL.030', 'PL.029') order by slotname;
+delete from xl_Pline where slotname in ('PL.030');
+FETCH FIRST xl_ins_cursor;
+delete from xl_Pline where slotname in ('PL.029');
+FETCH FIRST xl_ins_cursor;
+insert into xl_PLine values ('PL.029', '-367', '', 'PS.first.tb6');
+FETCH ALL FROM xl_ins_cursor;
+DELETE FROM xl_Pline WHERE CURRENT OF xl_ins_cursor;
+COMMIT;
+
+--with hold cursor wold be available after the transaction that successfully committed it is gone
+BEGIN;
+
+declare xl_with_hold_cursor CURSOR WITH HOLD for select * from xl_Pline order by slotname;
+
+FETCH FIRST xl_with_hold_cursor;
+FETCH ABSOLUTE 5 xl_with_hold_cursor;
+FETCH ALL FROM xl_with_hold_cursor;
+COMMIT;
+FETCH FIRST xl_with_hold_cursor;
+
+--SAVEPOINTs are not supported
+begin;
+ set constraints all deferred;
+ savepoint x;
+ set constraints all immediate; -- fails
+ rollback to x;
+commit; -- still fails
+
+--User defined functions have several limitations
+--Basic insert, update, delete test on multiple datanodes using plpgsql function is passing.
+create function xl_insert_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ insert into xl_PLine values ('PL.030', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.031', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.032', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.033', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.034', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.035', '-367', '', 'PS.first.tb6');
+ insert into xl_PLine values ('PL.036', '-367', '', 'PS.first.tb6');
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+
+select xl_insert_Pline_test(1);
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+
+
+create function xl_update_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.030';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.031';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.032';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.033';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.034';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.035';
+ update xl_Pline set phonenumber = '400' where slotname = 'PL.036';
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+
+select xl_update_Pline_test(1);
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+
+create function xl_delete_Pline_test(int) returns boolean as $$
+BEGIN
+ IF $1 < 20 THEN
+ delete from xl_Pline where slotname = 'PL.030';
+ delete from xl_Pline where slotname = 'PL.031';
+ delete from xl_Pline where slotname = 'PL.032';
+ delete from xl_Pline where slotname = 'PL.033';
+ delete from xl_Pline where slotname = 'PL.034';
+ delete from xl_Pline where slotname = 'PL.035';
+ delete from xl_Pline where slotname = 'PL.036';
+
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+END;$$ language plpgsql;
+
+select xl_delete_Pline_test(1);
+
+select xl_nodename_from_id(xc_node_id), * from xl_Pline order by slotname;
+
+
+--Correlated UPDATE/DELETE is not supported.
+-- distributed by default ==> xl_t by HASH(no), xl_t1 by HASH(no1)
+CREATE TABLE xl_t("no" integer,"name" character varying);
+CREATE TABLE xl_t1(no1 integer,name1 character varying);
+create table xl_names("name" character varying, "name1" character varying);
+
+INSERT INTO xl_t("no", "name")VALUES (1, 'A');
+INSERT INTO xl_t("no", "name")VALUES (2, 'B');
+INSERT INTO xl_t("no", "name")VALUES (3, 'C');
+INSERT INTO xl_t("no", "name")VALUES (4, 'D');
+
+INSERT INTO xl_t1("no1", "name1")VALUES (1, 'Z');
+INSERT INTO xl_t1("no1", "name1")VALUES (2, 'Y');
+INSERT INTO xl_t1("no1", "name1")VALUES (3, 'X');
+INSERT INTO xl_t1("no1", "name1")VALUES (4, 'W');
+
+INSERT INTO xl_names("name", "name1")VALUES ('A', 'A1');
+INSERT INTO xl_names("name", "name1")VALUES ('B', 'B1');
+INSERT INTO xl_names("name", "name1")VALUES ('C', 'C1');
+INSERT INTO xl_names("name", "name1")VALUES ('D', 'D1');
+INSERT INTO xl_names("name", "name1")VALUES ('W', 'W1');
+INSERT INTO xl_names("name", "name1")VALUES ('X', 'X1');
+INSERT INTO xl_names("name", "name1")VALUES ('Y', 'Y1');
+INSERT INTO xl_names("name", "name1")VALUES ('Z', 'Z1');
+
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+
+select xl_nodename_from_id(xc_node_id), * from xl_names order by name;
+
+update xl_t set name = T1.name1
+from (select no1,name1 from xl_t1) T1
+where xl_t.no = T1.no1;
+
+--correlated update fails
+update xl_t1 set name1 = T1.name1
+from (select name,name1 from xl_names) T1
+where xl_t1.name1 = T1.name;
+
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+
+--testing correlated delete:
+delete from xl_t
+where xl_t.no in (select no1 from xl_t1 where name1 in ('Z', 'X'))
+;
+
+--correlated delete fails
+delete from xl_t1
+where xl_t1.name1 in (select name1 from xl_names where name in ('Z', 'X'))
+;
+
+select xl_nodename_from_id(xc_node_id), * from xl_t;
+
+select xl_nodename_from_id(xc_node_id), * from xl_t1;
+
+drop table xl_t;
+drop table xl_t1;
+drop table xl_names;
+
+--EXCLUSION CONSTRAINTS are not supported
+--The constraint is enforced when both rows map to the same datanode. But if they go into different datanodes, the constraint is not enforced
+CREATE TABLE xl_circles (
+ c circle,
+ EXCLUDE USING gist (c WITH &&)
+);
+
+CREATE TABLE xl_cons_hash (a int, c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY HASH(a);
+CREATE TABLE xl_cons_modulo (a int, c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY MODULO(a); error
+CREATE TABLE xl_cons_rr (c circle, EXCLUDE USING gist (c WITH &&)) DISTRIBUTE BY ROUNDROBIN;
+CREATE TABLE xl_cons_hash2 (a int, b int, c circle, EXCLUDE USING btree (a WITH = , b WITH =)) DISTRIBUTE BY HASH(a);
+CREATE TABLE xl_cons_modulo2 (a int, b int, c circle, EXCLUDE USING btree (a WITH =, b WITH =)) DISTRIBUTE BY MODULO(a);
+
+-- xl_test1 is distributed by default on HASH(a)
+CREATE TABLE xl_test1 (a int, b int);
+INSERT INTO xl_test1 VALUES (1,2);
+INSERT INTO xl_test1 VALUES (2,2);
+INSERT INTO xl_test1 VALUES (3,2);
+INSERT INTO xl_test1 VALUES (4,2);
+INSERT INTO xl_test1 VALUES (5,2);
+INSERT INTO xl_test1 VALUES (6,2);
+INSERT INTO xl_test1 VALUES (7,2);
+
+select xl_nodename_from_id(xc_node_id),* from xl_test1 order by a;
+-- this is to see how hash of integers key distributes among data nodes.
+
+-- xl_test is distributed by default on HASH(a)
+CREATE TABLE xl_test (a int, b int, EXCLUDE USING btree (b WITH =));
+INSERT INTO xl_test VALUES (1,2);
+INSERT INTO xl_test VALUES (2,2);
+INSERT INTO xl_test VALUES (3,2);
+INSERT INTO xl_test VALUES (4,2);
+INSERT INTO xl_test VALUES (5,2);
+INSERT INTO xl_test VALUES (6,2);
+INSERT INTO xl_test VALUES (7,2);
+
+--the constraint is enforced when both rows map to the same datanode, e.g. when a=1, a=2
+--But if they go into different datanodes, the constraint is not enforced, e.g. when a=3
+
+drop table xl_circles;
+drop table xl_cons_hash;
+drop table xl_cons_modulo;
+drop table xl_cons_rr;
+drop table xl_test;
+drop table xl_test1;
+
+drop table xl_Room;
+drop table xl_WSlot;
+drop table xl_PLine;
+
+
+-- CREATE INDEX CONCURRENTLY is not supported
+--
+-- Try some concurrent index builds
+--
+-- Unfortunately this only tests about half the code paths because there are
+-- no concurrent updates happening to the table at the same time.
+
+CREATE TABLE xl_concur_heap (f1 text, f2 text);
+-- empty table
+CREATE INDEX CONCURRENTLY xl_concur_index1 ON xl_concur_heap(f2,f1);
+CREATE INDEX CONCURRENTLY IF NOT EXISTS xl_concur_index1 ON xl_concur_heap(f2,f1);
+INSERT INTO xl_concur_heap VALUES ('a','b');
+INSERT INTO xl_concur_heap VALUES ('b','b');
+
+drop index concurrently xl_concur_index1;
+drop table xl_concur_heap;
+
+
+--Large objects are not supported
+
+CREATE TABLE lotest_stash_values (loid oid, junk integer, fd integer);
+-- lo_creat(mode integer) returns oid
+-- The mode arg to lo_creat is unused, some vestigal holdover from ancient times
+-- returns the large object id
+INSERT INTO lotest_stash_values (loid) VALUES( lo_creat(42) );
+
+drop table lotest_stash_values;
+
+--EVENT TRIGGERs are not supported
+CREATE FUNCTION xl_event_trigger_for_drops()
+ RETURNS event_trigger LANGUAGE plpgsql AS $$
+DECLARE
+ obj record;
+BEGIN
+ FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
+ LOOP
+ RAISE NOTICE '% dropped object: % %.% %',
+ tg_tag,
+ obj.object_type,
+ obj.schema_name,
+ obj.object_name,
+ obj.object_identity;
+ END LOOP;
+END
+$$;
+CREATE EVENT TRIGGER xl_event_trigger_for_drops
+ ON sql_drop
+ EXECUTE PROCEDURE xl_event_trigger_for_drops();
+
+drop function xl_event_trigger_for_drops();
+drop EVENT TRIGGER xl_event_trigger_for_drops;
+
+--Recursive queries are not supported
+WITH RECURSIVE t(n) AS (
+ VALUES (1)
+ UNION ALL
+ SELECT n+1 FROM t WHERE n < 100
+)
+SELECT sum(n) FROM t;
+
+--FDWs are not supported
+
+CREATE FOREIGN DATA WRAPPER xl_foo; -- ERROR
+RESET ROLE;
+CREATE FOREIGN DATA WRAPPER xl_foo VALIDATOR postgresql_fdw_validator;
+
+--LISTEN/NOTIFY is not supported. Looks like they are supported now.
+--We would obviously have issues with LISTEN/NOTIFY if clients are connected to different coordinators. Need to test that manually as it is difficult via regression.
+--Should work. Send a valid message via a valid channel name
+--LISTEN notify_async1;
+-- commenting LISTEN as PIDs shown here would never match in regression.
+SELECT pg_notify('notify_async1','sample message1');
+SELECT pg_notify('notify_async1','');
+SELECT pg_notify('notify_async1',NULL);
+
+-- Should fail. Send a valid message via an invalid channel name
+SELECT pg_notify('','sample message1');
+SELECT pg_notify(NULL,'sample message1');
+SELECT pg_notify('notify_async_channel_name_too_long______________________________','sample_message1');
+
+--Should work. Valid NOTIFY/LISTEN/UNLISTEN commands
+NOTIFY notify_async2;
+LISTEN notify_async2;
+UNLISTEN notify_async2;
+UNLISTEN *;
+
+--LISTEN virtual;
+NOTIFY virtual;
+
+NOTIFY virtual, 'This is the payload';
+
+
+--LISTEN foo;
+SELECT pg_notify('fo' || 'o', 'pay' || 'load');
+
+drop function xl_room_au();
+drop function xl_trap_zero_divide(int);
+drop function xl_nodename_from_id(integer);
+drop function xl_insert_Pline_test(int);
+drop function xl_update_Pline_test(int);
+drop function xl_delete_Pline_test(int);
+
+
+
+