Merge remote-tracking branch 'remotes/origin/master' into xl10devel
authorPavan Deolasee <[email protected]>
Wed, 28 Jun 2017 06:14:26 +0000 (11:44 +0530)
committerPavan Deolasee <[email protected]>
Wed, 28 Jun 2017 06:14:26 +0000 (11:44 +0530)
This merges the current master branch of XL with the XL 10 development branch.
Commits upto f72330316ea5796a2b11a05710b98eba4e706788 are included in this
merge.

17 files changed:
1  2 
src/backend/commands/sequence.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/prep/prepunion.c
src/backend/pgxc/locator/locator.c
src/backend/pgxc/pool/execRemote.c
src/bin/pg_dump/pg_dump.c
src/bin/pgbench/pgbench.c
src/test/regress/expected/arrays.out
src/test/regress/expected/gist.out
src/test/regress/expected/inet.out
src/test/regress/expected/jsonb.out
src/test/regress/expected/plpgsql.out
src/test/regress/sql/arrays.sql
src/test/regress/sql/gist.sql
src/test/regress/sql/inet.sql
src/test/regress/sql/jsonb.sql

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 222bd62a1f106b2e54ec0340dd245f4f7aafd183,68f5de5ccc5567b37dba6e9740cb17951296db80..077bdf4a029698c7c41d2ce183497159be725357
@@@ -482,10 -451,10 +524,10 @@@ usage(void
                   "  -i, --initialize         invokes initialization mode\n"
                   "  -F, --fillfactor=NUM     set fill factor\n"
  #ifdef PGXC
-                  "  -k           distribute by primary key branch id - bid\n"
+                  "  -k                       distribute tables by branch id (bid)\n"
  #endif
 -              "  -n, --no-vacuum          do not run VACUUM after initialization\n"
 -      "  -q, --quiet              quiet logging (one message each 5 seconds)\n"
 +                 "  -n, --no-vacuum          do not run VACUUM after initialization\n"
 +                 "  -q, --quiet              quiet logging (one message each 5 seconds)\n"
                   "  -s, --scale=NUM          scaling factor\n"
                   "  --foreign-keys           create foreign key constraints between tables\n"
                   "  --index-tablespace=TABLESPACE\n"
Simple merge
Simple merge
Simple merge
Simple merge
index 70278fd9b688d1d4ba5f53ffe4c4d4fa8ea0f9db,e1185201e2b5b8af5951f62d93d97b8011269ee1..9ea65ef149e07fc212f6328dddc7c15e57b8e797
@@@ -5644,384 -5630,28 +5632,407 @@@ exception when others the
    null; -- do nothing
  end;
  $$;
- ERROR:  unhandled assertion
- CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
+ ERROR:  Internal subtransactions not supported in Postgres-XL
+ CONTEXT:  PL/pgSQL function inline_code_block line 2 during statement block entry
+ -- Check parameter handling
+ BEGIN;
+ DROP TABLE IF EXISTS testcase_13;
+ NOTICE:  table "testcase_13" does not exist, skipping
+ CREATE TABLE testcase_13 (patient_id integer);
+ INSERT INTO testcase_13 VALUES (1);
+ DO $$
+ DECLARE
+  r RECORD;
+ BEGIN
+ FOR r IN SELECT * FROM testcase_13 LOOP
+     RAISE INFO 'r.patient_id=%', r.patient_id;
+     IF   (SELECT EXISTS (
+             SELECT FROM testcase_13 WHERE patient_id = r.patient_id
+         ))
+        THEN
+           RAISE INFO 'condition true';
+     END IF;
+   END LOOP;
+ END $$;
+ INFO:  r.patient_id=1
+ INFO:  condition true
+ ROLLBACK;
++>>>>>>> remotes/origin/master
 +-- Test use of plpgsql in a domain check constraint (cf. bug #14414)
 +create function plpgsql_domain_check(val int) returns boolean as $$
 +begin return val > 0; end
 +$$ language plpgsql immutable;
 +create domain plpgsql_domain as integer check(plpgsql_domain_check(value));
 +do $$
 +declare v_test plpgsql_domain;
 +begin
 +  v_test := 1;
 +end;
 +$$;
 +do $$
 +declare v_test plpgsql_domain := 1;
 +begin
 +  v_test := 0;  -- fail
 +end;
 +$$;
 +ERROR:  value for domain plpgsql_domain violates check constraint "plpgsql_domain_check"
 +CONTEXT:  PL/pgSQL function inline_code_block line 4 at assignment
 +-- Test handling of expanded array passed to a domain constraint (bug #14472)
 +create function plpgsql_arr_domain_check(val int[]) returns boolean as $$
 +begin return val[1] > 0; end
 +$$ language plpgsql immutable;
 +create domain plpgsql_arr_domain as int[] check(plpgsql_arr_domain_check(value));
 +do $$
 +declare v_test plpgsql_arr_domain;
 +begin
 +  v_test := array[1];
 +  v_test := v_test || 2;
 +end;
 +$$;
 +do $$
 +declare v_test plpgsql_arr_domain := array[1];
 +begin
 +  v_test := 0 || v_test;  -- fail
 +end;
 +$$;
 +ERROR:  value for domain plpgsql_arr_domain violates check constraint "plpgsql_arr_domain_check"
 +CONTEXT:  PL/pgSQL function inline_code_block line 4 at assignment
 +--
 +-- test usage of transition tables in AFTER triggers
 +--
 +CREATE TABLE transition_table_base (id int PRIMARY KEY, val text);
 +CREATE FUNCTION transition_table_base_ins_func()
 +  RETURNS trigger
 +  LANGUAGE plpgsql
 +AS $$
 +DECLARE
 +  t text;
 +  l text;
 +BEGIN
 +  t = '';
 +  FOR l IN EXECUTE
 +           $q$
 +             EXPLAIN (TIMING off, COSTS off, VERBOSE on)
 +             SELECT * FROM newtable
 +           $q$ LOOP
 +    t = t || l || E'\n';
 +  END LOOP;
 +
 +  RAISE INFO '%', t;
 +  RETURN new;
 +END;
 +$$;
 +CREATE TRIGGER transition_table_base_ins_trig
 +  AFTER INSERT ON transition_table_base
 +  REFERENCING OLD TABLE AS oldtable NEW TABLE AS newtable
 +  FOR EACH STATEMENT
 +  EXECUTE PROCEDURE transition_table_base_ins_func();
 +ERROR:  OLD TABLE can only be specified for a DELETE or UPDATE trigger
 +CREATE TRIGGER transition_table_base_ins_trig
 +  AFTER INSERT ON transition_table_base
 +  REFERENCING NEW TABLE AS newtable
 +  FOR EACH STATEMENT
 +  EXECUTE PROCEDURE transition_table_base_ins_func();
 +INSERT INTO transition_table_base VALUES (1, 'One'), (2, 'Two');
 +INFO:  Named Tuplestore Scan
 +  Output: id, val
 +
 +INSERT INTO transition_table_base VALUES (3, 'Three'), (4, 'Four');
 +INFO:  Named Tuplestore Scan
 +  Output: id, val
 +
 +CREATE OR REPLACE FUNCTION transition_table_base_upd_func()
 +  RETURNS trigger
 +  LANGUAGE plpgsql
 +AS $$
 +DECLARE
 +  t text;
 +  l text;
 +BEGIN
 +  t = '';
 +  FOR l IN EXECUTE
 +           $q$
 +             EXPLAIN (TIMING off, COSTS off, VERBOSE on)
 +             SELECT * FROM oldtable ot FULL JOIN newtable nt USING (id)
 +           $q$ LOOP
 +    t = t || l || E'\n';
 +  END LOOP;
 +
 +  RAISE INFO '%', t;
 +  RETURN new;
 +END;
 +$$;
 +CREATE TRIGGER transition_table_base_upd_trig
 +  AFTER UPDATE ON transition_table_base
 +  REFERENCING OLD TABLE AS oldtable NEW TABLE AS newtable
 +  FOR EACH STATEMENT
 +  EXECUTE PROCEDURE transition_table_base_upd_func();
 +UPDATE transition_table_base
 +  SET val = '*' || val || '*'
 +  WHERE id BETWEEN 2 AND 3;
 +INFO:  Hash Full Join
 +  Output: COALESCE(ot.id, nt.id), ot.val, nt.val
 +  Hash Cond: (ot.id = nt.id)
 +  ->  Named Tuplestore Scan
 +        Output: ot.id, ot.val
 +  ->  Hash
 +        Output: nt.id, nt.val
 +        ->  Named Tuplestore Scan
 +              Output: nt.id, nt.val
 +
 +CREATE TABLE transition_table_level1
 +(
 +      level1_no serial NOT NULL ,
 +      level1_node_name varchar(255),
 +       PRIMARY KEY (level1_no)
 +) WITHOUT OIDS;
 +CREATE TABLE transition_table_level2
 +(
 +      level2_no serial NOT NULL ,
 +      parent_no int NOT NULL,
 +      level1_node_name varchar(255),
 +       PRIMARY KEY (level2_no)
 +) WITHOUT OIDS;
 +CREATE TABLE transition_table_status
 +(
 +      level int NOT NULL,
 +      node_no int NOT NULL,
 +      status int,
 +       PRIMARY KEY (level, node_no)
 +) WITHOUT OIDS;
 +CREATE FUNCTION transition_table_level1_ri_parent_del_func()
 +  RETURNS TRIGGER
 +  LANGUAGE plpgsql
 +AS $$
 +  DECLARE n bigint;
 +  BEGIN
 +    PERFORM FROM p JOIN transition_table_level2 c ON c.parent_no = p.level1_no;
 +    IF FOUND THEN
 +      RAISE EXCEPTION 'RI error';
 +    END IF;
 +    RETURN NULL;
 +  END;
 +$$;
 +CREATE TRIGGER transition_table_level1_ri_parent_del_trigger
 +  AFTER DELETE ON transition_table_level1
 +  REFERENCING OLD TABLE AS p
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    transition_table_level1_ri_parent_del_func();
 +CREATE FUNCTION transition_table_level1_ri_parent_upd_func()
 +  RETURNS TRIGGER
 +  LANGUAGE plpgsql
 +AS $$
 +  DECLARE
 +    x int;
 +  BEGIN
 +    WITH p AS (SELECT level1_no, sum(delta) cnt
 +                 FROM (SELECT level1_no, 1 AS delta FROM i
 +                       UNION ALL
 +                       SELECT level1_no, -1 AS delta FROM d) w
 +                 GROUP BY level1_no
 +                 HAVING sum(delta) < 0)
 +    SELECT level1_no
 +      FROM p JOIN transition_table_level2 c ON c.parent_no = p.level1_no
 +      INTO x;
 +    IF FOUND THEN
 +      RAISE EXCEPTION 'RI error';
 +    END IF;
 +    RETURN NULL;
 +  END;
 +$$;
 +CREATE TRIGGER transition_table_level1_ri_parent_upd_trigger
 +  AFTER UPDATE ON transition_table_level1
 +  REFERENCING OLD TABLE AS d NEW TABLE AS i
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    transition_table_level1_ri_parent_upd_func();
 +CREATE FUNCTION transition_table_level2_ri_child_insupd_func()
 +  RETURNS TRIGGER
 +  LANGUAGE plpgsql
 +AS $$
 +  BEGIN
 +    PERFORM FROM i
 +      LEFT JOIN transition_table_level1 p
 +        ON p.level1_no IS NOT NULL AND p.level1_no = i.parent_no
 +      WHERE p.level1_no IS NULL;
 +    IF FOUND THEN
 +      RAISE EXCEPTION 'RI error';
 +    END IF;
 +    RETURN NULL;
 +  END;
 +$$;
 +CREATE TRIGGER transition_table_level2_ri_child_insupd_trigger
 +  AFTER INSERT OR UPDATE ON transition_table_level2
 +  REFERENCING NEW TABLE AS i
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    transition_table_level2_ri_child_insupd_func();
 +-- create initial test data
 +INSERT INTO transition_table_level1 (level1_no)
 +  SELECT generate_series(1,200);
 +ANALYZE transition_table_level1;
 +INSERT INTO transition_table_level2 (level2_no, parent_no)
 +  SELECT level2_no, level2_no / 50 + 1 AS parent_no
 +    FROM generate_series(1,9999) level2_no;
 +ANALYZE transition_table_level2;
 +INSERT INTO transition_table_status (level, node_no, status)
 +  SELECT 1, level1_no, 0 FROM transition_table_level1;
 +INSERT INTO transition_table_status (level, node_no, status)
 +  SELECT 2, level2_no, 0 FROM transition_table_level2;
 +ANALYZE transition_table_status;
 +INSERT INTO transition_table_level1(level1_no)
 +  SELECT generate_series(201,1000);
 +ANALYZE transition_table_level1;
 +-- behave reasonably if someone tries to modify a transition table
 +CREATE FUNCTION transition_table_level2_bad_usage_func()
 +  RETURNS TRIGGER
 +  LANGUAGE plpgsql
 +AS $$
 +  BEGIN
 +    INSERT INTO d VALUES (1000000, 1000000, 'x');
 +    RETURN NULL;
 +  END;
 +$$;
 +CREATE TRIGGER transition_table_level2_bad_usage_trigger
 +  AFTER DELETE ON transition_table_level2
 +  REFERENCING OLD TABLE AS d
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    transition_table_level2_bad_usage_func();
 +DELETE FROM transition_table_level2
 +  WHERE level2_no BETWEEN 301 AND 305;
 +ERROR:  relation "d" cannot be the target of a modifying statement
 +CONTEXT:  SQL statement "INSERT INTO d VALUES (1000000, 1000000, 'x')"
 +PL/pgSQL function transition_table_level2_bad_usage_func() line 3 at SQL statement
 +DROP TRIGGER transition_table_level2_bad_usage_trigger
 +  ON transition_table_level2;
 +-- attempt modifications which would break RI (should all fail)
 +DELETE FROM transition_table_level1
 +  WHERE level1_no = 25;
 +ERROR:  RI error
 +CONTEXT:  PL/pgSQL function transition_table_level1_ri_parent_del_func() line 6 at RAISE
 +UPDATE transition_table_level1 SET level1_no = -1
 +  WHERE level1_no = 30;
 +ERROR:  RI error
 +CONTEXT:  PL/pgSQL function transition_table_level1_ri_parent_upd_func() line 15 at RAISE
 +INSERT INTO transition_table_level2 (level2_no, parent_no)
 +  VALUES (10000, 10000);
 +ERROR:  RI error
 +CONTEXT:  PL/pgSQL function transition_table_level2_ri_child_insupd_func() line 8 at RAISE
 +UPDATE transition_table_level2 SET parent_no = 2000
 +  WHERE level2_no = 40;
 +ERROR:  RI error
 +CONTEXT:  PL/pgSQL function transition_table_level2_ri_child_insupd_func() line 8 at RAISE
 +-- attempt modifications which would not break RI (should all succeed)
 +DELETE FROM transition_table_level1
 +  WHERE level1_no BETWEEN 201 AND 1000;
 +DELETE FROM transition_table_level1
 +  WHERE level1_no BETWEEN 100000000 AND 100000010;
 +SELECT count(*) FROM transition_table_level1;
 + count 
 +-------
 +   200
 +(1 row)
 +
 +DELETE FROM transition_table_level2
 +  WHERE level2_no BETWEEN 211 AND 220;
 +SELECT count(*) FROM transition_table_level2;
 + count 
 +-------
 +  9989
 +(1 row)
 +
 +CREATE TABLE alter_table_under_transition_tables
 +(
 +  id int PRIMARY KEY,
 +  name text
 +);
 +CREATE FUNCTION alter_table_under_transition_tables_upd_func()
 +  RETURNS TRIGGER
 +  LANGUAGE plpgsql
 +AS $$
 +BEGIN
 +  RAISE WARNING 'old table = %, new table = %',
 +                  (SELECT string_agg(id || '=' || name, ',') FROM d),
 +                  (SELECT string_agg(id || '=' || name, ',') FROM i);
 +  RAISE NOTICE 'one = %', (SELECT 1 FROM alter_table_under_transition_tables LIMIT 1);
 +  RETURN NULL;
 +END;
 +$$;
 +-- should fail, TRUNCATE is not compatible with transition tables
 +CREATE TRIGGER alter_table_under_transition_tables_upd_trigger
 +  AFTER TRUNCATE OR UPDATE ON alter_table_under_transition_tables
 +  REFERENCING OLD TABLE AS d NEW TABLE AS i
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    alter_table_under_transition_tables_upd_func();
 +ERROR:  TRUNCATE triggers with transition tables are not supported
 +-- should work
 +CREATE TRIGGER alter_table_under_transition_tables_upd_trigger
 +  AFTER UPDATE ON alter_table_under_transition_tables
 +  REFERENCING OLD TABLE AS d NEW TABLE AS i
 +  FOR EACH STATEMENT EXECUTE PROCEDURE
 +    alter_table_under_transition_tables_upd_func();
 +INSERT INTO alter_table_under_transition_tables
 +  VALUES (1, '1'), (2, '2'), (3, '3');
 +UPDATE alter_table_under_transition_tables
 +  SET name = name || name;
 +WARNING:  old table = 1=1,2=2,3=3, new table = 1=11,2=22,3=33
 +NOTICE:  one = 1
 +-- now change 'name' to an integer to see what happens...
 +ALTER TABLE alter_table_under_transition_tables
 +  ALTER COLUMN name TYPE int USING name::integer;
 +UPDATE alter_table_under_transition_tables
 +  SET name = (name::text || name::text)::integer;
 +WARNING:  old table = 1=11,2=22,3=33, new table = 1=1111,2=2222,3=3333
 +NOTICE:  one = 1
 +-- now drop column 'name'
 +ALTER TABLE alter_table_under_transition_tables
 +  DROP column name;
 +UPDATE alter_table_under_transition_tables
 +  SET id = id;
 +ERROR:  column "name" does not exist
 +LINE 1: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
 +                                               ^
 +QUERY:  SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
 +CONTEXT:  PL/pgSQL function alter_table_under_transition_tables_upd_func() line 3 at RAISE
 +--
 +-- Check type parsing and record fetching from partitioned tables
 +--
 +CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a);
 +CREATE TABLE pt_part1 PARTITION OF partitioned_table FOR VALUES IN (1);
 +CREATE TABLE pt_part2 PARTITION OF partitioned_table FOR VALUES IN (2);
 +INSERT INTO partitioned_table VALUES (1, 'Row 1');
 +INSERT INTO partitioned_table VALUES (2, 'Row 2');
 +CREATE OR REPLACE FUNCTION get_from_partitioned_table(partitioned_table.a%type)
 +RETURNS partitioned_table AS $$
 +DECLARE
 +    a_val partitioned_table.a%TYPE;
 +    result partitioned_table%ROWTYPE;
 +BEGIN
 +    a_val := $1;
 +    SELECT * INTO result FROM partitioned_table WHERE a = a_val;
 +    RETURN result;
 +END; $$ LANGUAGE plpgsql;
 +NOTICE:  type reference partitioned_table.a%TYPE converted to integer
 +SELECT * FROM get_from_partitioned_table(1) AS t;
 + a |   b   
 +---+-------
 + 1 | Row 1
 +(1 row)
 +
 +CREATE OR REPLACE FUNCTION list_partitioned_table()
 +RETURNS SETOF partitioned_table.a%TYPE AS $$
 +DECLARE
 +    row partitioned_table%ROWTYPE;
 +    a_val partitioned_table.a%TYPE;
 +BEGIN
 +    FOR row IN SELECT * FROM partitioned_table ORDER BY a LOOP
 +        a_val := row.a;
 +        RETURN NEXT a_val;
 +    END LOOP;
 +    RETURN;
 +END; $$ LANGUAGE plpgsql;
 +NOTICE:  type reference partitioned_table.a%TYPE converted to integer
 +SELECT * FROM list_partitioned_table() AS t;
 + t 
 +---
 + 1
 + 2
 +(2 rows)
Simple merge
Simple merge
Simple merge
Simple merge