Merge tag 'REL_10_6' into XL_10_STABLE
authorPavan Deolasee <[email protected]>
Fri, 7 Dec 2018 07:27:12 +0000 (12:57 +0530)
committerPavan Deolasee <[email protected]>
Fri, 7 Dec 2018 07:27:12 +0000 (12:57 +0530)
91 files changed:
1  2 
configure
configure.in
doc/bug.template
doc/src/sgml/config.sgml
doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml
doc/src/sgml/installation.sgml
doc/src/sgml/libpq.sgml
doc/src/sgml/lobj.sgml
doc/src/sgml/pgrowlocks.sgml
doc/src/sgml/ref/pg_ctl-ref.sgml
doc/src/sgml/ref/pgupgrade.sgml
doc/src/sgml/runtime.sgml
src/Makefile.global.in
src/Makefile.shlib
src/backend/access/heap/heapam.c
src/backend/access/transam/commit_ts.c
src/backend/access/transam/parallel.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/event_trigger.c
src/backend/commands/foreigncmds.c
src/backend/commands/indexcmds.c
src/backend/commands/tablecmds.c
src/backend/commands/view.c
src/backend/executor/execCurrent.c
src/backend/executor/execMain.c
src/backend/executor/execProcnode.c
src/backend/executor/nodeSubplan.c
src/backend/executor/spi.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/plan/planner.c
src/backend/postmaster/pgstat.c
src/backend/postmaster/postmaster.c
src/backend/replication/logical/logical.c
src/backend/rewrite/rewriteHandler.c
src/backend/storage/ipc/procarray.c
src/backend/storage/lmgr/lmgr.c
src/backend/storage/lmgr/lock.c
src/backend/tcop/postgres.c
src/backend/tcop/utility.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/timestamp.c
src/backend/utils/cache/inval.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/init/miscinit.c
src/backend/utils/misc/guc.c
src/bin/initdb/initdb.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_rewind/filemap.c
src/bin/psql/tab-complete.c
src/bin/scripts/vacuumdb.c
src/include/access/hash.h
src/include/access/xact.h
src/include/c.h
src/include/executor/executor.h
src/include/nodes/execnodes.h
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/optimizer/planner.h
src/include/pg_config.h.in
src/include/pg_config.h.win32
src/include/storage/lock.h
src/include/utils/lsyscache.h
src/test/regress/expected/alter_table.out
src/test/regress/expected/create_table.out
src/test/regress/expected/event_trigger.out
src/test/regress/expected/horology.out
src/test/regress/expected/polymorphism.out
src/test/regress/expected/privileges.out
src/test/regress/expected/sanity_check.out
src/test/regress/expected/select_parallel.out
src/test/regress/expected/strings.out
src/test/regress/expected/subselect.out
src/test/regress/expected/temp.out
src/test/regress/pg_regress.c
src/test/regress/sql/alter_table.sql
src/test/regress/sql/create_table.sql
src/test/regress/sql/horology.sql
src/test/regress/sql/polymorphism.sql
src/test/regress/sql/portals.sql
src/test/regress/sql/privileges.sql
src/test/regress/sql/select_parallel.sql
src/test/regress/sql/strings.sql
src/test/regress/sql/subselect.sql
src/test/regress/sql/temp.sql

diff --cc configure
index c6b7e1ed3de8dd77f425731182f4a2744fd943de,d39564c569ca85a76482f45c68b77c49eeeec27e..6a3c672cbe3c633de58e71e5a55117904eb32062
+++ b/configure
@@@ -1,8 -1,8 +1,8 @@@
  #! /bin/sh
  # Guess values for system-dependent variables and create Makefiles.
- # Generated by GNU Autoconf 2.69 for PostgreSQL 10.5 (Postgres-XL 10r1).
 -# Generated by GNU Autoconf 2.69 for PostgreSQL 10.6.
++# Generated by GNU Autoconf 2.69 for PostgreSQL 10.6 (Postgres-XL 10r1).
  #
 -# Report bugs to <pgsql-bugs@postgresql.org>.
 +# Report bugs to <bugs@postgres-xl.org>.
  #
  #
  # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@@ -582,10 -582,9 +582,10 @@@ MAKEFLAGS
  # Identity of this package.
  PACKAGE_NAME='PostgreSQL'
  PACKAGE_TARNAME='postgresql'
- PACKAGE_VERSION='10.5 (Postgres-XL 10r1)'
 -PACKAGE_VERSION='10.6'
 -PACKAGE_STRING='PostgreSQL 10.6'
 -PACKAGE_BUGREPORT='[email protected]'
++PACKAGE_VERSION='10.6 (Postgres-XL 10r1)'
 +PACKAGE_XC_VERSION='10r1'
- PACKAGE_STRING='PostgreSQL 10.5 (Postgres-XL 10r1)'
++PACKAGE_STRING='PostgreSQL 10.6 (Postgres-XL 10r1)'
 +PACKAGE_BUGREPORT='[email protected]'
  PACKAGE_URL=''
  
  ac_unique_file="src/backend/access/common/heaptuple.c"
@@@ -1413,7 -1411,7 +1415,7 @@@ if test "$ac_init_help" = "long"; the
    # Omit some internal or obsolete options to make the list less imposing.
    # This message is too long to be a string in the A/UX 3.1 sh.
    cat <<_ACEOF
- \`configure' configures PostgreSQL 10.5 (Postgres-XL 10r1) to adapt to many kinds of systems.
 -\`configure' configures PostgreSQL 10.6 to adapt to many kinds of systems.
++\`configure' configures PostgreSQL 10.6 (Postgres-XL 10r1) to adapt to many kinds of systems.
  
  Usage: $0 [OPTION]... [VAR=VALUE]...
  
  
  if test -n "$ac_init_help"; then
    case $ac_init_help in
-      short | recursive ) echo "Configuration of PostgreSQL 10.5 (Postgres-XL 10r1):";;
 -     short | recursive ) echo "Configuration of PostgreSQL 10.6:";;
++     short | recursive ) echo "Configuration of PostgreSQL 10.6 (Postgres-XL 10r1):";;
     esac
    cat <<\_ACEOF
  
  test -n "$ac_init_help" && exit $ac_status
  if $ac_init_version; then
    cat <<\_ACEOF
- PostgreSQL configure 10.5 (Postgres-XL 10r1)
 -PostgreSQL configure 10.6
++PostgreSQL configure 10.6 (Postgres-XL 10r1)
  generated by GNU Autoconf 2.69
  
  Copyright (C) 2012 Free Software Foundation, Inc.
@@@ -2348,7 -2346,7 +2350,7 @@@ cat >config.log <<_ACEO
  This file contains any messages produced by compilers while
  running configure, to aid debugging if configure makes a mistake.
  
- It was created by PostgreSQL $as_me 10.5 (Postgres-XL 10r1), which was
 -It was created by PostgreSQL $as_me 10.6, which was
++It was created by PostgreSQL $as_me 10.6 (Postgres-XL 10r1), which was
  generated by GNU Autoconf 2.69.  Invocation command line was
  
    $ $0 $@
@@@ -17008,10 -17010,16 +17057,19 @@@ cat >>confdefs.h <<_ACEO
  _ACEOF
  
  
 +# For PGXC, set -DPGXC by default. This can be overriden with -UPGXC if the user sets it.
 +# For Postgres-XL, set both -DPGXC and -DXCP  
 +CFLAGS="-DPGXC -DXCP $CFLAGS"
  
+ # If we are inserting PG_SYSROOT into CPPFLAGS, do so symbolically not
+ # literally, so that it's possible to override it at build time using
+ # a command like "make ... PG_SYSROOT=path".  This has to be done after
+ # we've finished all configure checks that depend on CPPFLAGS.
+ if test x"$PG_SYSROOT" != x; then
+   CPPFLAGS=`echo "$CPPFLAGS" | sed -e "s| $PG_SYSROOT | \\\$(PG_SYSROOT) |"`
+ fi
  
  # Begin output steps
  
@@@ -17571,7 -17579,7 +17629,7 @@@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wr
  # report actual input values of CONFIG_FILES etc. instead of their
  # values after options handling.
  ac_log="
- This file was extended by PostgreSQL $as_me 10.5 (Postgres-XL 10r1), which was
 -This file was extended by PostgreSQL $as_me 10.6, which was
++This file was extended by PostgreSQL $as_me 10.6 (Postgres-XL 10r1), which was
  generated by GNU Autoconf 2.69.  Invocation command line was
  
    CONFIG_FILES    = $CONFIG_FILES
@@@ -17641,7 -17649,7 +17699,7 @@@ _ACEO
  cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
  ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
  ac_cs_version="\\
- PostgreSQL config.status 10.5 (Postgres-XL 10r1)
 -PostgreSQL config.status 10.6
++PostgreSQL config.status 10.6 (Postgres-XL 10r1)
  configured by $0, generated by GNU Autoconf 2.69,
    with options \\"\$ac_cs_config\\"
  
diff --cc configure.in
index fe4e88d00c4279533ba3b1a9e7dbe7190de6c053,60c1b4b7a581a2cdb84c77d71f813961d61d795a..29c06721f1b44c012bca824dc518430a61e13493
@@@ -17,7 -17,7 +17,7 @@@ dnl Read the Autoconf manual for detail
  dnl
  m4_pattern_forbid(^PGAC_)dnl to catch undefined macros
  
- AC_INIT([PostgreSQL], [10.5 (Postgres-XL 10r1)], [[email protected]])
 -AC_INIT([PostgreSQL], [10.6], [[email protected]])
++AC_INIT([PostgreSQL], [10.6 (Postgres-XL 10r1)], [[email protected]])
  
  m4_if(m4_defn([m4_PACKAGE_VERSION]), [2.69], [], [m4_fatal([Autoconf version 2.69 is required.
  Untested combinations of 'autoconf' and PostgreSQL versions are not
index d943220e8e078de94e6da04c7ebf09bf20069933,4a36036032e231771ca4e66f86f9c6655906126f..f984f4bca467f745d376150fa1a028bfb379cd86
@@@ -27,7 -27,7 +27,7 @@@ System Configuration
  
    Operating System (example: Linux 2.4.18)    :
  
-   PostgreSQL version (example: PostgreSQL 10.5):  Postgres-XL 10r1
 -  PostgreSQL version (example: PostgreSQL 10.6):  PostgreSQL 10.6
++  PostgreSQL version (example: PostgreSQL 10.6):  Postgres-XL 10r1
  
    Compiler used (example: gcc 3.3.5)          :
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 35d22ac082d9757e8815523bfd47cce25ca765b8,b028b318e5c88cc071d3cf77ef88700f94cb1af9..a38bab582395ac7e088f4ff05f00ab91512c6d80
@@@ -976,21 -747,13 +992,24 @@@ GetCurrentTransactionStopTimestamp(void
        if (xactStopTimestamp != 0)
                return xactStopTimestamp;
        return GetCurrentTimestamp();
 +#endif
  }
  
 +#ifdef PGXC
 +TimestampTz
 +GetCurrentGTMStartTimestamp(void)
 +{
 +      if (GTMxactStartTimestamp == 0)
 +              GTMxactStartTimestamp = xactStartTimestamp;
 +      return GTMxactStartTimestamp;
 +}
 +#endif
 +
  /*
   *    SetCurrentStatementStartTimestamp
+  *
+  * In a parallel worker, this should already have been provided by a call
+  * to SetParallelStartTimestamps().
   */
  void
  SetCurrentStatementStartTimestamp(void)
@@@ -2223,19 -1915,18 +2245,25 @@@ StartTransaction(void
        /*
         * set transaction_timestamp() (a/k/a now()).  We want this to be the same
         * as the first command's statement_timestamp(), so don't do a fresh
-        * GetCurrentTimestamp() call (which'd be expensive anyway).  Also, mark
-        * xactStopTimestamp as unset.
+        * GetCurrentTimestamp() call (which'd be expensive anyway).  In a
+        * parallel worker, this should already have been provided by a call to
+        * SetParallelStartTimestamps().
+        *
+        * Also, mark xactStopTimestamp as unset.
         */
-       xactStartTimestamp = stmtStartTimestamp;
+       if (!IsParallelWorker())
+               xactStartTimestamp = stmtStartTimestamp;
+       else
+               Assert(xactStartTimestamp != 0);
        xactStopTimestamp = 0;
 +#ifdef PGXC
 +      /* For Postgres-XC, transaction start timestamp has to follow the GTM timeline */
 +      pgstat_report_xact_timestamp(GTMxactStartTimestamp ?
 +                      GTMxactStartTimestamp :
 +                      xactStartTimestamp);
 +#else
        pgstat_report_xact_timestamp(xactStartTimestamp);
 +#endif
  
        /*
         * initialize current transaction state fields
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index c98f85ba3f33e1ea3d39be6d0c21646cce37438c,a4cdde08472047eb3da4576b337b47d7b91d798e..087e0553391e8fe8c57ac5a7e4daf8c7b809ea31
  #include "utils/portal.h"
  #include "utils/rel.h"
  
 +#ifdef PGXC
 +#include "pgxc/execRemote.h"
 +#endif
  
  static char *fetch_cursor_param_value(ExprContext *econtext, int paramId);
 -static ScanState *search_plan_tree(PlanState *node, Oid table_oid,
 -                               bool *pending_rescan);
 -
  
- #ifndef PGXC
- static ScanState *search_plan_tree(PlanState *node, Oid table_oid);
- #endif
  /*
   * execCurrentOf
   *
@@@ -294,15 -295,20 +296,20 @@@ fetch_cursor_param_value(ExprContext *e
   *
   * Search through a PlanState tree for a scan node on the specified table.
   * Return NULL if not found or multiple candidates.
+  *
+  * If a candidate is found, set *pending_rescan to true if that candidate
+  * or any node above it has a pending rescan action, i.e. chgParam != NULL.
+  * That indicates that we shouldn't consider the node to be positioned on a
+  * valid tuple, even if its own state would indicate that it is.  (Caller
+  * must initialize *pending_rescan to false, and should not trust its state
+  * if multiple candidates are found.)
   */
- #ifdef PGXC
 -static ScanState *
 +ScanState *
- search_plan_tree(PlanState *node, Oid table_oid)
- #else
- static ScanState *
- search_plan_tree(PlanState *node, Oid table_oid)
- #endif
+ search_plan_tree(PlanState *node, Oid table_oid,
+                                bool *pending_rescan)
  {
+       ScanState  *result = NULL;
        if (node == NULL)
                return NULL;
        switch (nodeTag(node))
                         * Result and Limit can be descended through (these are safe
                         * because they always return their input's current row)
                         */
 +#ifdef PGXC
 +              case T_MaterialState:
 +#endif
                case T_ResultState:
                case T_LimitState:
-                       return search_plan_tree(node->lefttree, table_oid);
+                       result = search_plan_tree(node->lefttree,
+                                                                         table_oid,
+                                                                         pending_rescan);
+                       break;
  
                        /*
                         * SubqueryScan too, but it keeps the child in a different place
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index c4a258452df19c20fd543cc4f5ee861d66c68d4c,56d81890bce3b6a9826cabd3827a69e24ded8bbe..577d38fa9cc2f5c26c405701811dff69c6f5b0f3
@@@ -2864,15 -2734,7 +2864,15 @@@ pmdie(SIGNAL_ARGS
                                signal_child(BgWriterPID, SIGTERM);
                        if (WalReceiverPID != 0)
                                signal_child(WalReceiverPID, SIGTERM);
-                       if (pmState == PM_RECOVERY)
 +#ifdef XCP
 +                      /* and the pool manager too */
 +                      if (PgPoolerPID != 0)
 +                              signal_child(PgPoolerPID, SIGTERM);
 +                      /* and the cluster monitor too */
 +                      if (ClusterMonPID != 0)
 +                              signal_child(ClusterMonPID, SIGTERM);
 +#endif /* XCP */
+                       if (pmState == PM_STARTUP || pmState == PM_RECOVERY)
                        {
                                SignalSomeChildren(SIGTERM, BACKEND_TYPE_BGWORKER);
  
index f6774df96f2ab88b662bb9b9d9bc045978e4ebd1,46f13bbe61e92965da8e5172960fbc53c633e198..e38df742e28a06ef19049dbb5b7f9772ed0b4119
@@@ -77,16 -77,11 +77,21 @@@ CheckLogicalDecodingRequirements(void
  {
        CheckSlotRequirements();
  
 +      /*
 +       * Postgres-XL does not support logical replication for now. We could create
 +       * the logical replication slot, but attempts to decode the WAL would crash
 +       * and burn as ReorderBufferCommit() uses subtransactions internally. We need
 +       */
 +      ereport(ERROR,
 +                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 +                       errmsg("Postgres-XL does not support logical replication"),
 +                       errdetail("The feature is not currently supported")));
 +
+       /*
+        * NB: Adding a new requirement likely means that RestoreSlotFromDisk()
+        * needs the same check.
+        */
        if (wal_level < WAL_LEVEL_LOGICAL)
                ereport(ERROR,
                                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
Simple merge
Simple merge
index e1c74616d748b30e0f9d451047d4887660fdaa76,10e2d028fa8a537bc1bf73b4e103e4042daeca01..21a373a81796b99a1bce92cd0d7cb0ad4088ed3b
@@@ -123,18 -122,17 +124,27 @@@ LockRelationOid(Oid relid, LOCKMODE loc
         * modifies the rel, the relcache update happens via
         * CommandCounterIncrement, not here.)
         *
+        * However, in corner cases where code acts on tables (usually catalogs)
+        * recursively, we might get here while still processing invalidation
+        * messages in some outer execution of this function or a sibling.  The
+        * "cleared" status of the lock tells us whether we really are done
+        * absorbing relevant inval messages.
++       *
 +       * In Postgres-XL, multiple backends may run concurrently to serve a
 +       * distributed transaction. In that case, a conflicting lock may be granted
 +       * to another backend running the same distributed transaction. But it's
 +       * important that such backends process invalidation messages to ensure
 +       * that relcache entry modified by the other cooperating backend is truly
 +       * reflected. For example, the other backend may TRUNCATE the table and
 +       * change the relfilenode. So we must see that change and work with the new
 +       * relfilenode.
         */
-       if ((res != LOCKACQUIRE_ALREADY_HELD) ||
 -      if (res != LOCKACQUIRE_ALREADY_CLEAR)
++      if ((res != LOCKACQUIRE_ALREADY_CLEAR) ||
 +              (MyProc->coordPid && MyProc->coordId))
+       {
                AcceptInvalidationMessages();
+               MarkLockClear(locallock);
+       }
  }
  
  /*
index b332890aee6e124dbc354b6479973f6233f032b7,2810b2401ee9156e0fedac4619e1b05e32d10fb2..1499a9ddafddeff368e8214add3157b9aa676b24
@@@ -261,10 -260,6 +261,14 @@@ static LOCALLOCK *StrongLockInProgress
  static LOCALLOCK *awaitedLock;
  static ResourceOwner awaitedOwner;
  
- LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError,
- bool only_increment);
 +static LockAcquireResult LockAcquireExtendedXC(const LOCKTAG *locktag,
++                                                              LOCKMODE lockmode,
++                                                              bool sessionLock,
++                                                              bool dontWait,
++                                                              bool reportMemoryError, 
++                                                              LOCALLOCK **locallockp,
++                                                              bool only_increment);
 +
  
  #ifdef LOCK_DEBUG
  
@@@ -690,31 -686,10 +695,32 @@@ LockAcquire(const LOCKTAG *locktag
                        bool sessionLock,
                        bool dontWait)
  {
-       return LockAcquireExtended(locktag, lockmode, sessionLock, dontWait, true);
+       return LockAcquireExtended(locktag, lockmode, sessionLock, dontWait,
+                                                          true, NULL);
  }
  
-                                                               true, true);
 +#ifdef PGXC
 +/*
 + * LockIncrementIfExists - Special purpose case of LockAcquire().
 + * This checks if there is already a reference to the lock. If yes,
 + * increments it, and returns true. If not, just returns back false.
 + * Effectively, it never creates a new lock.
 + */
 +bool
 +LockIncrementIfExists(const LOCKTAG *locktag,
 +                      LOCKMODE lockmode, bool sessionLock)
 +{
 +      int ret;
 +
 +      ret = LockAcquireExtendedXC(locktag, lockmode,
 +                                  sessionLock,
 +                                  true, /* never wait */
++                                                              true, NULL, true);
 +
 +      return (ret == LOCKACQUIRE_ALREADY_HELD);
 +}
 +#endif
 +
  /*
   * LockAcquireExtended - allows us to specify additional options
   *
@@@ -729,23 -709,8 +740,25 @@@ LockAcquireExtended(const LOCKTAG *lock
                                        LOCKMODE lockmode,
                                        bool sessionLock,
                                        bool dontWait,
-                                       bool reportMemoryError)
+                                       bool reportMemoryError,
+                                       LOCALLOCK **locallockp)
 +{
 +      return LockAcquireExtendedXC(locktag, lockmode, sessionLock, dontWait,
-                                    reportMemoryError, false);
++                                   reportMemoryError, locallockp, false);
 +}
 +
 +/*
 + * LockAcquireExtendedXC - additional parameter only_increment. This is XC
 + * specific. Check comments for the function LockIncrementIfExists()
 + */
 +static LockAcquireResult
 +LockAcquireExtendedXC(const LOCKTAG *locktag,
 +                                      LOCKMODE lockmode,
 +                                      bool sessionLock,
 +                                      bool dontWait,
 +                                      bool reportMemoryError,
++                                      LOCALLOCK **locallockp,
 +                                      bool only_increment)
  {
        LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
        LockMethod      lockMethodTable;
        if (locallock->nLocks > 0)
        {
                GrantLockLocal(locallock, owner);
-               return LOCKACQUIRE_ALREADY_HELD;
+               if (locallock->lockCleared)
+                       return LOCKACQUIRE_ALREADY_CLEAR;
+               else
+                       return LOCKACQUIRE_ALREADY_HELD;
        }
 -
 +#ifdef PGXC
 +      else if (only_increment)
 +      {
 +              /* User does not want to create new lock if it does not already exist */
 +              return LOCKACQUIRE_NOT_AVAIL;
 +      }
 +#endif
        /*
         * Prepare to emit a WAL record if acquisition of this lock needs to be
         * replayed in a standby server.
Simple merge
index afcdf3e9376ead55a64547eefac9ac49b05b103b,135286ebbfb939df76c36877df4b35daf095e68e..783fc52faac8ceb26ba9c1f715bca0f431393a5d
@@@ -1356,37 -383,9 +1356,40 @@@ standard_ProcessUtility(PlannedStmt *ps
        bool            isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
        ParseState *pstate;
  
+       /* This can recurse, so check for excessive recursion */
+       check_stack_depth();
 +      /*
 +       * For more detail see comments in function pgxc_lock_for_backup.
 +       *
 +       * Cosider the following scenario:
 +       * Imagine a two cordinator cluster CO1, CO2
 +       * Suppose a client connected to CO1 issues select pgxc_lock_for_backup()
 +       * Now assume that a client connected to CO2 issues a create table
 +       * select pgxc_lock_for_backup() would try to acquire the advisory lock
 +       * in exclusive mode, whereas create table would try to acquire the same
 +       * lock in shared mode. Both these requests will always try acquire the
 +       * lock in the same order i.e. they would both direct the request first to
 +       * CO1 and then to CO2. One of the two requests would therefore pass
 +       * and the other would fail.
 +       *
 +       * Consider another scenario:
 +       * Suppose we have a two cooridnator cluster CO1 and CO2
 +       * Assume one client connected to each coordinator
 +       * Further assume one client starts a transaction
 +       * and issues a DDL. This is an unfinished transaction.
 +       * Now assume the second client issues
 +       * select pgxc_lock_for_backup()
 +       * This request would fail because the unfinished transaction
 +       * would already hold the advisory lock.
 +       */
 +      if (IS_PGXC_LOCAL_COORDINATOR && IsNormalProcessingMode())
 +      {
 +              /* Is the statement a prohibited one? */
 +              if (!IsStmtAllowedInLockedMode(parsetree, queryString))
 +                      pgxc_lock_for_utility_stmt(parsetree);
 +      }
 +
        check_xact_readonly(parsetree);
  
        if (completionTag)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 38abb2907d33dd534d62ce58433f7c809b2a4db5,83b2b9cee3c7c2cabf29ffaa848ecb4671d053a8..f0ff68d3a81d6a4c13d95a7e31ef46e68c32d817
@@@ -1421,17 -1405,32 +1421,32 @@@ psql_completion(const char *text, int s
         word_matches(p2, previous_words[previous_words_count - 2]) && \
         word_matches(p3, previous_words[previous_words_count - 3]))
  
+ #define HeadMatches4(p1, p2, p3, p4) \
+       (previous_words_count >= 4 && \
+        word_matches(p1, previous_words[previous_words_count - 1]) && \
+        word_matches(p2, previous_words[previous_words_count - 2]) && \
+        word_matches(p3, previous_words[previous_words_count - 3]) && \
+        word_matches(p4, previous_words[previous_words_count - 4]))
+ #define HeadMatches5(p1, p2, p3, p4, p5) \
+       (previous_words_count >= 5 && \
+        word_matches(p1, previous_words[previous_words_count - 1]) && \
+        word_matches(p2, previous_words[previous_words_count - 2]) && \
+        word_matches(p3, previous_words[previous_words_count - 3]) && \
+        word_matches(p4, previous_words[previous_words_count - 4]) && \
+        word_matches(p5, previous_words[previous_words_count - 5]))
        /* Known command-starting keywords. */
        static const char *const sql_commands[] = {
 -              "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
 +              "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLEAN CONNECTION", "CLOSE", "CLUSTER",
                "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
 -              "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
 -              "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
 -              "MOVE", "NOTIFY", "PREPARE",
 -              "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
 +              "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXECUTE DIRECT", "EXPLAIN",
 +              "FETCH", "GRANT", "INSERT", "LOAD", "LOCK",
 +              "MOVE", "PREPARE",
 +              "REASSIGN", "REINDEX",
                "RESET", "REVOKE", "ROLLBACK",
 -              "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
 -              "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
 +              "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
 +              "TABLE", "TRUNCATE", "UPDATE", "VACUUM", "VALUES", "WITH",
                NULL
        };
  
Simple merge
Simple merge
index 34c54198e2cc4ee41b924894b5abbe80a0c5c504,905f42c2b1d634049d96e65c2776340e579f2992..358523de489779bc6b8a1e2e75d1223a495dde69
@@@ -362,17 -337,11 +362,18 @@@ extern SubTransactionId GetCurrentSubTr
  extern void MarkCurrentTransactionIdLoggedIfAny(void);
  extern bool SubTransactionIsActive(SubTransactionId subxid);
  extern CommandId GetCurrentCommandId(bool used);
+ extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
  extern TimestampTz GetCurrentTransactionStartTimestamp(void);
  extern TimestampTz GetCurrentStatementStartTimestamp(void);
 +#ifdef XCP
 +extern TimestampTz GetCurrentLocalStatementStartTimestamp(void);
 +#endif
  extern TimestampTz GetCurrentTransactionStopTimestamp(void);
  extern void SetCurrentStatementStartTimestamp(void);
 +#ifdef PGXC
 +extern TimestampTz GetCurrentGTMStartTimestamp(void);
 +extern void SetCurrentGTMDeltaTimestamp(TimestampTz timestamp);
 +#endif
  extern int    GetCurrentTransactionNestLevel(void);
  extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
  extern void CommandCounterIncrement(void);
diff --cc src/include/c.h
Simple merge
index 389e34620922f4d2bb30ed2dab22ab7a1117483a,379e7c77a181704c1787b8242ffcdfe62fd761dd..0cf0bfa6c8a9e23fdfcec4780fafa400d0aabc9a
@@@ -114,10 -109,6 +114,11 @@@ extern bool execCurrentOf(CurrentOfExp
                          Oid table_oid,
                          ItemPointer current_tid);
  
- ScanState *search_plan_tree(PlanState *node, Oid table_oid);
 +#ifdef PGXC
++ScanState *search_plan_tree(PlanState *node, Oid table_oid,
++                              bool *pending_rescan);
 +#endif
 +
  /*
   * prototypes from functions in execGrouping.c
   */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 53015a1b9922227f42fbb1ff6805a0a058db83c1,a86261f5bbf429970b4e330c38d171ef2a87d52c..1cf42d5f4290172b6248a78e08de55b84fbc91dd
  #define MEMSET_LOOP_LIMIT 1024
  
  /* Define to the address where bug reports for this package should be sent. */
 -#define PACKAGE_BUGREPORT "p[email protected]"
 +#define PACKAGE_BUGREPORT "p[email protected]"
  
  /* Define to the full name of this package. */
 -#define PACKAGE_NAME "PostgreSQL"
 +#define PACKAGE_NAME "Postgres-XL"
  
  /* Define to the full name and version of this package. */
 -#define PACKAGE_STRING "PostgreSQL 10.6"
 +#define PACKAGE_STRING "Postgres-XL 10r1"
  
  /* Define to the version of this package. */
- #define PACKAGE_VERSION "10.5"
+ #define PACKAGE_VERSION "10.6"
  
  /* Define to the name of a signed 128-bit integer type. */
  #undef PG_INT128_TYPE
  #define PG_INT64_TYPE long long int
  
  /* PostgreSQL version as a string */
- #define PG_VERSION "10.5"
+ #define PG_VERSION "10.6"
  
  /* PostgreSQL version as a number */
- #define PG_VERSION_NUM 100005
+ #define PG_VERSION_NUM 100006
  
  /* Define to the one symbol short name of this package. */
 -#define PACKAGE_TARNAME "postgresql"
 +#define PACKAGE_TARNAME "postgres-xl"
 +
 +/* Postgres-XC version as a string */
 +#define PGXC_VERSION "1.1devel"
 +
 +/* Postgres-XC version as a number */
 +#define PGXC_VERSION_NUM 10100
  
  /* Define to the name of the default PostgreSQL service principal in Kerberos.
     (--with-krb-srvnam=NAME) */
Simple merge
Simple merge
index b7eec6067089086b96256d131f4e9132699c6571,70e140039ac911ec757ef2821fd65d4061dd6ac2..a7f6a4cf548831084f9ec267c8b32b5597e88313
@@@ -3693,119 -3669,36 +3693,154 @@@ alter table temp_part_parent attach par
    for values in (1, 2); -- ok
  drop table perm_part_parent cascade;
  drop table temp_part_parent cascade;
++
+ -- check that attaching partitions to a table while it is being used is
+ -- prevented
+ create table tab_part_attach (a int) partition by list (a);
+ create or replace function func_part_attach() returns trigger
+   language plpgsql as $$
+   begin
+     execute 'create table tab_part_attach_1 (a int)';
+     execute 'alter table tab_part_attach attach partition tab_part_attach_1 for values in (1)';
+     return null;
+   end $$;
+ create trigger trig_part_attach before insert on tab_part_attach
+   for each statement execute procedure func_part_attach();
+ insert into tab_part_attach values (1);
+ ERROR:  cannot ALTER TABLE "tab_part_attach" because it is being used by active queries in this session
+ CONTEXT:  SQL statement "alter table tab_part_attach attach partition tab_part_attach_1 for values in (1)"
+ PL/pgSQL function func_part_attach() line 4 at EXECUTE
+ drop table tab_part_attach;
+ drop function func_part_attach();
+ -- test case where the partitioning operator is a SQL function whose
+ -- evaluation results in the table's relcache being rebuilt partway through
+ -- the execution of an ATTACH PARTITION command
+ create function at_test_sql_partop (int4, int4) returns int language sql
+ as $$ select case when $1 = $2 then 0 when $1 > $2 then 1 else -1 end; $$;
+ create operator class at_test_sql_partop for type int4 using btree as
+     operator 1 < (int4, int4), operator 2 <= (int4, int4),
+     operator 3 = (int4, int4), operator 4 >= (int4, int4),
+     operator 5 > (int4, int4), function 1 at_test_sql_partop(int4, int4);
+ create table at_test_sql_partop (a int) partition by range (a at_test_sql_partop);
+ create table at_test_sql_partop_1 (a int);
+ alter table at_test_sql_partop attach partition at_test_sql_partop_1 for values from (0) to (10);
+ drop table at_test_sql_partop;
+ drop operator class at_test_sql_partop using btree;
+ drop function at_test_sql_partop;
++
 +-- xl tests
 +create table xl_parent (a int, b int, c text) partition by list (a);
 +-- create a partition
 +create table xl_child1 partition of xl_parent for values in (1, 2, 3);
 +-- attach a partition
 +create table xl_child2 (a int, b int, c text);
 +alter table xl_parent attach partition xl_child2 for values in (4, 5, 6);
 +-- attach a partition, distribution column position does not match
 +create table xl_child3 (b int, a int, c text) distribute by hash (a);
 +alter table xl_parent attach partition xl_child3 for values in (7, 8, 9);
 +ERROR:  table "xl_child3" is distributed on column "a" at position 1, but the parent table "xl_parent" is distributed on column "a" at position 2
 +DETAIL:  Distribution column for the child must be same as the parent
 +-- attach a partition, distribution column position matches, others do not
 +create table xl_child4 (a int, c text, b int) distribute by hash (a);
 +alter table xl_parent attach partition xl_child4 for values in (10, 11, 12);
 +create table xl_child5 (a int) distribute by hash (a);
 +alter table xl_child5 add column c text;
 +alter table xl_child5 add column b int;
 +alter table xl_parent attach partition xl_child5 for values in (13, 14, 15);
 +create table xl_child6 (a int, b int) distribute by hash (b);
 +alter table xl_child6 distribute by hash (a);
 +alter table xl_child6 add column c text;
 +alter table xl_parent attach partition xl_child6 for values in (16, 17, 18);
 +create table xl_child7 (a int, b int);
 +alter table xl_child7 drop column b;
 +alter table xl_child7 add column b int;
 +alter table xl_child7 add column c text;
 +alter table xl_parent attach partition xl_child7 for values in (19, 20, 21);
 +insert into xl_parent values (1, 100, 'us');
 +insert into xl_parent values (4, 200, 'they');
 +insert into xl_parent values (6, 300, 'me');
 +insert into xl_parent values (11, 400, 'mine');
 +insert into xl_parent values (12, 500, 'theirs');
 +insert into xl_parent values (9, 600, 'ours');
 +ERROR:  no partition of relation "xl_parent" found for row
 +DETAIL:  Partition key of the failing row contains (a) = (9).
 +insert into xl_parent values (13, 700, 'yours');
 +insert into xl_parent values (16, 800, 'my');
 +insert into xl_parent values (19, 900, 'his');
 +select * from xl_parent order by a;
 + a  |  b  |   c    
 +----+-----+--------
 +  1 | 100 | us
 +  4 | 200 | they
 +  6 | 300 | me
 + 11 | 400 | mine
 + 12 | 500 | theirs
 + 13 | 700 | yours
 + 16 | 800 | my
 + 19 | 900 | his
 +(8 rows)
 +
 +select * from xl_parent where a = 1;
 + a |  b  | c  
 +---+-----+----
 + 1 | 100 | us
 +(1 row)
 +
 +select * from xl_parent where a = 10;
 + a | b | c 
 +---+---+---
 +(0 rows)
 +
 +select * from xl_parent where a = 4;
 + a |  b  |  c   
 +---+-----+------
 + 4 | 200 | they
 +(1 row)
 +
 +select * from xl_parent where a = 13;
 + a  |  b  |   c   
 +----+-----+-------
 + 13 | 700 | yours
 +(1 row)
 +
 +drop table xl_parent;
 +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b);
 +create table xl_c1 (a int, b int, c text);
 +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3);
 +ERROR:  table "xl_c1" is distributed on column "a" at position 2, but the parent table "xl_parted" is distributed on column "b" at position 1
 +DETAIL:  Distribution column for the child must be same as the parent
 +drop table xl_c1;
 +create table xl_c1 (a int, b int, c text) distribute by hash (b);
 +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3);
 +insert into xl_parted values (100, 1, 'foo');
 +insert into xl_parted values (200, 3, 'bar');
 +alter table xl_parted drop column a;
 +create table xl_c2 (b int, c text);
 +-- fails
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +ERROR:  table "xl_c2" is distributed on column "b" at position 2, but the parent table "xl_parted" is distributed on column "b" at position 1
 +DETAIL:  Distribution column for the child must be same as the parent
 +insert into xl_parted values (5, 'baz');
 +ERROR:  no partition of relation "xl_parted" found for row
 +DETAIL:  Partition key of the failing row contains (b) = (5).
 +-- since attach failed above
 +drop table xl_c2;
 +create table xl_c2 (a int, b text, c text) distribute by hash (b);
 +alter table xl_c2 drop column a;
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +ERROR:  child table "xl_c2" has different type for column "b"
 +-- since attach failed above
 +drop table xl_c2;
 +create table xl_c2 (a int, b int, c text) distribute by hash (b);
 +alter table xl_c2 drop column a;
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +insert into xl_parted values (5, 'baz');
 +select * from xl_parted;
 + b |  c  
 +---+-----
 + 1 | foo
 + 5 | baz
 + 3 | bar
 +(3 rows)
 +
 +drop table xl_parted;
index 6e3ec8046aaba47fc26964ff5676734da50c13b8,481510c2bb10f5303aa4c3b6fc06a59d6efb7d23..92d756e54f00a4ccd77a447da2764fa6bf5a8588
@@@ -856,19 -830,19 +856,35 @@@ ERROR:  cannot create a temporary relat
  create temp table temp_part partition of temp_parted for values in (1, 2); -- ok
  drop table perm_parted cascade;
  drop table temp_parted cascade;
+ -- check that adding partitions to a table while it is being used is prevented
+ create table tab_part_create (a int) partition by list (a);
+ create or replace function func_part_create() returns trigger
+   language plpgsql as $$
+   begin
+     execute 'create table tab_part_create_1 partition of tab_part_create for values in (1)';
+     return null;
+   end $$;
+ create trigger trig_part_create before insert on tab_part_create
+   for each statement execute procedure func_part_create();
+ insert into tab_part_create values (1);
+ ERROR:  cannot CREATE TABLE .. PARTITION OF "tab_part_create" because it is being used by active queries in this session
+ CONTEXT:  SQL statement "create table tab_part_create_1 partition of tab_part_create for values in (1)"
+ PL/pgSQL function func_part_create() line 3 at EXECUTE
+ drop table tab_part_create;
+ drop function func_part_create();
 +-- xl tests
 +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b);
 +create table xl_c1 partition of xl_parted for values in (1, 2, 3);
 +insert into xl_parted values (100, 1, 'foo');
 +insert into xl_parted values (200, 3, 'bar');
 +alter table xl_parted drop column a;
 +create table xl_c2 partition of xl_parted for values in (4, 5, 6);
 +insert into xl_parted values (1, 'foo');
 +insert into xl_parted values (3, 'bar');
 +insert into xl_parted values (5, 'baz');
 +-- syntax error
 +create table xl_c3 partition of xl_parted for values in (4, 5, 6) distribute by hash (b);
 +ERROR:  syntax error at or near "distribute"
 +LINE 1: ...c3 partition of xl_parted for values in (4, 5, 6) distribute...
 +                                                             ^
 +drop table xl_parted;
index 085eb207b91a2faf26960dc463bc435d03dab485,9f22a6501277bf45c7ee0ceaf4c3937f641a1a01..b0615594accf77ad43705525fea2104ccd44e0c4
@@@ -283,17 -331,45 +283,40 @@@ CREATE SCHEMA evttri
        CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two')
        CREATE INDEX one_idx ON one (col_b)
        CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42);
+ -- Partitioned tables
+ CREATE TABLE evttrig.parted (
+     id int)
+     PARTITION BY RANGE (id);
+ CREATE TABLE evttrig.part_1_10 PARTITION OF evttrig.parted (id)
+   FOR VALUES FROM (1) TO (10);
+ CREATE TABLE evttrig.part_10_20 PARTITION OF evttrig.parted (id)
+   FOR VALUES FROM (10) TO (20) PARTITION BY RANGE (id);
+ CREATE TABLE evttrig.part_10_15 PARTITION OF evttrig.part_10_20 (id)
+   FOR VALUES FROM (10) TO (15);
+ CREATE TABLE evttrig.part_15_20 PARTITION OF evttrig.part_10_20 (id)
+   FOR VALUES FROM (15) TO (20);
  ALTER TABLE evttrig.two DROP COLUMN col_c;
 -NOTICE:  NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.two.col_c name={evttrig,two,col_c} args={}
 -NOTICE:  NORMAL: orig=f normal=t istemp=f type=table constraint identity=two_col_c_check on evttrig.two name={evttrig,two,two_col_c_check} args={}
  ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT;
 -NOTICE:  NORMAL: orig=t normal=f istemp=f type=default value identity=for evttrig.one.col_b name={evttrig,one,col_b} args={}
  ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey;
 -NOTICE:  NORMAL: orig=t normal=f istemp=f type=table constraint identity=one_pkey on evttrig.one name={evttrig,one,one_pkey} args={}
  DROP INDEX evttrig.one_idx;
 -NOTICE:  NORMAL: orig=t normal=f istemp=f type=index identity=evttrig.one_idx name={evttrig,one_idx} args={}
  DROP SCHEMA evttrig CASCADE;
- NOTICE:  drop cascades to 2 other objects
+ NOTICE:  drop cascades to 3 other objects
  DETAIL:  drop cascades to table evttrig.one
  drop cascades to table evttrig.two
+ drop cascades to table evttrig.parted
+ NOTICE:  NORMAL: orig=t normal=f istemp=f type=schema identity=evttrig name={evttrig} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.one name={evttrig,one} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=sequence identity=evttrig.one_col_a_seq name={evttrig,one_col_a_seq} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_a name={evttrig,one,col_a} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.two name={evttrig,two} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.parted name={evttrig,parted} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_1_10 name={evttrig,part_1_10} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_10_20 name={evttrig,part_10_20} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_10_15 name={evttrig,part_10_15} args={}
+ NOTICE:  NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_15_20 name={evttrig,part_15_20} args={}
  DROP TABLE a_temp_tbl;
 -NOTICE:  NORMAL: orig=t normal=f istemp=t type=table identity=pg_temp.a_temp_tbl name={pg_temp,a_temp_tbl} args={}
  DROP EVENT TRIGGER regress_event_trigger_report_dropped;
 +ERROR:  event trigger "regress_event_trigger_report_dropped" does not exist
  -- only allowed from within an event trigger function, should fail
  select pg_event_trigger_table_rewrite_oid();
  ERROR:  pg_event_trigger_table_rewrite_oid() can only be called in a table_rewrite event trigger function
index 50e7ab17b66efefb473716865de58328746353d9,70c6fe43eb1a9539a4d59098ece88453b59255e9..fa84891def1409329113a5aa94d2b55173726563
@@@ -580,35 -564,97 +580,107 @@@ reset role
  set force_parallel_mode=1;
  explain (costs off)
    select stringu1::int2 from tenk1 where unique1 = 1;
 -                  QUERY PLAN                   
 ------------------------------------------------
 - Gather
 -   Workers Planned: 1
 -   Single Copy: true
 -   ->  Index Scan using tenk1_unique1 on tenk1
 -         Index Cond: (unique1 = 1)
 -(5 rows)
 +                     QUERY PLAN                      
 +-----------------------------------------------------
 + Remote Fast Query Execution
 +   Node/s: datanode_1
 +   ->  Gather
 +         Workers Planned: 1
 +         Single Copy: true
 +         ->  Index Scan using tenk1_unique1 on tenk1
 +               Index Cond: (unique1 = 1)
 +(7 rows)
  
+ -- Window function calculation can't be pushed to workers.
+ explain (costs off, verbose)
+   select count(*) from tenk1 a where (unique1, two) in
+     (select unique1, row_number() over() from tenk1 b);
+                                           QUERY PLAN                                          
+ ----------------------------------------------------------------------------------------------
+  Aggregate
+    Output: count(*)
+    ->  Hash Semi Join
+          Hash Cond: ((a.unique1 = b.unique1) AND (a.two = (row_number() OVER (?))))
+          ->  Gather
+                Output: a.unique1, a.two
+                Workers Planned: 4
+                ->  Parallel Seq Scan on public.tenk1 a
+                      Output: a.unique1, a.two
+          ->  Hash
+                Output: b.unique1, (row_number() OVER (?))
+                ->  WindowAgg
+                      Output: b.unique1, row_number() OVER (?)
+                      ->  Gather
+                            Output: b.unique1
+                            Workers Planned: 4
+                            ->  Parallel Index Only Scan using tenk1_unique1 on public.tenk1 b
+                                  Output: b.unique1
+ (18 rows)
+ -- LIMIT/OFFSET within sub-selects can't be pushed to workers.
+ explain (costs off)
+   select * from tenk1 a where two in
+     (select two from tenk1 b where stringu1 like '%AAAA' limit 3);
+                           QUERY PLAN                           
+ ---------------------------------------------------------------
+  Hash Semi Join
+    Hash Cond: (a.two = b.two)
+    ->  Gather
+          Workers Planned: 4
+          ->  Parallel Seq Scan on tenk1 a
+    ->  Hash
+          ->  Limit
+                ->  Gather
+                      Workers Planned: 4
+                      ->  Parallel Seq Scan on tenk1 b
+                            Filter: (stringu1 ~~ '%AAAA'::text)
+ (11 rows)
  -- to increase the parallel query test coverage
 +EXPLAIN (timing off, summary off, costs off) SELECT * FROM tenk1;
 +               QUERY PLAN               
 +----------------------------------------
 + Remote Fast Query Execution
 +   Node/s: datanode_1, datanode_2
 +   ->  Gather
 +         Workers Planned: 4
 +         ->  Parallel Seq Scan on tenk1
 +(5 rows)
 +
  EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1;
 -                         QUERY PLAN                          
 --------------------------------------------------------------
 - Gather (actual rows=10000 loops=1)
 -   Workers Planned: 4
 -   Workers Launched: 4
 -   ->  Parallel Seq Scan on tenk1 (actual rows=2000 loops=5)
 -(4 rows)
 +                       QUERY PLAN                        
 +---------------------------------------------------------
 + Remote Fast Query Execution (actual rows=10000 loops=1)
 +   Node/s: datanode_1, datanode_2
 +(2 rows)
  
+ -- test passing expanded-value representations to workers
+ CREATE FUNCTION make_some_array(int,int) returns int[] as
+ $$declare x int[];
+   begin
+     x[1] := $1;
+     x[2] := $2;
+     return x;
+   end$$ language plpgsql parallel safe;
+ CREATE TABLE fooarr(f1 text, f2 int[], f3 text);
+ INSERT INTO fooarr VALUES('1', ARRAY[1,2], 'one');
+ PREPARE pstmt(text, int[]) AS SELECT * FROM fooarr WHERE f1 = $1 AND f2 = $2;
+ EXPLAIN (COSTS OFF) EXECUTE pstmt('1', make_some_array(1,2));
+                             QUERY PLAN                            
+ ------------------------------------------------------------------
+  Gather
+    Workers Planned: 3
+    ->  Parallel Seq Scan on fooarr
+          Filter: ((f1 = '1'::text) AND (f2 = '{1,2}'::integer[]))
+ (4 rows)
+ EXECUTE pstmt('1', make_some_array(1,2));
+  f1 |  f2   | f3  
+ ----+-------+-----
+  1  | {1,2} | one
+ (1 row)
+ DEALLOCATE pstmt;
  -- provoke error in worker
  select stringu1::int2 from tenk1 where unique1 = 1;
  ERROR:  invalid input syntax for integer: "BAAAAA"
Simple merge
Simple merge
Simple merge
index 67ca7f206f3b5ccb6d26b172b100a5b6df805372,e79b402a322865d967c99dce6ce97dc96e32cf35..304c3f7bdfb2ff1c7082b661a819f5cdf77fda8c
@@@ -2407,79 -2389,34 +2407,110 @@@ alter table temp_part_parent attach par
  drop table perm_part_parent cascade;
  drop table temp_part_parent cascade;
  
+ -- check that attaching partitions to a table while it is being used is
+ -- prevented
+ create table tab_part_attach (a int) partition by list (a);
+ create or replace function func_part_attach() returns trigger
+   language plpgsql as $$
+   begin
+     execute 'create table tab_part_attach_1 (a int)';
+     execute 'alter table tab_part_attach attach partition tab_part_attach_1 for values in (1)';
+     return null;
+   end $$;
+ create trigger trig_part_attach before insert on tab_part_attach
+   for each statement execute procedure func_part_attach();
+ insert into tab_part_attach values (1);
+ drop table tab_part_attach;
+ drop function func_part_attach();
+ -- test case where the partitioning operator is a SQL function whose
+ -- evaluation results in the table's relcache being rebuilt partway through
+ -- the execution of an ATTACH PARTITION command
+ create function at_test_sql_partop (int4, int4) returns int language sql
+ as $$ select case when $1 = $2 then 0 when $1 > $2 then 1 else -1 end; $$;
+ create operator class at_test_sql_partop for type int4 using btree as
+     operator 1 < (int4, int4), operator 2 <= (int4, int4),
+     operator 3 = (int4, int4), operator 4 >= (int4, int4),
+     operator 5 > (int4, int4), function 1 at_test_sql_partop(int4, int4);
+ create table at_test_sql_partop (a int) partition by range (a at_test_sql_partop);
+ create table at_test_sql_partop_1 (a int);
+ alter table at_test_sql_partop attach partition at_test_sql_partop_1 for values from (0) to (10);
+ drop table at_test_sql_partop;
+ drop operator class at_test_sql_partop using btree;
+ drop function at_test_sql_partop;
 +-- xl tests
 +create table xl_parent (a int, b int, c text) partition by list (a);
 +-- create a partition
 +create table xl_child1 partition of xl_parent for values in (1, 2, 3);
 +
 +-- attach a partition
 +create table xl_child2 (a int, b int, c text);
 +alter table xl_parent attach partition xl_child2 for values in (4, 5, 6);
 +
 +-- attach a partition, distribution column position does not match
 +create table xl_child3 (b int, a int, c text) distribute by hash (a);
 +alter table xl_parent attach partition xl_child3 for values in (7, 8, 9);
 +
 +-- attach a partition, distribution column position matches, others do not
 +create table xl_child4 (a int, c text, b int) distribute by hash (a);
 +alter table xl_parent attach partition xl_child4 for values in (10, 11, 12);
 +
 +create table xl_child5 (a int) distribute by hash (a);
 +alter table xl_child5 add column c text;
 +alter table xl_child5 add column b int;
 +alter table xl_parent attach partition xl_child5 for values in (13, 14, 15);
 +
 +create table xl_child6 (a int, b int) distribute by hash (b);
 +alter table xl_child6 distribute by hash (a);
 +alter table xl_child6 add column c text;
 +alter table xl_parent attach partition xl_child6 for values in (16, 17, 18);
 +
 +create table xl_child7 (a int, b int);
 +alter table xl_child7 drop column b;
 +alter table xl_child7 add column b int;
 +alter table xl_child7 add column c text;
 +alter table xl_parent attach partition xl_child7 for values in (19, 20, 21);
 +
 +insert into xl_parent values (1, 100, 'us');
 +insert into xl_parent values (4, 200, 'they');
 +insert into xl_parent values (6, 300, 'me');
 +insert into xl_parent values (11, 400, 'mine');
 +insert into xl_parent values (12, 500, 'theirs');
 +insert into xl_parent values (9, 600, 'ours');
 +insert into xl_parent values (13, 700, 'yours');
 +insert into xl_parent values (16, 800, 'my');
 +insert into xl_parent values (19, 900, 'his');
 +
 +select * from xl_parent order by a;
 +select * from xl_parent where a = 1;
 +select * from xl_parent where a = 10;
 +select * from xl_parent where a = 4;
 +select * from xl_parent where a = 13;
 +drop table xl_parent;
 +
 +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b);
 +create table xl_c1 (a int, b int, c text);
 +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3);
 +drop table xl_c1;
 +create table xl_c1 (a int, b int, c text) distribute by hash (b);
 +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3);
 +insert into xl_parted values (100, 1, 'foo');
 +insert into xl_parted values (200, 3, 'bar');
 +alter table xl_parted drop column a;
 +create table xl_c2 (b int, c text);
 +-- fails
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +insert into xl_parted values (5, 'baz');
 +-- since attach failed above
 +drop table xl_c2;
 +create table xl_c2 (a int, b text, c text) distribute by hash (b);
 +alter table xl_c2 drop column a;
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +-- since attach failed above
 +drop table xl_c2;
 +create table xl_c2 (a int, b int, c text) distribute by hash (b);
 +alter table xl_c2 drop column a;
 +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6);
 +insert into xl_parted values (5, 'baz');
 +select * from xl_parted;
 +drop table xl_parted;
index 412405c8987e1828ef9256cfa72a3cf57e381edb,bc6191f4acea0b926825cd4e97f22408ee6abdcf..ba5228759cf5cb6d6ea093bbd9c6ba6407be7d75
@@@ -679,16 -680,16 +679,29 @@@ create temp table temp_part partition o
  drop table perm_parted cascade;
  drop table temp_parted cascade;
  
+ -- check that adding partitions to a table while it is being used is prevented
+ create table tab_part_create (a int) partition by list (a);
+ create or replace function func_part_create() returns trigger
+   language plpgsql as $$
+   begin
+     execute 'create table tab_part_create_1 partition of tab_part_create for values in (1)';
+     return null;
+   end $$;
+ create trigger trig_part_create before insert on tab_part_create
+   for each statement execute procedure func_part_create();
+ insert into tab_part_create values (1);
+ drop table tab_part_create;
+ drop function func_part_create();
 +-- xl tests
 +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b);
 +create table xl_c1 partition of xl_parted for values in (1, 2, 3);
 +insert into xl_parted values (100, 1, 'foo');
 +insert into xl_parted values (200, 3, 'bar');
 +alter table xl_parted drop column a;
 +create table xl_c2 partition of xl_parted for values in (4, 5, 6);
 +insert into xl_parted values (1, 'foo');
 +insert into xl_parted values (3, 'bar');
 +insert into xl_parted values (5, 'baz');
 +-- syntax error
 +create table xl_c3 partition of xl_parted for values in (4, 5, 6) distribute by hash (b);
 +drop table xl_parted;
Simple merge
Simple merge
Simple merge
Simple merge
index 34c53d6424011bb9d801d415f9803a301c6db267,8225719ff35e0bd5fa2477aae091c99300f4bd74..203884ea7ee846ad0bc487c9412b9a666c6e3ef2
@@@ -203,11 -204,36 +203,38 @@@ set force_parallel_mode=1
  explain (costs off)
    select stringu1::int2 from tenk1 where unique1 = 1;
  
+ -- Window function calculation can't be pushed to workers.
+ explain (costs off, verbose)
+   select count(*) from tenk1 a where (unique1, two) in
+     (select unique1, row_number() over() from tenk1 b);
+ -- LIMIT/OFFSET within sub-selects can't be pushed to workers.
+ explain (costs off)
+   select * from tenk1 a where two in
+     (select two from tenk1 b where stringu1 like '%AAAA' limit 3);
  -- to increase the parallel query test coverage
 +EXPLAIN (timing off, summary off, costs off) SELECT * FROM tenk1;
 +
  EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1;
  
+ -- test passing expanded-value representations to workers
+ CREATE FUNCTION make_some_array(int,int) returns int[] as
+ $$declare x int[];
+   begin
+     x[1] := $1;
+     x[2] := $2;
+     return x;
+   end$$ language plpgsql parallel safe;
+ CREATE TABLE fooarr(f1 text, f2 int[], f3 text);
+ INSERT INTO fooarr VALUES('1', ARRAY[1,2], 'one');
+ PREPARE pstmt(text, int[]) AS SELECT * FROM fooarr WHERE f1 = $1 AND f2 = $2;
+ EXPLAIN (COSTS OFF) EXECUTE pstmt('1', make_some_array(1,2));
+ EXECUTE pstmt('1', make_some_array(1,2));
+ DEALLOCATE pstmt;
  -- provoke error in worker
  select stringu1::int2 from tenk1 where unique1 = 1;
  
Simple merge
Simple merge
Simple merge