Merge PG10 master branch into xl10devel
authorPavan Deolasee <pavan.deolasee@gmail.com>
Tue, 27 Jun 2017 11:23:19 +0000 (16:53 +0530)
committerPavan Deolasee <pavan.deolasee@gmail.com>
Tue, 27 Jun 2017 11:23:19 +0000 (16:53 +0530)
This commit merges PG10 branch upto commit
2710ccd782d0308a3fa1ab193531183148e9b626. Regression tests show no noteworthy
additional failures. This merge includes major pgindent work done with the
newer version of pgindent

260 files changed:
1  2 
configure
configure.in
contrib/hstore/hstore_io.c
contrib/pg_stat_statements/pg_stat_statements.c
contrib/sepgsql/hooks.c
doc/src/sgml/config.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/func.sgml
doc/src/sgml/high-availability.sgml
doc/src/sgml/maintenance.sgml
doc/src/sgml/perform.sgml
doc/src/sgml/plperl.sgml
doc/src/sgml/pltcl.sgml
doc/src/sgml/ref/create_function.sgml
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/explain.sgml
doc/src/sgml/ref/load.sgml
doc/src/sgml/ref/pgupgrade.sgml
doc/src/sgml/xfunc.sgml
src/backend/access/common/heaptuple.c
src/backend/access/hash/hashfunc.c
src/backend/access/heap/heapam.c
src/backend/access/heap/pruneheap.c
src/backend/access/heap/tuptoaster.c
src/backend/access/rmgrdesc/xactdesc.c
src/backend/access/transam/clog.c
src/backend/access/transam/commit_ts.c
src/backend/access/transam/parallel.c
src/backend/access/transam/slru.c
src/backend/access/transam/twophase.c
src/backend/access/transam/varsup.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogutils.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/namespace.c
src/backend/catalog/objectaddress.c
src/backend/catalog/pg_proc.c
src/backend/catalog/storage.c
src/backend/commands/analyze.c
src/backend/commands/cluster.c
src/backend/commands/copy.c
src/backend/commands/dbcommands.c
src/backend/commands/event_trigger.c
src/backend/commands/explain.c
src/backend/commands/extension.c
src/backend/commands/foreigncmds.c
src/backend/commands/indexcmds.c
src/backend/commands/matview.c
src/backend/commands/portalcmds.c
src/backend/commands/prepare.c
src/backend/commands/schemacmds.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/tablespace.c
src/backend/commands/trigger.c
src/backend/commands/vacuum.c
src/backend/commands/variable.c
src/backend/commands/view.c
src/backend/executor/execCurrent.c
src/backend/executor/execMain.c
src/backend/executor/execProcnode.c
src/backend/executor/execTuples.c
src/backend/executor/execUtils.c
src/backend/executor/functions.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeModifyTable.c
src/backend/executor/nodeNestloop.c
src/backend/executor/nodeWindowAgg.c
src/backend/executor/spi.c
src/backend/libpq/be-fsstubs.c
src/backend/main/main.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/makefuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepjointree.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/util/relnode.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_agg.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/parser/parse_utilcmd.c
src/backend/postmaster/autovacuum.c
src/backend/postmaster/pgstat.c
src/backend/postmaster/postmaster.c
src/backend/replication/logical/decode.c
src/backend/replication/logical/logicalfuncs.c
src/backend/replication/syncrep.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rowsecurity.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/file/fd.c
src/backend/storage/ipc/procarray.c
src/backend/storage/lmgr/lock.c
src/backend/storage/lmgr/lwlock.c
src/backend/storage/lmgr/predicate.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/tcop/pquery.c
src/backend/tcop/utility.c
src/backend/utils/adt/array_userfuncs.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/date.c
src/backend/utils/adt/dbsize.c
src/backend/utils/adt/jsonb.c
src/backend/utils/adt/lockfuncs.c
src/backend/utils/adt/misc.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/rowtypes.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/varlena.c
src/backend/utils/cache/inval.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/plancache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/syscache.c
src/backend/utils/error/elog.c
src/backend/utils/init/globals.c
src/backend/utils/init/miscinit.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/backend/utils/mmgr/mcxt.c
src/backend/utils/resowner/resowner.c
src/backend/utils/sort/tuplesort.c
src/backend/utils/sort/tuplestore.c
src/backend/utils/time/combocid.c
src/backend/utils/time/snapmgr.c
src/backend/utils/time/tqual.c
src/bin/initdb/initdb.c
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/pg_dumpall.c
src/bin/pg_rewind/filemap.c
src/bin/pgbench/pgbench.c
src/bin/psql/command.c
src/bin/psql/describe.c
src/bin/psql/startup.c
src/bin/psql/tab-complete.c
src/include/access/hash.h
src/include/access/htup.h
src/include/access/sysattr.h
src/include/access/transam.h
src/include/access/twophase.h
src/include/access/xact.h
src/include/access/xlog.h
src/include/bootstrap/bootstrap.h
src/include/c.h
src/include/catalog/catalog.h
src/include/catalog/dependency.h
src/include/catalog/heap.h
src/include/catalog/indexing.h
src/include/catalog/namespace.h
src/include/catalog/pg_class.h
src/include/catalog/pg_namespace.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/commands/dbcommands.h
src/include/commands/explain.h
src/include/commands/prepare.h
src/include/commands/schemacmds.h
src/include/commands/sequence.h
src/include/commands/tablecmds.h
src/include/commands/trigger.h
src/include/commands/vacuum.h
src/include/commands/variable.h
src/include/common/relpath.h
src/include/executor/execdesc.h
src/include/executor/executor.h
src/include/executor/spi.h
src/include/executor/tuptable.h
src/include/libpq/libpq-be.h
src/include/miscadmin.h
src/include/nodes/bitmapset.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/params.h
src/include/nodes/parsenodes.h
src/include/nodes/pg_list.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h
src/include/optimizer/cost.h
src/include/optimizer/pathnode.h
src/include/optimizer/planmain.h
src/include/optimizer/planner.h
src/include/parser/analyze.h
src/include/parser/parse_agg.h
src/include/parser/parse_func.h
src/include/parser/parse_relation.h
src/include/parser/parse_utilcmd.h
src/include/pg_config.h.win32
src/include/pgstat.h
src/include/port.h
src/include/postgres.h
src/include/postmaster/autovacuum.h
src/include/rewrite/rewriteHandler.h
src/include/storage/backendid.h
src/include/storage/lock.h
src/include/storage/lwlock.h
src/include/storage/proc.h
src/include/storage/procarray.h
src/include/storage/procsignal.h
src/include/storage/relfilenode.h
src/include/storage/smgr.h
src/include/tcop/dest.h
src/include/tcop/pquery.h
src/include/tcop/tcopprot.h
src/include/tcop/utility.h
src/include/utils/builtins.h
src/include/utils/elog.h
src/include/utils/guc.h
src/include/utils/guc_tables.h
src/include/utils/lsyscache.h
src/include/utils/plancache.h
src/include/utils/portal.h
src/include/utils/rel.h
src/include/utils/resowner_private.h
src/include/utils/snapshot.h
src/include/utils/syscache.h
src/include/utils/timestamp.h
src/include/utils/tuplesort.h
src/include/utils/tuplestore.h
src/interfaces/libpq/fe-auth.c
src/pl/plpgsql/src/pl_exec.c
src/test/regress/expected/join.out
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/rules.out
src/test/regress/expected/sequence.out
src/test/regress/parallel_schedule
src/test/regress/pg_regress.c
src/test/regress/serial_schedule
src/test/regress/sql/join.sql
src/test/regress/sql/opr_sanity.sql
src/test/regress/sql/rules.sql
src/test/regress/sql/sequence.sql

diff --cc configure
Simple merge
diff --cc configure.in
Simple merge
Simple merge
Simple merge
Simple merge
index a70047b34052124a72d66527078dcbd60cfbf255,b05a9c21500a57ae13a559b73f97653201e1737f..7449e064ac400ae576900a0f6166b4c831084c7b
mode 100755,100644..100755
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5a3821b25e89448eab4645ef0703a08b45777353,b15c19d3d0c32c5730c5b20114861c60ec596657..c799984f3b27d1335bc0b7d60ed4abe131591913
mode 100755,100644..100755
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 05fd37266436d323360abc000bd2861cd138b924,9766723deb3784170b37b368b5d46ddf608cadf9..42484f509c112869c6d224d8033502231d6bd488
@@@ -2636,11 -2623,8 +2636,11 @@@ heap_prepare_insert(Relation relation, 
                HeapTupleHeaderSetXminFrozen(tup->t_data);
  
        HeapTupleHeaderSetCmin(tup->t_data, cid);
-       HeapTupleHeaderSetXmax(tup->t_data, 0);         /* for cleanliness */
+       HeapTupleHeaderSetXmax(tup->t_data, 0); /* for cleanliness */
        tup->t_tableOid = RelationGetRelid(relation);
 +#ifdef PGXC
 +      tup->t_xc_node_id = PGXCNodeIdentifier;
 +#endif
  
        /*
         * If the new tuple is too big for storage or contains already toasted
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 3c1df5166eb323079f11ad82990f3230a18d5c8e,ba03d9687e566dcddc78a6ac357c0abd42b43ba2..12729111d395bc270906b9f39a992e0ba9c3a9ef
@@@ -625,21 -616,10 +625,21 @@@ LockGXact(const char *gid, Oid user
  
        LWLockRelease(TwoPhaseStateLock);
  
-               ereport(ERROR,
-                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                errmsg("prepared transaction with identifier \"%s\" does not exist",
-                                               gid)));
 +#ifdef PGXC
 +      /*
 +       * In PGXC, if xc_maintenance_mode is on, COMMIT/ROLLBACK PREPARED may be issued to the
 +       * node where the given xid does not exist.
 +       */
 +      if (!xc_maintenance_mode)
 +      {
 +#endif
+       ereport(ERROR,
+                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                        errmsg("prepared transaction with identifier \"%s\" does not exist",
+                                       gid)));
 +#ifdef PGXC
 +      }
 +#endif
  
        /* NOTREACHED */
        return NULL;
Simple merge
index 481231d13ac63202463c7ced45697569d92e2d25,b0aa69fe4b43de546f0b4dedae97c313f2f4812f..f7eb077a7f0bc7816503e47ebdaa06ce10a80342
@@@ -215,15 -184,11 +215,15 @@@ typedef struct TransactionStateDat
        int                     maxChildXids;   /* allocated size of childXids[] */
        Oid                     prevUser;               /* previous CurrentUserId setting */
        int                     prevSecContext; /* previous SecurityRestrictionContext */
-       bool            prevXactReadOnly;               /* entry-time xact r/o state */
-       bool            startedInRecovery;              /* did we start in recovery? */
+       bool            prevXactReadOnly;       /* entry-time xact r/o state */
+       bool            startedInRecovery;      /* did we start in recovery? */
        bool            didLogXid;              /* has xid been included in WAL record? */
-       int                     parallelModeLevel;              /* Enter/ExitParallelMode counter */
-       struct TransactionStateData *parent;            /* back link to parent */
+       int                     parallelModeLevel;      /* Enter/ExitParallelMode counter */
+       struct TransactionStateData *parent;    /* back link to parent */
 +#ifdef XCP
 +      int                             waitedForXidsCount;     /* count of xids we waited to finish */
 +      TransactionId   *waitedForXids;         /* xids we waited to finish */
 +#endif
  } TransactionStateData;
  
  typedef TransactionStateData *TransactionState;
index a07bb572ea9944dbbb2927f6b219ba783b0c8db3,0a6314a64267a232d201b195c46944bb13e0b5c2..7d917dbe7002558faa0f80b45e76e35c364f8727
@@@ -5274,15 -5269,8 +5273,15 @@@ readRecoveryCommandFile(void
                                                                                                                Int32GetDatum(-1)));
                        ereport(DEBUG2,
                                        (errmsg_internal("recovery_target_time = '%s'",
-                                                                  timestamptz_to_str(recoveryTargetTime))));
+                                                                        timestamptz_to_str(recoveryTargetTime))));
                }
 +#ifdef PGXC
 +              else if (strcmp(item->name, "recovery_target_barrier") == 0)
 +              {
 +                      recoveryTarget = RECOVERY_TARGET_BARRIER;
 +                      recoveryTargetBarrierId = pstrdup(item->value);
 +              }
 +#endif
                else if (strcmp(item->name, "recovery_target_name") == 0)
                {
                        recoveryTarget = RECOVERY_TARGET_NAME;
@@@ -5659,18 -5642,14 +5658,18 @@@ recoveryStopsBefore(XLogReaderState *re
                recoveryStopTime = 0;
                recoveryStopName[0] = '\0';
                ereport(LOG,
-                        (errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
-                                        (uint32) (recoveryStopLSN >> 32),
-                                        (uint32) recoveryStopLSN)));
+                               (errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
+                                               (uint32) (recoveryStopLSN >> 32),
+                                               (uint32) recoveryStopLSN)));
                return true;
        }
 -
 +#ifdef PGXC
 +      /* Otherwise we only consider stopping before COMMIT, ABORT or BARRIER records. */
 +      if ((XLogRecGetRmid(record) != RM_XACT_ID) && (XLogRecGetRmid(record) != RM_BARRIER_ID))
 +#else         
        /* Otherwise we only consider stopping before COMMIT or ABORT records. */
        if (XLogRecGetRmid(record) != RM_XACT_ID)
 +#endif                
                return false;
  
        xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
index 7be0e30a748e79dec740e29b6f9806bef9db8a66,b3f0b3cc92271e58d0e7ceea26fcf61d0999860f..c949ac31a7ce6804689a5ada9467581684a41524
  #include "utils/relmapper.h"
  #include "utils/tqual.h"
  
- uint32                bootstrap_data_checksum_version = 0;            /* No checksum */
 +#ifdef PGXC
 +#include "nodes/nodes.h"
 +#include "pgxc/poolmgr.h"
 +#include "postmaster/clustermon.h"
 +#endif
 +
+ uint32                bootstrap_data_checksum_version = 0;    /* No checksum */
  
  
  #define ALLOC(t, c) \
Simple merge
Simple merge
index d0d208e98d90faff698a46a44aee040e7f5d892b,027abd56b0d1814a99fd65eb640f1457bba39371..feff80d834f2135ee6cfdce3e511d0f7d27c0a27
@@@ -1938,38 -1937,24 +1938,38 @@@ index_update_stats(Relation rel
  
                if (rd_rel->relkind != RELKIND_INDEX)
                        visibilitymap_count(rel, &relallvisible, NULL);
-               else    /* don't bother for indexes */
+               else                                    /* don't bother for indexes */
                        relallvisible = 0;
  
 -              if (rd_rel->relpages != (int32) relpages)
 -              {
 -                      rd_rel->relpages = (int32) relpages;
 -                      dirty = true;
 -              }
 -              if (rd_rel->reltuples != (float4) reltuples)
 -              {
 -                      rd_rel->reltuples = (float4) reltuples;
 -                      dirty = true;
 -              }
 -              if (rd_rel->relallvisible != (int32) relallvisible)
 -              {
 -                      rd_rel->relallvisible = (int32) relallvisible;
 -                      dirty = true;
 -              }
 +#ifdef XCP
 +                      /*
 +                       * Coordinator stats are populated using data from remote
 +                       * datanodes. Hence we must not use local information to set those
 +                       * stats
 +                       */
 +              if (!IS_PGXC_COORDINATOR || !rel->rd_locator_info)
 +#endif
 +                      if (rd_rel->relpages != (int32) relpages)
 +                      {
 +                              rd_rel->relpages = (int32) relpages;
 +                              dirty = true;
 +                      }
 +#ifdef XCP
 +              if (!IS_PGXC_COORDINATOR || !rel->rd_locator_info)
 +#endif
 +                      if (rd_rel->reltuples != (float4) reltuples)
 +                      {
 +                              rd_rel->reltuples = (float4) reltuples;
 +                              dirty = true;
 +                      }
 +#ifdef XCP
 +              if (!IS_PGXC_COORDINATOR || !rel->rd_locator_info)
 +#endif
 +                      if (rd_rel->relallvisible != (int32) relallvisible)
 +                      {
 +                              rd_rel->relallvisible = (int32) relallvisible;
 +                              dirty = true;
 +                      }
        }
  
        /*
Simple merge
Simple merge
index 0f7ab80f65a1a2e2ea2a2fbd4c10c98cdc2a2261,571856e5250aaa8dc758d2b2d5ba5060267ae832..3ba00c34cae8983366fea4c78c8f592d1a325249
@@@ -937,17 -931,9 +937,17 @@@ fmgr_sql_validator(PG_FUNCTION_ARGS
                                RawStmt    *parsetree = lfirst_node(RawStmt, lc);
                                List       *querytree_sublist;
  
 +#ifdef PGXC
 +                              /* Block CTAS in SQL functions */
 +                              if (IsA(parsetree, CreateTableAsStmt))
 +                                      ereport(ERROR,
 +                                                      (errcode(ERRCODE_SYNTAX_ERROR),
 +                                                      errmsg("In XC, SQL functions cannot contain utility statements")));
 +#endif
 +
                                querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
                                                                                                                                  prosrc,
-                                                                          (ParserSetupHook) sql_fn_parser_setup,
+                                                                                                                                 (ParserSetupHook) sql_fn_parser_setup,
                                                                                                                                  pinfo,
                                                                                                                                  NULL);
                                querytree_list = list_concat(querytree_list,
Simple merge
Simple merge
Simple merge
index 3ae52116f4eaead8bac5ce8f0fb820fc4b2a4501,3c399e29db5cd7653ae8a49e005dd904978b2fc5..3f692b644155182a261a4752258c50b9577386ba
@@@ -1792,32 -1697,8 +1792,32 @@@ BeginCopy(ParseState *pstate
        /* See Multibyte encoding comment above */
        cstate->encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY(cstate->file_encoding);
  
-       cstate->copy_dest = COPY_FILE;          /* default */
+       cstate->copy_dest = COPY_FILE;  /* default */
  
 +#ifdef PGXC
 +      /*
 +       * We are here just at copy begin process,
 +       * so only pick up the list of connections.
 +       */
 +      if (IS_PGXC_COORDINATOR)
 +      {
 +              RemoteCopyData *remoteCopyState = cstate->remoteCopyState;
 +
 +              /*
 +               * In the case of CopyOut, it is just necessary to pick up one node randomly.
 +               * This is done when rel_loc is found.
 +               */
 +              if (remoteCopyState && remoteCopyState->rel_loc)
 +              {
 +                      DataNodeCopyBegin(remoteCopyState);
 +                      if (!remoteCopyState->locator)
 +                              ereport(ERROR,
 +                                              (errcode(ERRCODE_CONNECTION_EXCEPTION),
 +                                               errmsg("Failed to initialize Datanodes for COPY")));
 +              }
 +      }
 +#endif
 +
        MemoryContextSwitchTo(oldcontext);
  
        return cstate;
index baeb8b591e457c331af9220f0430a34d0b469069,e138539035e08aaadfad133a209b88076b657eff..ce49f91166c7451e000def5e45ef71c49c6d09ba
@@@ -772,29 -751,10 +772,29 @@@ check_encoding_locale_matches(int encod
                                 errmsg("encoding \"%s\" does not match locale \"%s\"",
                                                pg_encoding_to_char(encoding),
                                                collate),
-                errdetail("The chosen LC_COLLATE setting requires encoding \"%s\".",
-                                  pg_encoding_to_char(collate_encoding))));
+                                errdetail("The chosen LC_COLLATE setting requires encoding \"%s\".",
+                                                  pg_encoding_to_char(collate_encoding))));
  }
  
 +#ifdef PGXC
 +/*
 + * Error cleanup callback for createdb. Aftec createdb() succeeds, the
 + * transaction can still be aborted due to other nodes. So on abort-transaction,
 + * this function is called to do the cleanup. This involves removing directories
 + * created after successful completion.
 + * Nothing to be done on commit.
 + */
 +static void
 +createdb_xact_callback(bool isCommit, void *arg)
 +{
 +      if (isCommit)
 +              return;
 +
 +      /* Throw away any successfully copied subdirectories */
 +      remove_dbtablespaces(*(Oid *) arg);
 +}
 +#endif
 +
  /* Error cleanup callback for createdb */
  static void
  createdb_failure_callback(int code, Datum arg)
@@@ -1605,16 -1472,11 +1605,16 @@@ AlterDatabase(ParseState *pstate, Alter
                if (list_length(stmt->options) != 1)
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                          errmsg("option \"%s\" cannot be specified with other options",
-                                         dtablespace->defname),
+                                        errmsg("option \"%s\" cannot be specified with other options",
+                                                       dtablespace->defname),
                                         parser_errposition(pstate, dtablespace->location)));
                /* this case isn't allowed within a transaction block */
 -              PreventTransactionChain(isTopLevel, "ALTER DATABASE SET TABLESPACE");
 +#ifdef PGXC
 +              /* ... but we allow it on remote nodes */
 +              if (IS_PGXC_LOCAL_COORDINATOR)
 +#endif
 +                      PreventTransactionChain(isTopLevel, "ALTER DATABASE SET TABLESPACE");
 +
                movedb(stmt->dbname, defGetString(dtablespace));
                return InvalidOid;
        }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 7c260082bdfbd8caa2ebed7c07f21bb7760b4023,7d9c769b062e189699eb179e13637ba348a4833a..a1de996723e2281a127a448b05ff7e79ca5603b6
@@@ -149,23 -138,18 +149,23 @@@ static List *on_commits = NIL
   * a pass determined by subcommand type.
   */
  
- #define AT_PASS_UNSET                 -1              /* UNSET will cause ERROR */
- #define AT_PASS_DROP                  0               /* DROP (all flavors) */
- #define AT_PASS_ALTER_TYPE            1               /* ALTER COLUMN TYPE */
- #define AT_PASS_OLD_INDEX             2               /* re-add existing indexes */
- #define AT_PASS_OLD_CONSTR            3               /* re-add existing constraints */
- #define AT_PASS_COL_ATTRS             4               /* set other column attributes */
+ #define AT_PASS_UNSET                 -1      /* UNSET will cause ERROR */
+ #define AT_PASS_DROP                  0       /* DROP (all flavors) */
+ #define AT_PASS_ALTER_TYPE            1       /* ALTER COLUMN TYPE */
+ #define AT_PASS_OLD_INDEX             2       /* re-add existing indexes */
+ #define AT_PASS_OLD_CONSTR            3       /* re-add existing constraints */
+ #define AT_PASS_COL_ATTRS             4       /* set other column attributes */
  /* We could support a RENAME COLUMN pass here, but not currently used */
- #define AT_PASS_ADD_COL                       5               /* ADD COLUMN */
- #define AT_PASS_ADD_INDEX             6               /* ADD indexes */
- #define AT_PASS_ADD_CONSTR            7               /* ADD constraints, defaults */
- #define AT_PASS_MISC                  8               /* other stuff */
+ #define AT_PASS_ADD_COL                       5       /* ADD COLUMN */
+ #define AT_PASS_ADD_INDEX             6       /* ADD indexes */
+ #define AT_PASS_ADD_CONSTR            7       /* ADD constraints, defaults */
+ #define AT_PASS_MISC                  8       /* other stuff */
 +#ifdef PGXC
- #define AT_PASS_DISTRIB                       9               /* Redistribution pass */
++#define AT_PASS_DISTRIB                       9       /* Redistribution pass */
 +#define AT_NUM_PASSES                 10
 +#else
  #define AT_NUM_PASSES                 9
 +#endif
  
  typedef struct AlteredTableInfo
  {
index dc4d3ab02de69bbd7dd1097f6158304fdf19c2f1,8559c3b6b36e69cf7b8977b2f676c9412859cb5f..8036d95ac922ae25d3f3d50a1b696cbfdaaa0aa7
@@@ -288,15 -282,7 +288,15 @@@ CreateTableSpace(CreateTableSpaceStmt *
         * reference the whole path here, but mkdir() uses the first two parts.
         */
        if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
-         OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
 +#ifdef PGXC
 +              /*
 +               * In Postgres-XC, node name is added in the tablespace folder name to
 +               * insure unique names for nodes sharing the same server.
 +               * So real format is PG_XXX_<nodename>/<dboid>/<relid>.<nnn>''
 +               */
 +              strlen(PGXCNodeName) + 1 +
 +#endif
+               OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                 errmsg("tablespace location \"%s\" is too long",
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index bb5c609e543583c33cc60189ad2b103a58c0420b,3630f5d96689d7dd1168596617c58ccee60d14ac..1e993742c23fd067aa5fb9671b05c59b1a874af5
@@@ -535,27 -531,9 +535,27 @@@ init_execution_state(List *queryTree_li
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                /* translator: %s is a SQL statement name */
-                                          errmsg("%s is not allowed in a non-volatile function",
-                                                         CreateCommandTag((Node *) stmt))));
+                                                errmsg("%s is not allowed in a non-volatile function",
+                                                               CreateCommandTag((Node *) stmt))));
  
 +#ifdef PGXC
 +                      if (IS_PGXC_LOCAL_COORDINATOR)
 +                      {
 +                              if (queryTree->commandType != CMD_UTILITY)
 +                              {
 +                                      /*
 +                                      * The parameterised queries in RemoteQuery nodes will be prepared
 +                                      * on the Datanode, and need parameter types for the same. Set the
 +                                      * parameter types and their number in all RemoteQuery nodes in the
 +                                      * plan
 +                                      */
 +                                      SetRemoteStatementName(((PlannedStmt *)stmt)->planTree, NULL,
 +                                                                                      fcache->pinfo->nargs,
 +                                                                                      fcache->pinfo->argtypes, 0);
 +                              }
 +                      }
 +#endif /* PGXC */
 +
                        if (IsInParallelMode() && !CommandIsReadOnly(stmt))
                                PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
  
Simple merge
Simple merge
Simple merge
index a9ce846540aa03c87a0382678f989894156e82ee,cd00a6d9f25e096fbd8f907cdc7d23830942dcd7..a168b63e267d9f0c6ae576926cc9a363806715c3
@@@ -1954,10 -1877,9 +1954,10 @@@ _SPI_prepare_oneshot_plan(const char *s
                RawStmt    *parsetree = lfirst_node(RawStmt, list_item);
                CachedPlanSource *plansource;
  
 +
                plansource = CreateOneShotCachedPlan(parsetree,
                                                                                         src,
-                                                                                 CreateCommandTag(parsetree->stmt));
+                                                                                        CreateCommandTag(parsetree->stmt));
  
                plancache_list = lappend(plancache_list, plansource);
        }
index 4773b18df966f68ef0a0f9b716ea5af62eda592e,b31c90fa24db9995bab99422c4862d9618a98f50..554977f190cacffb4c215c25decca2779731b2dc
@@@ -986,15 -868,8 +986,15 @@@ be_lo_from_bytea(PG_FUNCTION_ARGS
        Oid                     loOid = PG_GETARG_OID(0);
        bytea      *str = PG_GETARG_BYTEA_PP(1);
        LargeObjectDesc *loDesc;
-       int written PG_USED_FOR_ASSERTS_ONLY;
+       int                     written PG_USED_FOR_ASSERTS_ONLY;
  
 +#ifdef PGXC
 +      ereport(ERROR,
 +                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 +                       errmsg("Postgres-XL does not yet support large objects"),
 +                       errdetail("The feature is not currently supported")));
 +#endif
 +
        CreateFSContext();
  
        loOid = inv_create(loOid);
@@@ -1016,15 -891,8 +1016,15 @@@ be_lo_put(PG_FUNCTION_ARGS
        int64           offset = PG_GETARG_INT64(1);
        bytea      *str = PG_GETARG_BYTEA_PP(2);
        LargeObjectDesc *loDesc;
-       int written PG_USED_FOR_ASSERTS_ONLY;
+       int                     written PG_USED_FOR_ASSERTS_ONLY;
  
 +#ifdef PGXC
 +      ereport(ERROR,
 +                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 +                       errmsg("Postgres-XL does not yet support large objects"),
 +                       errdetail("The feature is not currently supported")));
 +#endif
 +
        CreateFSContext();
  
        loDesc = inv_open(loOid, INV_WRITE, fscxt);
index 78ee4cbc184b395a201cfd9b7a2125f154fe8b82,09f99486e01576f603c2f2f46be264f39be1ee69..60db834d3eb007deb9a5a270804533a6842ffb9e
@@@ -375,15 -374,8 +375,15 @@@ help(const char *progname
        printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
        printf(_("  -x NUM             internal use\n"));
  
 +#ifdef PGXC
 +      printf(_("\nNode options:\n"));
 +      printf(_("  --coordinator      start as a Coordinator\n"));
 +      printf(_("  --datanode         start as a Datanode\n"));
 +      printf(_("  --restoremode      start to restore existing schema on the new node to be added\n"));
 +#endif
 +
        printf(_("\nPlease read the documentation for the complete list of run-time\n"
-        "configuration settings and how to set them on the command line or in\n"
+                        "configuration settings and how to set them on the command line or in\n"
                         "the configuration file.\n\n"
                         "Report bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 3219d00240272e29ebfdfff2afaf031fcd4fb027,2988e8bd16d15829216acdfa7226d0c671e04798..157e88e4b816ce6af49f2d859063c6ce16ee4f8a
@@@ -801,14 -538,8 +800,14 @@@ _readConst(void
  
        token = pg_strtok(&length); /* skip :constvalue */
        if (local_node->constisnull)
-               token = pg_strtok(&length);             /* skip "<>" */
+               token = pg_strtok(&length); /* skip "<>" */
        else
 +#ifdef XCP
 +              if (portable_input)
 +                      local_node->constvalue = scanDatum(local_node->consttype,
 +                                                                                         local_node->consttypmod);
 +              else
 +#endif
                local_node->constvalue = readDatum(local_node->constbyval);
  
        READ_DONE();
index 196c6194cb39de7efbab5bec49596e679f4c2240,f087ddb61db8ae75781b674ba8f9cafb37621346..9ebe69ebad3057dc6bb357d8169138b99a1b2add
@@@ -1962,38 -1922,8 +1962,38 @@@ set_subquery_pathlist(PlannerInfo *root
                pathkeys = convert_subquery_pathkeys(root,
                                                                                         rel,
                                                                                         subpath->pathkeys,
-                                                       make_tlist_from_pathtarget(subpath->pathtarget));
+                                                                                        make_tlist_from_pathtarget(subpath->pathtarget));
  
 +              if (subroot->distribution && subroot->distribution->distributionExpr)
 +              {
 +                      ListCell *lc;
 +
 +                      /* FIXME Could we use pathtarget directly? */
 +                      List *targetlist = make_tlist_from_pathtarget(subpath->pathtarget);
 +
 +                      /*
 +                       * The distribution expression from the subplan's tlist, but it should
 +                       * be from the rel, need conversion.
 +                       */
 +                      distribution = makeNode(Distribution);
 +                      distribution->distributionType = subroot->distribution->distributionType;
 +                      distribution->nodes = bms_copy(subroot->distribution->nodes);
 +                      distribution->restrictNodes = bms_copy(subroot->distribution->restrictNodes);
 +
 +                      foreach(lc, targetlist)
 +                      {
 +                              TargetEntry *tle = (TargetEntry *) lfirst(lc);
 +                              if (equal(tle->expr, subroot->distribution->distributionExpr))
 +                              {
 +                                      distribution->distributionExpr = (Node *)
 +                                                      makeVarFromTargetEntry(rel->relid, tle);
 +                                      break;
 +                              }
 +                      }
 +              }
 +              else
 +                      distribution = subroot->distribution;
 +
                /* Generate outer path using this subpath */
                add_path(rel, (Path *)
                                 create_subqueryscan_path(root, rel, subpath,
Simple merge
index 5c833e933ddac07f26a8a20538e02253d27e1547,e589d92c80553acd99aa13f0b2c3f6f86211ba42..0d375b13c7b73781caa773d2fc0f0c36aeef3080
@@@ -6438,15 -5726,7 +6438,15 @@@ prepare_sort_from_pathkeys(Plan *lefttr
                                                                  NULL,
                                                                  true);
                        tlist = lappend(tlist, tle);
-                       lefttree->targetlist = tlist;           /* just in case NIL before */
+                       lefttree->targetlist = tlist;   /* just in case NIL before */
 +#ifdef XCP
 +                      /*
 +                       * RemoteSubplan is conditionally projection capable - it is
 +                       * pushing projection to the data nodes
 +                       */
 +                      if (IsA(lefttree, RemoteSubplan))
 +                              lefttree->lefttree->targetlist = tlist;
 +#endif
                }
  
                /*
Simple merge
Simple merge
Simple merge
index 0ccf4bd47da594e205f4233c5bf88d5a052ed35e,f2d6385f18353ad4e4bf93e2db1c26ac493b6c25..8d99cf9b34bd26b9fb70c7a0d0a54e0318f7b3e2
@@@ -2429,78 -1214,7 +2429,76 @@@ create_append_path(RelOptInfo *rel, Lis
        pathnode->path.parallel_aware = false;
        pathnode->path.parallel_safe = rel->consider_parallel;
        pathnode->path.parallel_workers = parallel_workers;
-       pathnode->path.pathkeys = NIL;          /* result is always considered
-                                                                                * unsorted */
+       pathnode->path.pathkeys = NIL;  /* result is always considered unsorted */
 +#ifdef XCP
 +      /*
 +       * Append path is used to implement scans of inherited tables and some
 +       * "set" operations, like UNION ALL. While all inherited tables should
 +       * have the same distribution, UNION'ed queries may have different.
 +       * When paths being appended have the same distribution it is OK to push
 +       * Append down to the data nodes. If not, perform "coordinator" Append.
 +       */
 +
 +      /* Special case of the dummy relation, if the subpaths list is empty */
 +      if (subpaths)
 +      {
 +              /* Take distribution of the first node */
 +              l = list_head(subpaths);
 +              subpath = (Path *) lfirst(l);
 +              distribution = copyObject(subpath->distribution);
 +              /*
 +               * Check remaining subpaths, if all distributions equal to the first set
 +               * it as a distribution of the Append path; otherwise make up coordinator
 +               * Append
 +               */
 +              while ((l = lnext(l)))
 +              {
 +                      subpath = (Path *) lfirst(l);
 +
 +                      /*
 +                       * For Append and MergeAppend paths, we are most often dealing with
 +                       * different relations, appended together. So its very likely that
 +                       * the distribution for each relation will have a different varno.
 +                       * But we should be able to push down Append and MergeAppend as
 +                       * long as rest of the distribution information matches.
 +                       *
 +                       * equalDistribution() compares everything except the varnos
 +                       */
 +                      if (equalDistribution(distribution, subpath->distribution))
 +                      {
 +                              /*
 +                               * Both distribution and subpath->distribution may be NULL at
 +                               * this point, or they both are not null.
 +                               */
 +                              if (distribution && subpath->distribution->restrictNodes)
 +                                      distribution->restrictNodes = bms_union(
 +                                                      distribution->restrictNodes,
 +                                                      subpath->distribution->restrictNodes);
 +                      }
 +                      else
 +                      {
 +                              break;
 +                      }
 +              }
 +              if (l)
 +              {
 +                      List *newsubpaths = NIL;
 +                      foreach(l, subpaths)
 +                      {
 +                              subpath = (Path *) lfirst(l);
 +                              if (subpath->distribution)
 +                                      subpath = redistribute_path(NULL, subpath, NIL,
 +                                                                                              LOCATOR_TYPE_NONE, NULL,
 +                                                                                              NULL, NULL);
 +                              newsubpaths = lappend(newsubpaths, subpath);
 +                      }
 +                      subpaths = newsubpaths;
 +                      pathnode->path.distribution = NULL;
 +              }
 +              else
 +                      pathnode->path.distribution = distribution;
 +      }
 +#endif
        pathnode->partitioned_rels = list_copy(partitioned_rels);
        pathnode->subpaths = subpaths;
  
@@@ -3109,11 -1742,8 +3107,11 @@@ create_gather_path(PlannerInfo *root, R
        pathnode->path.parallel_aware = false;
        pathnode->path.parallel_safe = false;
        pathnode->path.parallel_workers = 0;
-       pathnode->path.pathkeys = NIL;          /* Gather has unordered result */
+       pathnode->path.pathkeys = NIL;  /* Gather has unordered result */
  
 +      /* distribution is the same as in the subpath */
 +      pathnode->path.distribution = (Distribution *) copyObject(subpath->distribution);
 +
        pathnode->subpath = subpath;
        pathnode->num_workers = subpath->parallel_workers;
        pathnode->single_copy = false;
Simple merge
Simple merge
index 020d6f74c4b25884cce849bbccf90420bd7cc753,4fb793cfbf025400c44b431f580f5046ca598bbd..fb6250efb1cd7e04ba09ca296c17e3a7f2a29ea9
@@@ -347,16 -313,9 +347,16 @@@ transformStmt(ParseState *pstate, Node 
                                                                                  (ExplainStmt *) parseTree);
                        break;
  
 +#ifdef PGXC
 +              case T_ExecDirectStmt:
 +                      result = transformExecDirectStmt(pstate,
 +                                                                                       (ExecDirectStmt *) parseTree);
 +                      break;
 +#endif
 +
                case T_CreateTableAsStmt:
                        result = transformCreateTableAsStmt(pstate,
-                                                                                       (CreateTableAsStmt *) parseTree);
+                                                                                               (CreateTableAsStmt *) parseTree);
                        break;
  
                default:
Simple merge
index a95e34956291f9ad819a3a9b2bfc4448ee340348,613bdabd52071d66b87ec46be5bd4479946556de..a07274f77e3cd28b4044708d5cbdeba07a119c68
@@@ -1100,10 -1093,9 +1100,10 @@@ parseCheckAggregates(ParseState *pstate
                root->parse = qry;
                root->planner_cxt = CurrentMemoryContext;
                root->hasJoinRTEs = true;
 +              root->recursiveOk = true;
  
                groupClauses = (List *) flatten_join_alias_vars(root,
-                                                                                                         (Node *) groupClauses);
+                                                                                                               (Node *) groupClauses);
        }
  
        /*
Simple merge
Simple merge
index 8ae8b00236c35bce0c83b28cbab6e34d1a9b55bc,684a50d3df66af05baaae1cf7d753abb2b97b758..f2d4b21746e1484dd5788669ebf7515d7a8b3a2c
@@@ -1320,27 -1248,8 +1320,27 @@@ addRangeTableEntry(ParseState *pstate
        rte->inh = inh;
        rte->inFromCl = inFromCl;
  
 +#ifdef XCP
 +      /*
 +       * Ugly workaround against permission check error when non-privileged
 +       * user executes ANALYZE command.
 +       * To update local statistics coordinator queries pg_statistic tables on
 +       * datanodes, but these are not selectable by PUBLIC. It would be better
 +       * to define view, but pg_statistic contains fields of anyarray pseudotype
 +       * which is not allowed in view.
 +       * So we just disable check for SELECT permission if query referring the
 +       * pg_statistic table is parsed on datanodes. That might be a security hole,
 +       * but fortunately any user query against pg_statistic would be parsed on
 +       * coordinator, and permission check would take place; the only way to
 +       * have arbitrary query parsed on datanode is EXECUTE DIRECT, it is only
 +       * available for superuser.
 +       */
 +      if (IS_PGXC_DATANODE && rte->relid == StatisticRelationId)
 +              rte->requiredPerms = 0;
 +      else
 +#endif
        rte->requiredPerms = ACL_SELECT;
-       rte->checkAsUser = InvalidOid;          /* not set-uid by default, either */
+       rte->checkAsUser = InvalidOid;  /* not set-uid by default, either */
        rte->selectedCols = NULL;
        rte->insertedCols = NULL;
        rte->updatedCols = NULL;
Simple merge
index 5e1e89c979c4428d1b3cd6967b7657d376d8afe5,ee5f3a3a52cb3fafec046167d015d34d04557477..1cdeacf3b51d3443e53cfbe191e234be3fb4aec1
@@@ -114,14 -90,8 +114,14 @@@ typedef struc
        List       *alist;                      /* "after list" of things to do after creating
                                                                 * the table */
        IndexStmt  *pkey;                       /* PRIMARY KEY index, if any */
 +#ifdef PGXC
 +      FallbackSrc fallback_source;
 +      List       *fallback_dist_cols;
 +      DistributeBy    *distributeby;          /* original distribute by column of CREATE TABLE */
 +      PGXCSubCluster  *subcluster;            /* original subcluster option of CREATE TABLE */
 +#endif
        bool            ispartitioned;  /* true if table is partitioned */
-       PartitionBoundSpec *partbound;          /* transformed FOR VALUES */
+       PartitionBoundSpec *partbound;  /* transformed FOR VALUES */
  } CreateStmtContext;
  
  /* State shared by transformCreateSchemaStmt and its subroutines */
@@@ -167,16 -134,9 +167,16 @@@ static void transformConstraintAttrs(Cr
                                                 List *constraintList);
  static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
  static void setSchemaName(char *context_schema, char **stmt_schema_name);
 +#ifdef PGXC
 +static void checkLocalFKConstraints(CreateStmtContext *cxt);
 +#endif
 +#ifdef XCP
 +static List *transformSubclusterNodes(PGXCSubCluster *subcluster);
 +static PGXCSubCluster *makeSubCluster(List *nodelist);
 +#endif
  static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
  static Const *transformPartitionBoundValue(ParseState *pstate, A_Const *con,
-                                                 const char *colName, Oid colType, int32 colTypmod);
+                                                        const char *colName, Oid colType, int32 colTypmod);
  
  
  /*
Simple merge
Simple merge
index 1e511f4c1e86f882cba101b00a5cb19f9643f88d,2874f635af3d8db57950014780ef2110754f76f1..d25ea8826afe8fe4326308d50932e088f8e4a51d
@@@ -567,44 -541,8 +572,44 @@@ static bool save_backend_variables(Back
  
  static void ShmemBackendArrayAdd(Backend *bn);
  static void ShmemBackendArrayRemove(Backend *bn);
- #endif   /* EXEC_BACKEND */
+ #endif                                                        /* EXEC_BACKEND */
  
 +#ifdef XCP
 +char *parentPGXCNode = NULL;
 +int  parentPGXCNodeId = -1;
 +int    parentPGXCPid = -1;
 +char parentPGXCNodeType = PGXC_NODE_DATANODE;
 +#endif
 +
 +#ifdef PGXC
 +bool isPGXCCoordinator = false;
 +bool isPGXCDataNode = false;
 +
 +/*
 + * While adding a new node to the cluster we need to restore the schema of
 + * an existing database to the new node.
 + * If the new node is a datanode and we connect directly to it,
 + * it does not allow DDL, because it is in read only mode &
 + * If the new node is a coordinator it will send DDLs to all the other
 + * coordinators which we do not want it to do
 + * To provide ability to restore on the new node a new command line
 + * argument is provided called --restoremode
 + * It is to be provided in place of --coordinator OR --datanode.
 + * In restore mode both coordinator and datanode are internally
 + * treated as a datanode.
 + */
 +bool isRestoreMode = false;
 +
 +int remoteConnType = REMOTE_CONN_APP;
 +
 +/* key pair to be used as object id while using advisory lock for backup */
 +Datum xc_lockForBackupKey1;
 +Datum xc_lockForBackupKey2;
 +
 +#define StartPoolManager()            StartChildProcess(PoolerProcess)
 +#define StartClusterMonitor() StartChildProcess(ClusterMonitorProcess)
 +#endif
 +
  #define StartupDataBase()             StartChildProcess(StartupProcess)
  #define StartBackgroundWriter() StartChildProcess(BgWriterProcess)
  #define StartCheckpointer()           StartChildProcess(CheckpointerProcess)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0e0bbf71f00e6736399ac5efaeae2bfb227128e4,6eb7c72ec329aa0010fde9857786ec76297fcad4..fe0dabd90cae9e5f7e51eda63cc5a24db284f2c7
@@@ -169,36 -149,8 +169,36 @@@ static void DisplayXidCache(void)
  #define xc_by_known_assigned_inc()    ((void) 0)
  #define xc_no_overflow_inc()          ((void) 0)
  #define xc_slow_answer_inc()          ((void) 0)
- #endif   /* XIDCACHE_DEBUG */
+ #endif                                                        /* XIDCACHE_DEBUG */
  
 +#ifdef PGXC  /* PGXC_DATANODE */
 +
 +static bool GetPGXCSnapshotData(Snapshot snapshot, bool latest);
 +
 +typedef struct
 +{
 +      /* Global snapshot data */
 +      SnapshotSource snapshot_source;
 +      TransactionId gxmin;
 +      TransactionId gxmax;
 +      int gxcnt;
 +      int max_gxcnt;
 +      TransactionId *gxip;
 +} GlobalSnapshotData;
 +
 +GlobalSnapshotData globalSnapshot = {
 +      SNAPSHOT_UNDEFINED,
 +      InvalidTransactionId,
 +      InvalidTransactionId,
 +      0,
 +      0,
 +      NULL
 +};
 +
 +static void GetSnapshotFromGlobalSnapshot(Snapshot snapshot);
 +static void GetSnapshotDataFromGTM(Snapshot snapshot);
 +#endif
 +
  /* Primitives for KnownAssignedXids array handling for standby */
  static void KnownAssignedXidsCompress(bool force);
  static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid,
@@@ -3353,285 -3099,9 +3353,285 @@@ DisplayXidCache(void
                        xc_no_overflow,
                        xc_slow_answer);
  }
- #endif   /* XIDCACHE_DEBUG */
+ #endif                                                        /* XIDCACHE_DEBUG */
  
  
 +#ifdef PGXC
 +/*
 + * Store snapshot data received from the Coordinator
 + */
 +void
 +SetGlobalSnapshotData(TransactionId xmin, TransactionId xmax,
 +              int xcnt, TransactionId *xip, SnapshotSource source)
 +{
 +      if (globalSnapshot.max_gxcnt < xcnt)
 +      {
 +              globalSnapshot.gxip = (TransactionId *) realloc(globalSnapshot.gxip,
 +                              sizeof (TransactionId) * xcnt);
 +              if (globalSnapshot.gxip == NULL)
 +                      elog(ERROR, "Out of memory");
 +              globalSnapshot.max_gxcnt = xcnt;
 +      }
 +
 +      globalSnapshot.snapshot_source = source;
 +      globalSnapshot.gxmin = xmin;
 +      globalSnapshot.gxmax = xmax;
 +      globalSnapshot.gxcnt = xcnt;
 +      memcpy(globalSnapshot.gxip, xip, sizeof (TransactionId) * xcnt);
 +      elog (DEBUG1, "global snapshot info: gxmin: %d, gxmax: %d, gxcnt: %d", xmin, xmax, xcnt);
 +}
 +
 +/*
 + * Force Datanode to use local snapshot data
 + */
 +void
 +UnsetGlobalSnapshotData(void)
 +{
 +      globalSnapshot.snapshot_source = SNAPSHOT_UNDEFINED;
 +      globalSnapshot.gxmin = InvalidTransactionId;
 +      globalSnapshot.gxmax = InvalidTransactionId;
 +      globalSnapshot.gxcnt = 0;
 +      elog (DEBUG1, "unset snapshot info");
 +}
 +
 +
 +/*
 + * Entry of snapshot obtention for Postgres-XC node
 + */
 +static bool
 +GetPGXCSnapshotData(Snapshot snapshot, bool latest)
 +{
 +      /*
 +       * If this node is in recovery phase,
 +       * snapshot has to be taken directly from WAL information.
 +       */
 +      if (RecoveryInProgress())
 +              return false;
 +
 +      /*
 +       * The typical case is that the local Coordinator passes down the snapshot to the
 +       * remote nodes to use, while it itself obtains it from GTM. Autovacuum processes
 +       * need however to connect directly to GTM themselves to obtain XID and snapshot
 +       * information for autovacuum worker threads.
 +       * A vacuum analyze uses a special function to get a transaction ID and signal
 +       * GTM not to include this transaction ID in snapshot.
 +       * A vacuum worker starts as a normal transaction would.
 +       */
 +
 +      if ((IsConnFromCoord() || IsConnFromDatanode())
 +                      && !IsInitProcessingMode() && !GetForceXidFromGTM() &&
 +                      !latest)
 +      {
 +              if (globalSnapshot.snapshot_source == SNAPSHOT_COORDINATOR)
 +                      GetSnapshotFromGlobalSnapshot(snapshot);
 +              else
 +                      GetSnapshotDataFromGTM(snapshot);
 +              return true;
 +      }
 +      else if (IsPostmasterEnvironment)
 +      {
 +              GetSnapshotDataFromGTM(snapshot);
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +static void
 +GetSnapshotDataFromGTM(Snapshot snapshot)
 +{
 +      GTM_Snapshot gtm_snapshot;
 +      GlobalTransactionId reporting_xmin;
 +      bool canbe_grouped = (!FirstSnapshotSet) || (!IsolationUsesXactSnapshot());
 +      bool xmin_changed = false;
 +
 +      /*
 +       * We never want to use a snapshot whose xmin is older than the
 +       * RecentGlobalXmin computed by the GTM. While it does not look likely that
 +       * that this will ever happen because both these computations happen on the
 +       * GTM, we are still worried about a race condition where a backend sends a
 +       * snapshot request, and before snapshot is received, the cluster monitor
 +       * reports our Xmin (which obviously does not include this snapshot's
 +       * xmin). Now if GTM processes the snapshot request first, computes
 +       * snapshot's xmin and then receives our Xmin-report, it may actually moves
 +       * RecentGlobalXmin beyond snapshot's xmin assuming some transactions
 +       * finished in between.
 +       *
 +       * We try to introduce some interlock between the Xmin reporting and
 +       * snapshot request. Since we don't want to wait on a lock while Xmin is
 +       * being reported by the cluster monitor process, we just make sure that
 +       * the snapshot's xmin is not older than the Xmin we are currently
 +       * reporting. Given that this is a very rare possibility, we just get a
 +       * fresh snapshot from the GTM.
 +       *
 +       */
 +      
 +      LWLockAcquire(ClusterMonitorLock, LW_SHARED);
 +
 +retry:
 +      reporting_xmin = ClusterMonitorGetReportingGlobalXmin();
 +      
 +      xmin_changed = false;
 +      if (TransactionIdIsValid(reporting_xmin) &&
 +              !TransactionIdIsValid(MyPgXact->xmin))
 +      {
 +              MyPgXact->xmin = reporting_xmin;
 +              xmin_changed = true;
 +      }
 +
 +      gtm_snapshot = GetSnapshotGTM(GetCurrentTransactionIdIfAny(), canbe_grouped);
 +
 +      if (!gtm_snapshot)
 +              ereport(ERROR,
 +                              (errcode(ERRCODE_CONNECTION_FAILURE),
 +                               errmsg("GTM error, could not obtain snapshot. Current XID = %d, Autovac = %d", GetCurrentTransactionId(), IsAutoVacuumWorkerProcess())));
 +      else
 +      {
 +              if (xmin_changed)
 +                      MyPgXact->xmin = InvalidTransactionId;
 +              if (TransactionIdPrecedes(gtm_snapshot->sn_xmin, reporting_xmin))
 +                      goto retry;
 +
 +              /* 
 +               * Set RecentGlobalXmin by copying from the shared memory state
 +               * maintained by the Clutser Monitor
 +               */
 +              RecentGlobalXmin = ClusterMonitorGetGlobalXmin();
 +              if (!TransactionIdIsValid(RecentGlobalXmin))
 +                      RecentGlobalXmin = FirstNormalTransactionId;
 +              /*
 +               * XXX Is it ok to set RecentGlobalDataXmin same as RecentGlobalXmin ?
 +               */
 +              RecentGlobalDataXmin = RecentGlobalXmin;
 +              SetGlobalSnapshotData(gtm_snapshot->sn_xmin, gtm_snapshot->sn_xmax,
 +                              gtm_snapshot->sn_xcnt, gtm_snapshot->sn_xip, SNAPSHOT_DIRECT);
 +              GetSnapshotFromGlobalSnapshot(snapshot);
 +      }
 +      LWLockRelease(ClusterMonitorLock);
 +}
 +
 +static void
 +GetSnapshotFromGlobalSnapshot(Snapshot snapshot)
 +{
 +      if ((globalSnapshot.snapshot_source == SNAPSHOT_COORDINATOR ||
 +                              globalSnapshot.snapshot_source == SNAPSHOT_DIRECT)
 +                              && TransactionIdIsValid(globalSnapshot.gxmin))
 +      {
 +              TransactionId global_xmin;
 +
 +              snapshot->xmin = globalSnapshot.gxmin;
 +              snapshot->xmax = globalSnapshot.gxmax;
 +              snapshot->xcnt = globalSnapshot.gxcnt;
 +              /*
 +               * Allocating space for maxProcs xids is usually overkill; numProcs would
 +               * be sufficient.  But it seems better to do the malloc while not holding
 +               * the lock, so we can't look at numProcs.  Likewise, we allocate much
 +               * more subxip storage than is probably needed.
 +               *
 +               * This does open a possibility for avoiding repeated malloc/free: since
 +               * maxProcs does not change at runtime, we can simply reuse the previous
 +               * xip arrays if any.  (This relies on the fact that all callers pass
 +               * static SnapshotData structs.) */
 +              if (snapshot->xip == NULL)
 +              {
 +                      ProcArrayStruct *arrayP = procArray;
 +                      /*
 +                       * First call for this snapshot
 +                       */
 +                      snapshot->xip = (TransactionId *)
 +                              malloc(Max(arrayP->maxProcs, globalSnapshot.gxcnt) * sizeof(TransactionId));
 +                      if (snapshot->xip == NULL)
 +                              ereport(ERROR,
 +                                              (errcode(ERRCODE_OUT_OF_MEMORY),
 +                                               errmsg("out of memory")));
 +                      snapshot->max_xcnt = Max(arrayP->maxProcs, globalSnapshot.gxcnt);
 +
 +                      Assert(snapshot->subxip == NULL);
 +                      snapshot->subxip = (TransactionId *)
 +                              malloc(arrayP->maxProcs * PGPROC_MAX_CACHED_SUBXIDS * sizeof(TransactionId));
 +                      if (snapshot->subxip == NULL)
 +                              ereport(ERROR,
 +                                              (errcode(ERRCODE_OUT_OF_MEMORY),
 +                                               errmsg("out of memory")));
 +              }
 +              else if (snapshot->max_xcnt < globalSnapshot.gxcnt)
 +              {
 +                      snapshot->xip = (TransactionId *)
 +                              realloc(snapshot->xip, globalSnapshot.gxcnt * sizeof(TransactionId));
 +                      if (snapshot->xip == NULL)
 +                              ereport(ERROR,
 +                                              (errcode(ERRCODE_OUT_OF_MEMORY),
 +                                               errmsg("out of memory")));
 +                      snapshot->max_xcnt = globalSnapshot.gxcnt;
 +              }
 +
 +              /* PGXCTODO - set this until we handle subtransactions. */
 +              snapshot->subxcnt = 0;
 +
 +              /*
 +               * This is a new snapshot, so set both refcounts are zero, and mark it
 +               * as not copied in persistent memory.
 +               */
 +              snapshot->active_count = 0;
 +              snapshot->regd_count = 0;
 +              snapshot->copied = false;
 +
 +              /*
 +               * Start of handling for local ANALYZE
 +               * Make adjustments for any running auto ANALYZE commands
 +               */
 +              LWLockAcquire(ProcArrayLock, LW_SHARED);
 +
 +              /*
 +               * Once we have a SHARED lock on the ProcArrayLock, fetch the
 +               * GlobalXmin and ensure that the snapshot we are dealing with isn't
 +               * too old. Since such a snapshot may need to see rows that have
 +               * already been removed by the server
 +               *
 +               * These scenarios are not very likely to happen because the
 +               * ClusterMonitor will ensure that GlobalXmins are reported to GTM in
 +               * time and the GlobalXmin on the GTM can't advance past the reported
 +               * xmins. But in some cases where a node fails to report its GlobalXmin
 +               * and gets excluded from the list of nodes on GTM, the GlobalXmin will
 +               * be advanced. Usually such node will shoot itself in the head
 +               * and rejoin the cluster, but if at all it sends a snapshot to us, we
 +               * should protect ourselves from using it
 +               */
 +              global_xmin = ClusterMonitorGetGlobalXmin();
 +              if (!TransactionIdIsValid(global_xmin))
 +                      global_xmin = FirstNormalTransactionId;
 +
 +              if (TransactionIdPrecedes(globalSnapshot.gxmin, global_xmin))
 +                      elog(ERROR, "Snapshot too old - RecentGlobalXmin (%d) has already "
 +                                      "advanced past the snapshot xmin (%d)",
 +                                      global_xmin, globalSnapshot.gxmin);
 +
 +              memcpy(snapshot->xip, globalSnapshot.gxip,
 +                              globalSnapshot.gxcnt * sizeof(TransactionId));
 +              snapshot->curcid = GetCurrentCommandId(false);
 +
 +              if (!TransactionIdIsValid(MyPgXact->xmin))
 +                      MyPgXact->xmin = TransactionXmin = globalSnapshot.gxmin;
 +
 +              RecentXmin = globalSnapshot.gxmin;
 +              RecentGlobalXmin = global_xmin;
 +
 +              /*
 +               * XXX Is it ok to set RecentGlobalDataXmin same as RecentGlobalXmin ?
 +               */
 +              RecentGlobalDataXmin = RecentGlobalXmin;
 +
 +              if (!TransactionIdIsValid(MyPgXact->xmin))
 +                      MyPgXact->xmin = snapshot->xmin;
 +
 +              LWLockRelease(ProcArrayLock);
 +              /* End handling of local analyze XID in snapshots */
 +      }
 +      else
 +              elog(ERROR, "Cannot set snapshot from global snapshot");
 +}
 +#endif /* PGXC */
 +
  /* ----------------------------------------------
   *            KnownAssignedTransactions sub-module
   * ----------------------------------------------
Simple merge
Simple merge
Simple merge
Simple merge
index 8c7beaf201d42bc90c75e4d6fbda936379940261,b8d860ebdbf42ebc60cc19c8bffba48007ceeab5..4bd95643263f7645a1a27ea732af55e977b7498a
@@@ -1421,10 -1193,9 +1421,10 @@@ exec_simple_query(const char *query_str
   */
  static void
  exec_parse_message(const char *query_string,  /* string to execute */
-                                  const char *stmt_name,               /* name for prepared stmt */
-                                  Oid *paramTypes,             /* parameter types */
+                                  const char *stmt_name,       /* name for prepared stmt */
+                                  Oid *paramTypes, /* parameter types */
 +                                 char **paramTypeNames,       /* parameter type names */
-                                  int numParams)               /* number of parameters */
+                                  int numParams)       /* number of parameters */
  {
        MemoryContext unnamed_stmt_context = NULL;
        MemoryContext oldcontext;
@@@ -5193,13 -4431,13 +5196,13 @@@ ShowUsageCommon(const char *title, stru
  
        appendStringInfoString(&str, "! system usage stats:\n");
        appendStringInfo(&str,
-                       "!\t%ld.%06ld s user, %ld.%06ld s system, %ld.%06ld s elapsed\n",
+                                        "!\t%ld.%06ld s user, %ld.%06ld s system, %ld.%06ld s elapsed\n",
 -                                       (long) (r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec),
 -                                       (long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec),
 -                                       (long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec),
 -                                       (long) (r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec),
 -                                       (long) (elapse_t.tv_sec - Save_t.tv_sec),
 -                                       (long) (elapse_t.tv_usec - Save_t.tv_usec));
 +                                       (long) (r.ru_utime.tv_sec - save_r->ru_utime.tv_sec),
 +                                       (long) (r.ru_utime.tv_usec - save_r->ru_utime.tv_usec),
 +                                       (long) (r.ru_stime.tv_sec - save_r->ru_stime.tv_sec),
 +                                       (long) (r.ru_stime.tv_usec - save_r->ru_stime.tv_usec),
 +                                       (long) (elapse_t.tv_sec - save_t->tv_sec),
 +                                       (long) (elapse_t.tv_usec - save_t->tv_usec));
        appendStringInfo(&str,
                                         "!\t[%ld.%06ld s user, %ld.%06ld s system total]\n",
                                         (long) user.tv_sec,
  #if defined(HAVE_GETRUSAGE)
        appendStringInfo(&str,
                                         "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
 -                                       r.ru_inblock - Save_r.ru_inblock,
 +                                       r.ru_inblock - save_r->ru_inblock,
        /* they only drink coffee at dec */
 -                                       r.ru_oublock - Save_r.ru_oublock,
 +                                       r.ru_oublock - save_r->ru_oublock,
                                         r.ru_inblock, r.ru_oublock);
        appendStringInfo(&str,
-                         "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
 -                                       "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
 -                                       r.ru_majflt - Save_r.ru_majflt,
 -                                       r.ru_minflt - Save_r.ru_minflt,
++                                       "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
 +                                       r.ru_majflt - save_r->ru_majflt,
 +                                       r.ru_minflt - save_r->ru_minflt,
                                         r.ru_majflt, r.ru_minflt,
 -                                       r.ru_nswap - Save_r.ru_nswap,
 +                                       r.ru_nswap - save_r->ru_nswap,
                                         r.ru_nswap);
        appendStringInfo(&str,
-                "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
 -                                       "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
 -                                       r.ru_nsignals - Save_r.ru_nsignals,
++                                       "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
 +                                       r.ru_nsignals - save_r->ru_nsignals,
                                         r.ru_nsignals,
 -                                       r.ru_msgrcv - Save_r.ru_msgrcv,
 -                                       r.ru_msgsnd - Save_r.ru_msgsnd,
 +                                       r.ru_msgrcv - save_r->ru_msgrcv,
 +                                       r.ru_msgsnd - save_r->ru_msgsnd,
                                         r.ru_msgrcv, r.ru_msgsnd);
        appendStringInfo(&str,
-                        "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
 -                                       "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
 -                                       r.ru_nvcsw - Save_r.ru_nvcsw,
 -                                       r.ru_nivcsw - Save_r.ru_nivcsw,
++                                       "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
 +                                       r.ru_nvcsw - save_r->ru_nvcsw,
 +                                       r.ru_nivcsw - save_r->ru_nivcsw,
                                         r.ru_nvcsw, r.ru_nivcsw);
- #endif   /* HAVE_GETRUSAGE */
+ #endif                                                        /* HAVE_GETRUSAGE */
  
        /* remove trailing newline */
        if (str.data[str.len - 1] == '\n')
Simple merge
index 3fdf5c84da4c6491110acd4e90fcb88d6693083f,ddacac87747ab54faca5510bd2903aa7599b85f4..ada57ac500cf38e0ebd22e9f4779a284e69ad0c1
@@@ -2014,21 -1324,15 +2014,21 @@@ ProcessUtilitySlow(ParseState *pstate
                                        /* ... and do it */
                                        EventTriggerAlterTableStart(parsetree);
                                        address =
-                                               DefineIndex(relid,              /* OID of heap relation */
+                                               DefineIndex(relid,      /* OID of heap relation */
                                                                        stmt,
                                                                        InvalidOid, /* no predefined OID */
-                                                                       false,          /* is_alter_table */
-                                                                       true,           /* check_rights */
-                                                                       true,           /* check_not_in_use */
-                                                                       false,          /* skip_build */
-                                                                       false);         /* quiet */
+                                                                       false,  /* is_alter_table */
+                                                                       true,   /* check_rights */
+                                                                       true,   /* check_not_in_use */
+                                                                       false,  /* skip_build */
+                                                                       false); /* quiet */
  
 +#ifdef PGXC
 +                                      if (IS_PGXC_COORDINATOR && !stmt->isconstraint && !IsConnFromCoord())
 +                                              ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
 +                                                              stmt->concurrent, exec_type, is_temp);
 +#endif
 +
                                        /*
                                         * Add the CREATE INDEX node itself to stash right away;
                                         * if there were any commands stashed in the ALTER TABLE
                                        address = DefineCompositeType(stmt->typevar,
                                                                                                  stmt->coldeflist);
                                }
 +#ifdef PGXC
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
-                       case T_CreateEnumStmt:          /* CREATE TYPE AS ENUM */
+                       case T_CreateEnumStmt:  /* CREATE TYPE AS ENUM */
                                address = DefineEnum((CreateEnumStmt *) parsetree);
 +#ifdef PGXC
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
-                       case T_CreateRangeStmt:         /* CREATE TYPE AS RANGE */
+                       case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
                                address = DefineRange((CreateRangeStmt *) parsetree);
 +#ifdef PGXC
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
-                       case T_AlterEnumStmt:           /* ALTER TYPE (enum) */
+                       case T_AlterEnumStmt:   /* ALTER TYPE (enum) */
                                address = AlterEnum((AlterEnumStmt *) parsetree);
 +#ifdef PGXC
 +                              /*
 +                               * In this case force autocommit, this transaction cannot be launched
 +                               * inside a transaction block.
 +                               */
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
 +                                                      true, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
                        case T_ViewStmt:        /* CREATE VIEW */
                                PG_TRY();
                                {
                                        address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
-                                                                                queryString, params, completionTag);
+                                                                                                queryString, params, completionTag);
 +#ifdef PGXC
 +                                      if ((IS_PGXC_COORDINATOR) && !IsConnFromCoord())
 +                                      {
 +                                              RefreshMatViewStmt *stmt = (RefreshMatViewStmt *) parsetree;
 +                                              if (stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
 +                                                      ExecUtilityStmtOnNodes(queryString, NULL,
 +                                                                      sentToRemote, false, EXEC_ON_COORDS, false);
 +                                      }
 +#endif
                                }
                                PG_CATCH();
                                {
  
                        case T_CreatePolicyStmt:        /* CREATE POLICY */
                                address = CreatePolicy((CreatePolicyStmt *) parsetree);
 +#ifdef PGXC
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
-                       case T_AlterPolicyStmt:         /* ALTER POLICY */
+                       case T_AlterPolicyStmt: /* ALTER POLICY */
                                address = AlterPolicy((AlterPolicyStmt *) parsetree);
 +#ifdef PGXC
 +                              if (IS_PGXC_LOCAL_COORDINATOR)
 +                                      ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
 +#endif
                                break;
  
                        case T_SecLabelStmt:
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index a1a7edd58940376363456e28bdb00e5e8124d08a,18d9e27d1ed9af9543c5b11ddabb4e5ad6f38196..2f28197517495bd8c27415cc0b10ecd8b63d8fa9
@@@ -128,14 -113,8 +128,14 @@@ typedef struc
        int                     wrapColumn;             /* max line length, or -1 for no limit */
        int                     indentLevel;    /* current indent level for prettyprint */
        bool            varprefix;              /* TRUE to print prefixes on Vars */
-       ParseExprKind special_exprkind;         /* set only for exprkinds needing
-                                                                                * special handling */
+       ParseExprKind special_exprkind; /* set only for exprkinds needing special
+                                                                        * handling */
 +#ifdef PGXC
 +      bool            finalise_aggs;  /* should Datanode finalise the aggregates? */
 +      bool            sortgroup_colno;/* instead of expression use resno for
 +                                                               * sortgrouprefs.
 +                                                               */
 +#endif /* PGXC */
  } deparse_context;
  
  /*
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index a91faf4b717ddcb6979c5bee4859e691608ec407,7c09498dc047ebc34403a3edc85d147ef293d82e..4b9578de6dd7c6a5b9b4737449e528897dfd6c8c
@@@ -147,9 -136,5 +147,9 @@@ int                        VacuumPageHit = 0
  int                   VacuumPageMiss = 0;
  int                   VacuumPageDirty = 0;
  
- int                   VacuumCostBalance = 0;          /* working state for vacuum */
+ int                   VacuumCostBalance = 0;  /* working state for vacuum */
  bool          VacuumCostActive = false;
 +
 +#ifdef PGXC
 +bool useLocalXid = false;
 +#endif
Simple merge
Simple merge
index f7391cc6b8f4cb3c846164444eac57bc2ad120d4,82e54c084b8c02901249ad2b8ff0900a7abb6ae8..2deaf62455d83e3fdbc5972f404a3ec15587157c
@@@ -497,13 -438,8 +497,13 @@@ bool             Debug_pretty_print = true
  bool          log_parser_stats = false;
  bool          log_planner_stats = false;
  bool          log_executor_stats = false;
- bool          log_statement_stats = false;            /* this is sort of all three
-                                                                                                * above together */
+ bool          log_statement_stats = false;    /* this is sort of all three above
+                                                                                        * together */
 +#ifdef XCP
 +bool          log_gtm_stats = false;
 +bool          log_remotesubplan_stats = false;
 +#endif
 +
  bool          log_btree_build_stats = false;
  char     *event_source;
  
Simple merge
Simple merge
index 02cd1d7fe27e9b652c711936b673f02c6c1c0911,a8a115c6b093e84174c7688b3dfaf72d9164bfe0..e427ba72fe99a72b50d0aba3e5d9a95c4366957b
@@@ -333,16 -322,8 +333,16 @@@ struct Tuplesortstat
         * from the slab memory arena, or is palloc'd, see readtup_alloc().
         */
        void            (*readtup) (Tuplesortstate *state, SortTuple *stup,
-                                                                               int tapenum, unsigned int len);
+                                                       int tapenum, unsigned int len);
  
 +#ifdef PGXC
 +      /*
 +       * Function to read length of next stored tuple.
 +       * Used as 'len' parameter for readtup function.
 +       */
 +      unsigned int (*getlen) (Tuplesortstate *state, int tapenum, bool eofOK);
 +#endif
 +
        /*
         * This array holds the tuples now in sort memory.  If we are in state
         * INITIAL, the tuples are in no particular order; if we are in state
index 9cbce9e59894e35a39cab610e3d42168211afdc9,98c006b663e3d2f6c7db00bf20c71ab5fbf24c39..9da5ff6eb63552043378f0bcdb0e6e7927c7dd20
@@@ -1157,11 -1051,8 +1157,11 @@@ tuplestore_gettuple(Tuplestorestate *st
                                                        SEEK_CUR) != 0)
                                ereport(ERROR,
                                                (errcode_for_file_access(),
-                                errmsg("could not seek in tuplestore temporary file: %m")));
+                                                errmsg("could not seek in tuplestore temporary file: %m")));
                        tup = READTUP(state, tuplen);
 +                      if (state->stat_name && tup)
 +                              state->stat_read_count++;
 +
                        return tup;
  
                default:
@@@ -1687,226 -1553,6 +1687,226 @@@ readtup_heap(Tuplestorestate *state, un
                                                sizeof(tuplen)) != sizeof(tuplen))
                        ereport(ERROR,
                                        (errcode_for_file_access(),
-                          errmsg("could not read from tuplestore temporary file: %m")));
+                                        errmsg("could not read from tuplestore temporary file: %m")));
        return (void *) tuple;
  }
 +
 +
 +#ifdef XCP
 +/*
 + * Routines to support Datarow tuple format, used for exchange between nodes
 + * as well as send data to client
 + */
 +Tuplestorestate *
 +tuplestore_begin_datarow(bool interXact, int maxKBytes,
 +                                               MemoryContext tmpcxt)
 +{
 +      Tuplestorestate *state;
 +
 +      state = tuplestore_begin_common(0, interXact, maxKBytes);
 +
 +      state->format = TSF_DATAROW;
 +      state->copytup = copytup_datarow;
 +      state->writetup = writetup_datarow;
 +      state->readtup = readtup_datarow;
 +      state->tmpcxt = tmpcxt;
 +
 +      return state;
 +}
 +
 +
 +/*
 + * Do we need this at all?
 + */
 +static void *
 +copytup_datarow(Tuplestorestate *state, void *tup)
 +{
 +      Assert(false);
 +      return NULL;
 +}
 +
 +static void
 +writetup_datarow(Tuplestorestate *state, void *tup)
 +{
 +      RemoteDataRow tuple = (RemoteDataRow) tup;
 +
 +      /* the part of the MinimalTuple we'll write: */
 +      char       *tupbody = tuple->msg;
 +      unsigned int tupbodylen = tuple->msglen;
 +
 +      /* total on-disk footprint: */
 +      unsigned int tuplen = tupbodylen + sizeof(int) + sizeof(tuple->msgnode);
 +
 +      if (BufFileWrite(state->myfile, (void *) &tuplen,
 +                                       sizeof(int)) != sizeof(int))
 +              elog(ERROR, "write failed");
 +      if (BufFileWrite(state->myfile, (void *) &tuple->msgnode,
 +                                       sizeof(tuple->msgnode)) != sizeof(tuple->msgnode))
 +              elog(ERROR, "write failed");
 +      if (BufFileWrite(state->myfile, (void *) tupbody,
 +                                       tupbodylen) != (size_t) tupbodylen)
 +              elog(ERROR, "write failed");
 +      if (state->backward)            /* need trailing length word? */
 +              if (BufFileWrite(state->myfile, (void *) &tuplen,
 +                                               sizeof(tuplen)) != sizeof(tuplen))
 +                      elog(ERROR, "write failed");
 +
 +      FREEMEM(state, GetMemoryChunkSpace(tuple));
 +      pfree(tuple);
 +}
 +
 +static void *
 +readtup_datarow(Tuplestorestate *state, unsigned int len)
 +{
 +      RemoteDataRow tuple = (RemoteDataRow) palloc(len);
 +      unsigned int tupbodylen = len - sizeof(int) - sizeof(tuple->msgnode);
 +
 +      USEMEM(state, GetMemoryChunkSpace(tuple));
 +      /* read in the tuple proper */
 +      tuple->msglen = tupbodylen;
 +      if (BufFileRead(state->myfile, (void *) &tuple->msgnode,
 +                                      sizeof(tuple->msgnode)) != sizeof(tuple->msgnode))
 +              elog(ERROR, "unexpected end of data");
 +      if (BufFileRead(state->myfile, (void *) tuple->msg,
 +                                      tupbodylen) != (size_t) tupbodylen)
 +              elog(ERROR, "unexpected end of data");
 +      if (state->backward)            /* need trailing length word? */
 +              if (BufFileRead(state->myfile, (void *) &len,
 +                                              sizeof(len)) != sizeof(len))
 +                      elog(ERROR, "unexpected end of data");
 +      return (void *) tuple;
 +}
 +
 +
 +/*
 + * Routines to support storage of protocol message data
 + */
 +Tuplestorestate *
 +tuplestore_begin_message(bool interXact, int maxKBytes)
 +{
 +      Tuplestorestate *state;
 +
 +      state = tuplestore_begin_common(0, interXact, maxKBytes);
 +
 +      state->format = TSF_MESSAGE;
 +      state->copytup = copytup_message;
 +      state->writetup = writetup_message;
 +      state->readtup = readtup_message;
 +      state->tmpcxt = NULL;
 +
 +      return state;
 +}
 +
 +
 +void
 +tuplestore_putmessage(Tuplestorestate *state, int len, char* msg)
 +{
 +      msg_data m;
 +      void *tuple;
 +      MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
 +
 +      Assert(state->format == TSF_MESSAGE);
 +
 +      m.msglen = len;
 +      m.msg = msg;
 +
 +      tuple = COPYTUP(state, &m);
 +      tuplestore_puttuple_common(state, tuple);
 +
 +      MemoryContextSwitchTo(oldcxt);
 +}
 +
 +
 +char *
 +tuplestore_getmessage(Tuplestorestate *state, int *len)
 +{
 +      bool should_free;
 +      void *result;
 +      void *tuple = tuplestore_gettuple(state, true, &should_free);
 +
 +      Assert(state->format == TSF_MESSAGE);
 +
 +      /* done? */
 +      if (!tuple)
 +              return NULL;
 +
 +      *len = *((int *) tuple);
 +
 +      result = palloc(*len);
 +      memcpy(result, ((char *) tuple) + sizeof(int), *len);
 +      if (should_free)
 +              pfree(tuple);
 +
 +      return (char *) result;
 +}
 +
 +
 +static void *
 +copytup_message(Tuplestorestate *state, void *tup)
 +{
 +      msg_data *m = (msg_data *) tup;
 +      void *tuple;
 +
 +      tuple = palloc(m->msglen + sizeof(int));
 +      *((int *) tuple) = m->msglen;
 +      memcpy(((char *) tuple) + sizeof(int), m->msg, m->msglen);
 +      USEMEM(state, GetMemoryChunkSpace(tuple));
 +      return tuple;
 +}
 +
 +
 +static void
 +writetup_message(Tuplestorestate *state, void *tup)
 +{
 +      void *tupbody = ((char *) tup) + sizeof(int);
 +      unsigned int tupbodylen = *((int *) tup);
 +      /* total on-disk footprint: */
 +      unsigned int tuplen = tupbodylen + sizeof(tuplen);
 +
 +      if (BufFileWrite(state->myfile, &tuplen,
 +                                       sizeof(tuplen)) != sizeof(tuplen))
 +              elog(ERROR, "write failed");
 +      if (BufFileWrite(state->myfile, tupbody, tupbodylen) != tupbodylen)
 +              elog(ERROR, "write failed");
 +      if (state->backward)            /* need trailing length word? */
 +              if (BufFileWrite(state->myfile, &tuplen,
 +                                               sizeof(tuplen)) != sizeof(tuplen))
 +                      elog(ERROR, "write failed");
 +
 +      FREEMEM(state, GetMemoryChunkSpace(tup));
 +      pfree(tup);
 +}
 +
 +static void *
 +readtup_message(Tuplestorestate *state, unsigned int len)
 +{
 +      void *tuple = palloc(len);
 +      int tupbodylen = len - sizeof(int);
 +      void *tupbody = ((char *) tuple) + sizeof(int);
 +      *((int *) tuple) = tupbodylen;
 +
 +      USEMEM(state, GetMemoryChunkSpace(tuple));
 +      /* read in the tuple proper */
 +      if (BufFileRead(state->myfile, tupbody, tupbodylen) != tupbodylen)
 +              elog(ERROR, "unexpected end of data");
 +      if (state->backward)            /* need to read trailing length word? */
 +              if (BufFileRead(state->myfile, (void *) &len,
 +                                              sizeof(len)) != sizeof(len))
 +                      elog(ERROR, "unexpected end of data");
 +      return tuple;
 +}
 +#endif
 +
 +
 +void
 +tuplestore_collect_stat(Tuplestorestate *state, char *name)
 +{
 +      if (state->status != TSS_INMEM || state->memtupcount != 0)
 +      {
 +              elog(WARNING, "tuplestore %s is already in use, to late to get statistics",
 +                       name);
 +              return;
 +      }
 +
 +      state->stat_name = pstrdup(name);
 +}
Simple merge
Simple merge
Simple merge
index 6399d92f64b9c778014123c8d2f2717ed21b3c15,7303bbe8923734a656ca1ac16b3afd52fccab288..54fb24f42aa82c6bed4ed6deeeb2a24931fa6a95
@@@ -1092,15 -1078,8 +1092,15 @@@ setup_config(void
                         "default_text_search_config = 'pg_catalog.%s'",
                         escape_quotes(default_text_search_config));
        conflines = replace_token(conflines,
-                                                "#default_text_search_config = 'pg_catalog.simple'",
+                                                         "#default_text_search_config = 'pg_catalog.simple'",
                                                          repltok);
 +#ifdef PGXC
 +      /* Add Postgres-XC node name to configuration file */
 +      snprintf(repltok, sizeof(repltok),
 +                       "pgxc_node_name = '%s'",
 +                       escape_quotes(nodename));
 +      conflines = replace_token(conflines, "#pgxc_node_name = ''", repltok);
 +#endif
  
        default_timezone = select_default_timezone(share_path);
        if (default_timezone)
@@@ -2995,12 -2921,13 +3010,17 @@@ initialize_data_directory(void
  
        setup_depend(cmdfd);
  
+       /*
+        * Note that no objects created after setup_depend() will be "pinned".
+        * They are all droppable at the whim of the DBA.
+        */
        setup_sysviews(cmdfd);
  
 +#ifdef PGXC
 +      /* Initialize catalog information about the node self */
 +      setup_nodeself(cmdfd);
 +#endif
        setup_description(cmdfd);
  
        setup_collation(cmdfd);
Simple merge
index c567905a297fd50db843181b389df450de2fa5f2,144068ac4922167a3eb2c89c92df26661ffd657d..52a5e1cc7ef0a59201c33aac3a2f8bf7503c2e70
@@@ -181,12 -181,11 +181,12 @@@ typedef struct Archiv
        RestoreOptions *ropt;           /* options, if restoring */
  
        int                     verbose;
-       char       *remoteVersionStr;           /* server's version string */
+       char       *remoteVersionStr;   /* server's version string */
        int                     remoteVersion;  /* same in numeric form */
        bool            isStandby;              /* is server a standby node */
 +      bool            isPostgresXL;   /* is server a Postgres-XL node */
  
-       int                     minRemoteVersion;               /* allowable range */
+       int                     minRemoteVersion;       /* allowable range */
        int                     maxRemoteVersion;
  
        int                     numWorkers;             /* number of parallel processes */
Simple merge
index 8829ceacc8382ffcf50f7f0fe566c855de222a8d,ec349d4192c9439d40b7afe700a3564737fee0f6..932ca6aa431690f107679e2f29c873688540b01b
@@@ -5756,15 -5721,10 +5756,15 @@@ getTables(Archive *fout, int *numTables
                                                  "d.classid = c.tableoid AND d.objid = c.oid AND "
                                                  "d.objsubid = 0 AND "
                                                  "d.refclassid = c.tableoid AND d.deptype = 'a') "
-                                          "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
-                                  "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+                                                 "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
                                                  "ORDER BY c.oid",
                                                  username_subquery,
 +                                                fout->isPostgresXL
 +                                                        ?  "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype,"
 +                                                        "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum,"
 +                                                        "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , "
 +                                                        : "",
                                                  RELKIND_SEQUENCE,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE,
                                                  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
                                                  "d.classid = c.tableoid AND d.objid = c.oid AND "
                                                  "d.objsubid = 0 AND "
                                                  "d.refclassid = c.tableoid AND d.deptype = 'a') "
-                                          "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
-                                  "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+                                                 "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
                                                  "ORDER BY c.oid",
                                                  username_subquery,
 +                                                fout->isPostgresXL
 +                                                        ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype,"
 +                                                        "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum,"
 +                                                        "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , "
 +                                                        : "",
                                                  RELKIND_SEQUENCE,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE,
                                                  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
                                                  "d.classid = c.tableoid AND d.objid = c.oid AND "
                                                  "d.objsubid = 0 AND "
                                                  "d.refclassid = c.tableoid AND d.deptype = 'a') "
-                                          "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
-                                  "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+                                                 "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
                                                  "ORDER BY c.oid",
                                                  username_subquery,
 +                                                fout->isPostgresXL
 +                                                      ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype,"
 +                                                        "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum,"
 +                                                        "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , "
 +                                                      : "",
                                                  RELKIND_SEQUENCE,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE,
                                                  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
                                                  "d.classid = c.tableoid AND d.objid = c.oid AND "
                                                  "d.objsubid = 0 AND "
                                                  "d.refclassid = c.tableoid AND d.deptype = 'a') "
-                                          "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
-                                  "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+                                                 "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
                                                  "ORDER BY c.oid",
                                                  username_subquery,
 +                                                fout->isPostgresXL
 +                                                        ?  "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype,"
 +                                                        "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum,"
 +                                                        "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , "
 +                                                        : "",
                                                  RELKIND_SEQUENCE,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE,
                                                  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
Simple merge
Simple merge
Simple merge
index fe5df0fa22e940512d37406c687274fefb700b56,4d364a1db4cb219358b78f9ebd5614d3e264fd03..222bd62a1f106b2e54ec0340dd245f4f7aafd183
@@@ -481,11 -476,8 +481,11 @@@ usage(void
                   "\nInitialization options:\n"
                   "  -i, --initialize         invokes initialization mode\n"
                   "  -F, --fillfactor=NUM     set fill factor\n"
-               "  -n, --no-vacuum          do not run VACUUM after initialization\n"
-       "  -q, --quiet              quiet logging (one message each 5 seconds)\n"
 +#ifdef PGXC
 +                 "  -k           distribute by primary key 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"
                   "  -s, --scale=NUM          scaling factor\n"
                   "  --foreign-keys           create foreign key constraints between tables\n"
                   "  --index-tablespace=TABLESPACE\n"
                   "  -c, --client=NUM         number of concurrent database clients (default: 1)\n"
                   "  -C, --connect            establish new connection for each transaction\n"
                   "  -D, --define=VARNAME=VALUE\n"
-         "                           define variable for use by custom script\n"
+                  "                           define variable for use by custom script\n"
 +#ifdef PGXC
 +                 "  -k           query with default key and additional key branch id (bid)\n"
 +#endif
                   "  -j, --jobs=NUM           number of threads (default: 1)\n"
                   "  -l, --log                write transaction times to log file\n"
                   "  -L, --latency-limit=NUM  count transactions lasting more than NUM ms as late\n"
Simple merge
Simple merge
Simple merge
Simple merge
index c608b03bb070e4bf06115fa3bdbcb6a2deddb20e,7fa868b556b3d7c53b30de95cdc4dde6c98185fb..4e50a843f7c87c3b8856ae846d1a2ff6ab1db2e7
@@@ -423,9 -422,4 +422,9 @@@ extern void hashbucketcleanup(Relation 
                                  bool bucket_has_garbage,
                                  IndexBulkDeleteCallback callback, void *callback_state);
  
- #endif   /* HASH_H */
 +#ifdef PGXC
 +extern Datum compute_hash(Oid type, Datum value, char locator);
 +extern char *get_compute_hash_function(Oid type, char locator);
 +#endif
 +
+ #endif                                                        /* HASH_H */
Simple merge
index 348c67ed868565600932d6cfc6fbf379c43abd38,b88c5e11411189a45c4ec417ad082ab4dd799989..1b3ab8e4aa99c22a3f789fc8f34560f6147eaddc
  #define MaxTransactionIdAttributeNumber                       (-5)
  #define MaxCommandIdAttributeNumber                           (-6)
  #define TableOidAttributeNumber                                       (-7)
 +#ifdef PGXC
 +#define XC_NodeIdAttributeNumber                              (-8)
 +#define FirstLowInvalidHeapAttributeNumber            (-9)
 +#else
  #define FirstLowInvalidHeapAttributeNumber            (-8)
 +#endif
 +
  
- #endif   /* SYSATTR_H */
+ #endif                                                        /* SYSATTR_H */
Simple merge
Simple merge
index 2186e706a63c3b762cb6a3ad0af962b9232c27de,ad5aad96df0cdcc11e1d022dd07c84a9a4307545..16b3c5a26fa9db0d3e05670ad30e652f3f62ebc5
@@@ -124,21 -118,8 +123,21 @@@ typedef enu
  } SubXactEvent;
  
  typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
-                                                                       SubTransactionId parentSubid, void *arg);
+                                                                SubTransactionId parentSubid, void *arg);
  
 +#ifdef PGXC
 +/*
 + * GTM callback events
 + */
 +typedef enum
 +{
 +      GTM_EVENT_COMMIT,
 +      GTM_EVENT_ABORT,
 +      GTM_EVENT_PREPARE
 +} GTMEvent;
 +
 +typedef void (*GTMCallback) (GTMEvent event, void *arg);
 +#endif
  
  /* ----------------
   *            transaction-related XLOG entries
Simple merge
Simple merge
diff --cc src/include/c.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 3657201317daa82af64c743309dcf3f52e7c3a8a,b256657bda08f1377952202619a1ac1285347b35..04c163042c51608aee29a3552d6b14842d10419b
@@@ -157,24 -157,20 +157,24 @@@ DATA(insert OID = 1259 (  pg_class              PGN
  DESCR("");
  
  
- #define                 RELKIND_RELATION                'r'           /* ordinary table */
- #define                 RELKIND_INDEX                   'i'           /* secondary index */
- #define                 RELKIND_SEQUENCE                'S'           /* sequence object */
- #define                 RELKIND_TOASTVALUE      't'           /* for out-of-line values */
- #define                 RELKIND_VIEW                    'v'           /* view */
- #define                 RELKIND_MATVIEW                 'm'           /* materialized view */
- #define                 RELKIND_COMPOSITE_TYPE  'c'           /* composite type */
- #define                 RELKIND_FOREIGN_TABLE   'f'           /* foreign table */
- #define                 RELKIND_PARTITIONED_TABLE 'p'         /* partitioned table */
- #define                 RELPERSISTENCE_PERMANENT      'p'             /* regular table */
- #define                 RELPERSISTENCE_UNLOGGED       'u'             /* unlogged permanent table */
- #define                 RELPERSISTENCE_TEMP           't'             /* temporary table */
+ #define                 RELKIND_RELATION                'r'   /* ordinary table */
+ #define                 RELKIND_INDEX                   'i'   /* secondary index */
+ #define                 RELKIND_SEQUENCE                'S'   /* sequence object */
+ #define                 RELKIND_TOASTVALUE      't'   /* for out-of-line values */
+ #define                 RELKIND_VIEW                    'v'   /* view */
+ #define                 RELKIND_MATVIEW                 'm'   /* materialized view */
+ #define                 RELKIND_COMPOSITE_TYPE  'c'   /* composite type */
+ #define                 RELKIND_FOREIGN_TABLE   'f'   /* foreign table */
+ #define                 RELKIND_PARTITIONED_TABLE 'p' /* partitioned table */
+ #define                 RELPERSISTENCE_PERMANENT      'p' /* regular table */
+ #define                 RELPERSISTENCE_UNLOGGED       'u' /* unlogged permanent table */
+ #define                 RELPERSISTENCE_TEMP           't' /* temporary table */
  
 +#ifdef PGXC
 +#define                 RELPERSISTENCE_LOCAL_TEMP     'l'     /* local temp table */
 +#endif
 +
  /* default selection for replica identity (primary key or nothing) */
  #define                 REPLICA_IDENTITY_DEFAULT      'd'
  /* no replica identity is logged for this relation */
Simple merge
index cafdb8990aac98c5aaab3059f3b0a48b4065b352,8b33b4e0ea70a00412923f03327f9ff3bf6b129f..d44c4ecc0b56de1ab2139d22158fb54eb43227c5
@@@ -5449,23 -5433,11 +5449,25 @@@ DESCR("get an individual replication or
  DATA(insert OID = 6014 ( pg_show_replication_origin_status PGNSP PGUID 12 1 100 0 0 f f f f f t v r 0 0 2249 "" "{26,25,3220,3220}" "{o,o,o,o}" "{local_id, external_id, remote_lsn, local_lsn}" _null_ _null_ pg_show_replication_origin_status _null_ _null_ _null_ ));
  DESCR("get progress for all replication origins");
  
 +#ifdef USE_MODULE_MSGIDS
 +DATA(insert OID = 6015 ( pg_msgmodule_set PGNSP PGUID 12 1 1 0 0 f f f f t t i s 4 0 16 "20 20 20 25" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_set _null_ _null_ _null_ ));
 +DESCR("set debugging level for module/file/msg");
 +DATA(insert OID = 6016 ( pg_msgmodule_change PGNSP PGUID 12 1 1 0 0 f f f f t t i s 4 0 16 "20 20 20 20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_change _null_ _null_ _null_ ));
 +DESCR("change debugging level for module/file/msg");
 +DATA(insert OID = 6017 ( pg_msgmodule_enable PGNSP PGUID 12 1 1 0 0 f f f f t t i s 1 0 16 "20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_enable _null_ _null_ _null_ ));
 +DESCR("pid to honour overriden log levels");
 +DATA(insert OID = 6018 ( pg_msgmodule_disable PGNSP PGUID 12 1 1 0 0 f f f f t t i s 1 0 16 "20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_disable _null_ _null_ _null_ ));
 +DESCR("pid to ignore overriden log levels");
 +DATA(insert OID = 6019 ( pg_msgmodule_enable_all PGNSP PGUID 12 1 1 0 0 f f f f t t i s 1 0 16 "16" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_enable_all _null_ _null_ _null_ ));
 +DESCR("all current/future processes to honour overriden log levels");
 +DATA(insert OID = 6020 ( pg_msgmodule_disable_all PGNSP PGUID 12 1 1 0 0 f f f f t t i s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_disable_all _null_ _null_ _null_ ));
 +DESCR("all processes to ignore overriden log levels");
 +#endif
  /* publications */
- DATA(insert OID = 6119 ( pg_get_publication_tables    PGNSP PGUID 12 1 1000 0 0 f f t f t t s s 1 0 26 "25" "{25,26}" "{i,o}" "{pubname,relid}" _null_ _null_ pg_get_publication_tables _null_ _null_ _null_ ));
+ DATA(insert OID = 6119 ( pg_get_publication_tables    PGNSP PGUID 12 1 1000 0 0 f f f f t t s s 1 0 26 "25" "{25,26}" "{i,o}" "{pubname,relid}" _null_ _null_ pg_get_publication_tables _null_ _null_ _null_ ));
  DESCR("get OIDs of tables in a publication");
+ DATA(insert OID = 6121 ( pg_relation_is_publishable PGNSP PGUID 12 1  0 0 0 f f f f t f s s 1 0 16 "2205" _null_ _null_ _null_ _null_ _null_ pg_relation_is_publishable _null_ _null_ _null_ ));
+ DESCR("returns whether a relation can be part of a publication");
  
  /* rls */
  DATA(insert OID = 3298 (  row_security_active    PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_        row_security_active _null_ _null_ _null_ ));
Simple merge
index 5a74a02a5d80d8972ea171d86f7cdc5b4fd89492,f42c8cdbe305e13ed7b6c9e61a628c7b4716cb12..91186654d0587c4df12ad2f30291be9d67bd7609
@@@ -31,8 -31,4 +31,8 @@@ extern char *get_database_name(Oid dbid
  
  extern void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype);
  
- #endif   /* DBCOMMANDS_H */
 +#ifdef PGXC
 +extern bool IsSetTableSpace(AlterDatabaseStmt *stmt);
 +#endif
 +
+ #endif                                                        /* DBCOMMANDS_H */
Simple merge
index 147f22b8701d9640760d6ec72edcb1c306809d8c,5ec1200e0aed780951bcb31ddefccc4bb011b94b..0d84d5aeba92e5f4bebd208b0935da7afe7e2484
@@@ -28,11 -28,8 +28,11 @@@ typedef struc
  {
        /* dynahash.c requires key to be first field */
        char            stmt_name[NAMEDATALEN];
-       CachedPlanSource *plansource;           /* the actual cached plan */
+       CachedPlanSource *plansource;   /* the actual cached plan */
        bool            from_sql;               /* prepared via SQL, not FE/BE protocol? */
 +#ifdef XCP    
 +      bool            use_resowner;   /* does it use resowner for tracking? */
 +#endif        
        TimestampTz prepare_time;       /* the time when the stmt was prepared */
  } PreparedStatement;
  
@@@ -70,13 -57,4 +70,13 @@@ extern List *FetchPreparedStatementTarg
  
  extern void DropAllPreparedStatements(void);
  
- #endif   /* PREPARE_H */
 +#ifdef PGXC
 +extern DatanodeStatement *FetchDatanodeStatement(const char *stmt_name, bool throwError);
 +extern bool ActivateDatanodeStatementOnNode(const char *stmt_name, int noid);
 +extern bool HaveActiveDatanodeStatements(void);
 +extern void DropDatanodeStatement(const char *stmt_name);
 +extern int SetRemoteStatementName(Plan *plan, const char *stmt_name, int num_params,
 +                                              Oid *param_types, int n);
 +#endif
 +
+ #endif                                                        /* PREPARE_H */
Simple merge
index 0e9533cc2de7f0e7159dffdaf0f9418fbad7f9fd,caab19513067ccd161288e25f7040a21066e5e83..7d9cfe80e71ad8a7ba216199fd837121b4469caf
@@@ -72,25 -66,4 +72,25 @@@ extern void seq_desc(StringInfo buf, XL
  extern const char *seq_identify(uint8 info);
  extern void seq_mask(char *pagedata, BlockNumber blkno);
  
- #endif   /* SEQUENCE_H */
 +#ifdef XCP
 +#define DEFAULT_CACHEVAL      1
 +extern int SequenceRangeVal;
 +#endif
 +#ifdef PGXC
 +/*
 + * List of actions that registered the callback.
 + * This is listed here and not in sequence.c because callback can also
 + * be registered in dependency.c and tablecmds.c as sequences can be dropped
 + * or renamed in cascade.
 + */
 +typedef enum
 +{
 +      GTM_CREATE_SEQ,
 +      GTM_DROP_SEQ
 +} GTM_SequenceDropType;
 +
 +extern bool IsTempSequence(Oid relid);
 +extern char *GetGlobalSeqName(Relation rel, const char *new_seqname, const char *new_schemaname);
 +#endif
 +
+ #endif                                                        /* SEQUENCE_H */
Simple merge
Simple merge
Simple merge
Simple merge
index 8468c0c6f6f98685e5cb5013d3a2de32a2765bf6,ec5ef99451750c49388d90b633e8358b3f720fc3..fb9ca3e785c0aa31ae762c2b161e069332b84063
@@@ -79,17 -66,9 +79,17 @@@ extern char *GetRelationPath_client(Oi
  /* First argument is a RelFileNode */
  #define relpathperm(rnode, forknum) \
        relpathbackend(rnode, InvalidBackendId, forknum)
 +#ifdef XCP
 +#define relpathperm_client(rnode, forknum, nodename) \
 +      relpathbackend_client(rnode, InvalidBackendId, forknum, nodename)
 +#endif
  
  /* First argument is a RelFileNodeBackend */
 +#ifdef XCP
 +#define relpath(rnode, forknum) \
 +      relpathbackend((rnode).node, InvalidBackendId, forknum)
 +#else
  #define relpath(rnode, forknum) \
        relpathbackend((rnode).node, (rnode).backend, forknum)
 -
 +#endif
- #endif   /* RELPATH_H */
+ #endif                                                        /* RELPATH_H */
index 62a2f2e477bbaff18a2ee491d35c61c0197f1058,8c09961e281db914ee87ac54f093c1e84ce6ce19..a4b0609e2c06349ccb4132f8f8361dba523dd3d8
@@@ -51,15 -48,8 +51,15 @@@ typedef struct QueryDes
        EState     *estate;                     /* executor's query-wide state */
        PlanState  *planstate;          /* tree of per-plan-node state */
  
 +#ifdef XCP
 +      SharedQueue squeue;             /* the shared memory queue to sent data to other
 +                                                               * nodes */
 +      int             myindex;                /* -1 if locally executed subplan is producing
 +                                                               * data and distribute via squeue. Otherwise
 +                                                               * get local data from squeue */
 +#endif
        /* This field is set by ExecutorRun */
-       bool            already_executed;               /* true if previously executed */
+       bool            already_executed;       /* true if previously executed */
  
        /* This is always set NULL by the core system, but plugins can change it */
        struct Instrumentation *totaltime;      /* total time spent in ExecutorRun */
Simple merge
index c22b3ed5d69ac5fd3c4b8b475fa476f58645cfd9,acade7e92e370e9441ded7acd571b37bb74a6c5d..6bbef72cc1463a127c2bfcc9cab71ccd31a22fd9
@@@ -159,8 -159,4 +159,8 @@@ extern int SPI_register_trigger_data(Tr
  extern void AtEOXact_SPI(bool isCommit);
  extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
  
- #endif   /* SPI_H */
 +#ifdef PGXC
 +extern int SPI_execute_direct(const char *src, char *nodename);
 +#endif
 +
+ #endif                                                        /* SPI_H */
index efdb6fee5a3874b1024b52871678b4f4cc2bec78,55f4cce4ee1bac27fa7ae9aef51faa8efa229529..a1db5eb54b3f436ed457dbb6e6a0c4cfe44316b6
@@@ -116,15 -115,9 +116,15 @@@ typedef struct TupleTableSlo
        NodeTag         type;
        bool            tts_isempty;    /* true = slot is empty */
        bool            tts_shouldFree; /* should pfree tts_tuple? */
-       bool            tts_shouldFreeMin;              /* should pfree tts_mintuple? */
+       bool            tts_shouldFreeMin;      /* should pfree tts_mintuple? */
        bool            tts_slow;               /* saved state for slot_deform_tuple */
        HeapTuple       tts_tuple;              /* physical tuple, or NULL if virtual */
 +#ifdef PGXC
 +      RemoteDataRow tts_datarow;      /* Tuple data in DataRow format */
 +      MemoryContext tts_drowcxt;      /* Context to store deformed */
 +      bool            tts_shouldFreeRow;      /* should pfree tts_dataRow? */
 +      struct AttInMetadata *tts_attinmeta;    /* store here info to extract values from the DataRow */
 +#endif
        TupleDesc       tts_tupleDescriptor;    /* slot's tuple descriptor */
        MemoryContext tts_mcxt;         /* slot itself is in this context */
        Buffer          tts_buffer;             /* tuple's buffer, or InvalidBuffer */
Simple merge
Simple merge
index f381bedd44b1892d59152b970202ef5c5076f705,aa3fb253c27fd85efb410c07f1d4482788b198fc..28641e20d4097d1ce9d1ff48a738baad02c54b3a
@@@ -101,8 -101,4 +101,8 @@@ extern int bms_next_member(const Bitmap
  /* support for hashtables using Bitmapsets as keys: */
  extern uint32 bms_hash_value(const Bitmapset *a);
  
- #endif   /* BITMAPSET_H */
 +#ifdef XCP
 +extern int    bms_any_member(Bitmapset *a);
 +#endif
 +
+ #endif                                                        /* BITMAPSET_H */
index 2bc126dabe02d1f47bf9c538244dd9229789da72,54c5cf5f95b5c5a3cf40062e603c43c36216d81a..86f379c12645dcebf7fcbce8e226ab75228a90a5
@@@ -928,12 -940,9 +942,12 @@@ typedef struct ModifyTableStat
        bool            canSetTag;              /* do we set the command tag/es_processed? */
        bool            mt_done;                /* are we done? */
        PlanState **mt_plans;           /* subplans (one per target rel) */
 +#ifdef PGXC
 +      PlanState **mt_remoterels;      /* per-target remote query node */
 +#endif
        int                     mt_nplans;              /* number of plans in the array */
        int                     mt_whichplan;   /* which one is being executed (0..n-1) */
-       ResultRelInfo *resultRelInfo;           /* per-subplan target relations */
+       ResultRelInfo *resultRelInfo;   /* per-subplan target relations */
        ResultRelInfo *rootResultRelInfo;       /* root target relation (partitioned
                                                                                 * table root) */
        List      **mt_arowmarks;       /* per-subplan ExecAuxRowMark lists */
Simple merge
Simple merge
index fb3684eb5c3ff260924469e814a6b00a8f892aa9,1d96169d34df77ec8abf1d97707d1ef3c5474895..fb8dbc871baa4944d6d19925b025d1bc595269fb
@@@ -3110,11 -3079,7 +3110,11 @@@ typedef enum VacuumOptio
        VACOPT_FULL = 1 << 4,           /* FULL (non-concurrent) vacuum */
        VACOPT_NOWAIT = 1 << 5,         /* don't wait to get lock (autovacuum only) */
        VACOPT_SKIPTOAST = 1 << 6,      /* don't process the TOAST table, if any */
-       VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7,          /* don't skip any pages */
 -      VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7   /* don't skip any pages */
++      VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7,  /* don't skip any pages */
 +      VACOPT_COORDINATOR = 1 << 8     /* don't trigger analyze on the datanodes, but
 +                                                               * just collect existing info and populate
 +                                                               * coordinator side stats.
 +                                                               */
  } VacuumOption;
  
  typedef struct VacuumStmt
Simple merge
Simple merge
Simple merge
index 1e7e6942d54125a688383c2f3d3f7716812dd888,9bae3c6ab98e75bebadc0db8ad4009731c092f17..d3d2f33ff3a63158dc48dcf2301c9f1afb60b77c
@@@ -1339,12 -1296,8 +1339,12 @@@ typedef struct JoinPat
        Path       *outerjoinpath;      /* path for the outer side of the join */
        Path       *innerjoinpath;      /* path for the inner side of the join */
  
-       List       *joinrestrictinfo;           /* RestrictInfos to apply to join */
+       List       *joinrestrictinfo;   /* RestrictInfos to apply to join */
  
 +#ifdef XCP
 +      List       *movedrestrictinfo;          /* RestrictInfos moved down to inner path */
 +#endif
 +
        /*
         * See the notes for RelOptInfo and ParamPathInfo to understand why
         * joinrestrictinfo is needed in JoinPath, and can't be merged into the
Simple merge
Simple merge
Simple merge
Simple merge
index 2c14b1e1af36381924ce7c39b057b248a2aad596,40f22339f1a6f2064ab692ea2c03346b7aa862eb..42435884fed79a56c74b62b00eee03d1a752a3d7
@@@ -44,8 -43,4 +44,8 @@@ extern void applyLockingClause(Query *q
                                   LockClauseStrength strength,
                                   LockWaitPolicy waitPolicy, bool pushedDown);
  
- #endif   /* ANALYZE_H */
 +#ifdef XCP
 +extern void ParseAnalyze_callback(ParseState *pstate, Query *query);
 +extern post_parse_analyze_hook_type prev_ParseAnalyze_callback;
 +#endif
+ #endif                                                        /* ANALYZE_H */
Simple merge
index c684217e33cd9cb8e89537dd7028152a9de1f8e7,b4b6084b1bfd35c7bb7e72c326354e4569980848..538b35bc172b53cfbde063569153e8c30f43f4b1
@@@ -70,5 -70,4 +70,5 @@@ extern Oid LookupAggWithArgs(ObjectWith
  extern void check_srf_call_placement(ParseState *pstate, Node *last_srf,
                                                 int location);
  
- #endif   /* PARSE_FUNC_H */
 +extern void check_pg_get_expr_args(ParseState *pstate, Oid fnoid, List *args);
+ #endif                                                        /* PARSE_FUNC_H */
index 4eece2bf8d2334c1d4115954681902ac2caac3b6,91542d4f15a6ca733900c3ef5700cd8d1cb514b6..bbb605c31b3d0599584dff0507a161df5b16d179
@@@ -129,8 -129,4 +129,8 @@@ extern Oid attnumTypeId(Relation rd, in
  extern Oid    attnumCollationId(Relation rd, int attid);
  extern bool isQueryUsingTempRelation(Query *query);
  
- #endif   /* PARSE_RELATION_H */
 +#ifdef PGXC
 +extern int    specialAttNum(const char *attname);
 +#endif
 +
+ #endif                                                        /* PARSE_RELATION_H */
Simple merge
Simple merge
Simple merge
Simple merge
index 7426a253d2e4b716a40e536c87ae1780f36f2bcb,1ca9b60ea19a779cda9cb60c3ea564797fb2f7a3..29eec53bf820018c5bb2bc5c9971893aa038c559
@@@ -811,15 -801,6 +811,12 @@@ extern Datum Float8GetDatum(float8 X)
   */
  extern void ExceptionalCondition(const char *conditionName,
                                         const char *errorType,
-                          const char *fileName, int lineNumber) pg_attribute_noreturn();
- //#define PGXC_COORD  // for PGXC coordinator compiling
- //#define PGXC_DATANODE // for PGXC data node compiling
+                                        const char *fileName, int lineNumber) pg_attribute_noreturn();
  
- #endif   /* POSTGRES_H */
 +
 +extern void ResetUsageCommon(struct rusage *save_r, struct timeval *save_t);
 +extern void ResetUsage(void);
 +extern void ShowUsageCommon(const char *title, struct rusage *save_r, struct
 +              timeval *save_t);
 +
+ #endif                                                        /* POSTGRES_H */
Simple merge
index 4504968437d282d29f4d1e3b6fa60535345dd8ff,494fa29f10e1a888c63f425c1447cdde745de795..bbac12707d2bec8079ca8a88c04b954f8edcc329
@@@ -30,8 -30,4 +30,8 @@@ extern int relation_is_updatable(Oid re
                                          bool include_triggers,
                                          Bitmapset *include_cols);
  
- #endif   /* REWRITEHANDLER_H */
 +#ifdef PGXC
 +extern List *QueryRewriteCTAS(Query *parsetree);
 +#endif
 +
+ #endif                                                        /* REWRITEHANDLER_H */
index 3445caeb9365d34f131e912bdba3686ffc44d2f5,bf31ba4f4802308a1ec25b2881675f9c59b43dd4..5dea03051060f0de82e41efa680091025148ba9f
@@@ -23,24 -22,8 +23,24 @@@ typedef int BackendId;                      /* unique curr
  
  #define InvalidBackendId              (-1)
  
- extern PGDLLIMPORT BackendId MyBackendId;             /* backend id of this backend */
+ extern PGDLLIMPORT BackendId MyBackendId;     /* backend id of this backend */
  
 +#ifdef XCP
 +/*
 + * Two next variables make up distributed session id. Actual distributed
 + * session id is a string, which includes coordinator node name, but
 + * it is better to use Oid to store and compare with distributed session ids
 + * of other backends under the same postmaster.
 + */
 +extern PGDLLIMPORT Oid MyCoordId;
 +extern PGDLLIMPORT char MyCoordName[NAMEDATALEN];
 +
 +extern PGDLLIMPORT int MyCoordPid;
 +extern PGDLLIMPORT LocalTransactionId MyCoordLxid;
 +
 +/* BackendId of the first backend of the distributed session on the node */
 +extern PGDLLIMPORT BackendId MyFirstBackendId;
 +#endif
  /* backend id of our parallel session leader, or InvalidBackendId if none */
  extern PGDLLIMPORT BackendId ParallelMasterBackendId;
  
Simple merge
Simple merge
index 0be7165d4f664ea7ec2f2d280f6e6c0e61498717,7dbaa81a8ff9167c750aec86bedf8e6d072f5168..4c8345db83aae093fee0f405167012431060079c
@@@ -113,14 -112,8 +113,14 @@@ struct PGPRO
        BackendId       backendId;              /* This backend's backend ID (if assigned) */
        Oid                     databaseId;             /* OID of database this backend is using */
        Oid                     roleId;                 /* OID of role using this backend */
 +#ifdef XCP
 +      Oid                     coordId;                /* Oid of originating coordinator */
 +      int                     coordPid;               /* Pid of the originating session */
 +      BackendId       firstBackendId; /* Backend ID of the first backend of
 +                                                               * the distributed session */
 +#endif
  
-       bool            isBackgroundWorker;             /* true if background worker. */
+       bool            isBackgroundWorker; /* true if background worker. */
  
        /*
         * While in hot standby mode, shows that a conflict signal has been sent
index 7dfe37f881a66f88f7af58deadde81536516a2af,174c537be4616b2829b00e23b7eabe22d6f25dc2..4e1622b174c2e5fd2f89b206948803de364963ef
@@@ -148,13 -117,9 +147,13 @@@ extern bool CountOtherDBBackends(Oid da
  extern void XidCacheRemoveRunningXids(TransactionId xid,
                                                  int nxids, const TransactionId *xids,
                                                  TransactionId latestXid);
 +#ifdef XCP
 +extern void GetGlobalSessionInfo(int pid, Oid *coordId, int *coordPid);
 +extern int    GetFirstBackendId(int *numBackends, int *backends);
 +#endif /* XCP */
  
  extern void ProcArraySetReplicationSlotXmin(TransactionId xmin,
-                                                       TransactionId catalog_xmin, bool already_locked);
+                                                               TransactionId catalog_xmin, bool already_locked);
  
  extern void ProcArrayGetReplicationSlotXmin(TransactionId *xmin,
                                                                TransactionId *catalog_xmin);
index d58c1bede970d3f604bc8d29f0b093a91d1ca191,20bb05b177944c158b015183cc8e733c57eee2d9..9b8f067a4ebe999f66313b82f9762b7911d49572
@@@ -41,13 -31,8 +41,12 @@@ typedef enu
  {
        PROCSIG_CATCHUP_INTERRUPT,      /* sinval catchup interrupt */
        PROCSIG_NOTIFY_INTERRUPT,       /* listen/notify interrupt */
 +#ifdef PGXC
 +      PROCSIG_PGXCPOOL_RELOAD,        /* abort current transaction and reconnect to pooler */
 +      PROCSIG_PGXCPOOL_REFRESH,       /* refresh local view of connection handles */
 +#endif
        PROCSIG_PARALLEL_MESSAGE,       /* message from cooperating parallel backend */
-       PROCSIG_WALSND_INIT_STOPPING,           /* ask walsenders to prepare for
-                                                                                * shutdown  */
+       PROCSIG_WALSND_INIT_STOPPING,   /* ask walsenders to prepare for shutdown  */
  
        /* Recovery conflict reasons */
        PROCSIG_RECOVERY_CONFLICT_DATABASE,
Simple merge
Simple merge
Simple merge
index e8ec5d0f8f0f8fcc9d932fe6f73cc4763f62e366,6abfe7b282fcd6e681575ff681472dd97ffd900a..0d787dd99c5c8d951929c7400f9858ddc334c7e4
@@@ -43,9 -42,4 +43,9 @@@ extern uint64 PortalRunFetch(Portal por
                           long count,
                           DestReceiver *dest);
  
- #endif   /* PQUERY_H */
 +#ifdef XCP
 +extern int    AdvanceProducingPortal(Portal portal, bool can_wait);
 +extern void cleanupClosedProducers(void);
 +#endif
 +
+ #endif                                                        /* PQUERY_H */
Simple merge
index d52f3e852513bee7dc8c3d386ed513b337bacb64,5bd386ddaaedd32d01b362e04db7a11bde318b4c..2f09a939d9ffc2b726cd4aa0166aa45ccf6e1a7d
@@@ -25,12 -25,10 +25,12 @@@ typedef enu
  
  /* Hook for plugins to get control in ProcessUtility() */
  typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
-                                         const char *queryString, ProcessUtilityContext context,
-                                                                                                         ParamListInfo params,
-                                                                                                 QueryEnvironment *queryEnv,
-                                                                       DestReceiver *dest,
-                                                                       bool sentToRemote,
-                                                                       char *completionTag);
+                                                                                 const char *queryString, ProcessUtilityContext context,
+                                                                                 ParamListInfo params,
+                                                                                 QueryEnvironment *queryEnv,
 -                                                                                DestReceiver *dest, char *completionTag);
++                                                                                DestReceiver *dest,
++                                                                                bool sentToRemote,
++                                                                                char *completionTag);
  extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook;
  
  extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString,
@@@ -58,8 -52,4 +58,8 @@@ extern LogStmtLevel GetCommandLogLevel(
  
  extern bool CommandIsReadOnly(PlannedStmt *pstmt);
  
- #endif   /* UTILITY_H */
 +#ifdef PGXC
 +extern bool pgxc_lock_for_utility_stmt(Node *parsetree);
 +#endif
 +
+ #endif                                                        /* UTILITY_H */
index ea93c922f1fd281095a79d67705125f26ac87064,762532f63692910528f04ff497e5ece69aaca33b..586dc449786424b6524b2ad7bee98008a4ac4e15
@@@ -138,19 -121,4 +138,19 @@@ extern int32 type_maximum_size(Oid type
  /* quote.c */
  extern char *quote_literal_cstr(const char *rawstr);
  
- #endif   /* BUILTINS_H */
 +#ifdef PGXC
 +/* backend/pgxc/pool/poolutils.c */
 +extern Datum pgxc_pool_check(PG_FUNCTION_ARGS);
 +extern Datum pgxc_pool_reload(PG_FUNCTION_ARGS);
 +
 +/* backend/access/transam/transam.c */
 +extern Datum pgxc_is_committed(PG_FUNCTION_ARGS);
 +extern Datum pgxc_is_inprogress(PG_FUNCTION_ARGS);
 +#endif
 +extern Datum pg_msgmodule_set(PG_FUNCTION_ARGS);
 +extern Datum pg_msgmodule_change(PG_FUNCTION_ARGS);
 +extern Datum pg_msgmodule_enable(PG_FUNCTION_ARGS);
 +extern Datum pg_msgmodule_disable(PG_FUNCTION_ARGS);
 +extern Datum pg_msgmodule_enable_all(PG_FUNCTION_ARGS);
 +extern Datum pg_msgmodule_disable_all(PG_FUNCTION_ARGS);
+ #endif                                                        /* BUILTINS_H */
index b56e444b5e1c5394a99f399da407f342afc5e598,7bfd25a9e912134e5c13ea6e10081cc6846e9927..df9e7a6901922e6bdb9523beae0a74e58909bfde
                if (elevel_ >= ERROR) \
                        pg_unreachable(); \
        } while(0)
- #endif   /* HAVE__BUILTIN_CONSTANT_P */
+ #endif                                                        /* HAVE__BUILTIN_CONSTANT_P */
 +#endif
  
  #define ereport(elevel, rest) \
        ereport_domain(elevel, TEXTDOMAIN, rest)
@@@ -268,22 -214,14 +268,22 @@@ extern int      getinternalerrposition(void)
                                pg_unreachable(); \
                } \
        } while(0)
- #endif   /* HAVE__BUILTIN_CONSTANT_P */
+ #endif                                                        /* HAVE__BUILTIN_CONSTANT_P */
  #else                                                 /* !HAVE__VA_ARGS */
  #define elog  \
 -      elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), \
 +      do { \
 +              elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
 +      } while (0); \
        elog_finish
- #endif   /* HAVE__VA_ARGS */
+ #endif                                                        /* HAVE__VA_ARGS */
 +#endif
  
 -extern void elog_start(const char *filename, int lineno, const char *funcname);
 +extern void elog_start(const char *filename, int lineno,
 +#ifdef USE_MODULE_MSGIDS
 +              int moduleid, int flieid, int msgid,
 +#endif
 +              const char *funcname
 +              );
  extern void elog_finish(int elevel, const char *fmt,...) pg_attribute_printf(2, 3);
  
  
index 144281aa244bde9bda71f5cf9187bfafcd96ef6e,c1870d213014342f84888746eac23f71691e73e5..7917832a55b5d1a0071cbbeed88302ad0e318ba4
@@@ -445,6 -431,5 +445,6 @@@ extern void assign_search_path(const ch
  /* in access/transam/xlog.c */
  extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
  extern void assign_xlog_sync_method(int new_sync_method, void *extra);
 +extern const char *quote_guc_value(const char *value, int flags);
  
- #endif   /* GUC_H */
+ #endif                                                        /* GUC_H */
Simple merge
Simple merge
index fbb271ed1c719cb48efa8a528750616a97ece24b,87fab19f3cbf82584095dce8fe0c3d9bab3e26c1..2cb2241f453d9452c5d148e6f0924ae016985cc9
@@@ -111,14 -110,11 +111,14 @@@ typedef struct CachedPlanSourc
        bool            is_valid;               /* is the query_list currently valid? */
        int                     generation;             /* increments each time we create a plan */
        /* If CachedPlanSource has been saved, it is a member of a global list */
-       struct CachedPlanSource *next_saved;            /* list link, if so */
+       struct CachedPlanSource *next_saved;    /* list link, if so */
        /* State kept to help decide whether to use custom or generic plans: */
        double          generic_cost;   /* cost of generic plan, or -1 if not known */
-       double          total_custom_cost;              /* total cost of custom plans so far */
-       int                     num_custom_plans;               /* number of plans included in total */
+       double          total_custom_cost;      /* total cost of custom plans so far */
+       int                     num_custom_plans;       /* number of plans included in total */
 +#ifdef PGXC
 +      char       *stmt_name;          /* If set, this is a copy of prepared stmt name */
 +#endif
  } CachedPlanSource;
  
  /*
@@@ -188,9 -181,5 +188,9 @@@ extern CachedPlan *GetCachedPlan(Cached
                          bool useResOwner,
                          QueryEnvironment *queryEnv);
  extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
 +#ifdef XCP
 +extern void SetRemoteSubplan(CachedPlanSource *plansource,
 +                               const char *plan_string);
 +#endif
  
- #endif   /* PLANCACHE_H */
+ #endif                                                        /* PLANCACHE_H */
index c9ce886483fc99fa6b229e7a945e316de36e17f4,cb6f00081d5fd44553acc87489bfb456658254a5..0ec2eba5d3efac09ec5b0cb632727afdb0f6be99
@@@ -244,13 -236,6 +244,13 @@@ extern void PortalDefineQuery(Portal po
  extern PlannedStmt *PortalGetPrimaryStmt(Portal portal);
  extern void PortalCreateHoldStore(Portal portal);
  extern void PortalHashTableDeleteAll(void);
 +#ifdef XCP
 +extern void PortalCreateProducerStore(Portal portal);
 +extern List *getProducingPortals(void);
 +extern void addProducingPortal(Portal portal);
 +extern void removeProducingPortal(Portal portal);
 +extern bool portalIsProducing(Portal portal);
 +#endif
  extern bool ThereAreNoReadyPortals(void);
  
- #endif   /* PORTAL_H */
+ #endif                                                        /* PORTAL_H */
index dd5de58fefaa1f18c67f7a589a197d37661291e1,4bc61e53806b50c9f7d5f0efef7ef95daf3bbdbc..ab07f614c8acce821e26f73b65a84f4518ed277a
@@@ -217,10 -215,7 +217,10 @@@ typedef struct RelationDat
        Oid                     rd_toastoid;    /* Real TOAST table's OID, or InvalidOid */
  
        /* use "struct" here to avoid needing to include pgstat.h: */
-       struct PgStat_TableStatus *pgstat_info;         /* statistics collection area */
+       struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
 +#ifdef PGXC
 +      RelationLocInfo *rd_locator_info;
 +#endif
  } RelationData;
  
  
index 2f763d75390fcd83b0cf6576dce67e66b8b48f35,2420b651b39b4c3a2d0cfcef9838fb1366d5756a..4c9d1fe50e323e74044f4942429b248eb6dba98e
@@@ -88,13 -88,4 +88,13 @@@ extern void ResourceOwnerRememberDSM(Re
  extern void ResourceOwnerForgetDSM(ResourceOwner owner,
                                           dsm_segment *);
  
- #endif   /* RESOWNER_PRIVATE_H */
 +#ifdef XCP
 +/* support for prepared statement management */
 +extern void ResourceOwnerEnlargePreparedStmts(ResourceOwner owner);
 +extern void ResourceOwnerRememberPreparedStmt(ResourceOwner owner,
 +                                                char *stmt);
 +extern void ResourceOwnerForgetPreparedStmt(ResourceOwner owner,
 +                                              char *stmt);
 +#endif
 +
+ #endif                                                        /* RESOWNER_PRIVATE_H */
Simple merge
Simple merge
Simple merge
Simple merge
index aef4fc984040da19108568b2513d708600e804b9,7f4e1e318fa5ca1c44aa4c72c3bcd8e561ad6f1c..33b5c9f9969ed909908f318cd37cf89a7238cc7b
@@@ -89,14 -88,4 +89,14 @@@ extern void tuplestore_clear(Tuplestore
  
  extern void tuplestore_end(Tuplestorestate *state);
  
- #endif   /* TUPLESTORE_H */
 +#ifdef XCP
 +extern Tuplestorestate *tuplestore_begin_datarow(bool interXact, int maxKBytes,
 +                                               MemoryContext tmpcxt);
 +extern Tuplestorestate *tuplestore_begin_message(bool interXact, int maxKBytes);
 +extern void tuplestore_putmessage(Tuplestorestate *state, int len, char* msg);
 +extern char *tuplestore_getmessage(Tuplestorestate *state, int *len);
 +#endif
 +
 +extern void tuplestore_collect_stat(Tuplestorestate *state, char *name);
 +
+ #endif                                                        /* TUPLESTORE_H */
Simple merge
Simple merge
index 10a9db40e46daa067fd0dc99f01ab6abc2c610a9,9f4c88dab4ed76bdffe76a9687a44b872d01577e..53884191b8aa1c3240c91fde866d41a68c8b90f1
@@@ -5612,45 -5327,41 +5612,80 @@@ ERROR:  invalid reference to FROM-claus
  LINE 1: ...xx1 using lateral (select * from int4_tbl where f1 = x1) ss;
                                                                  ^
  HINT:  There is an entry for table "xx1", but it cannot be referenced from this part of the query.
 +-- demonstrate problem with extrememly slow join
 +CREATE TABLE testr (a int, b int) DISTRIBUTE BY REPLICATION;
 +INSERT INTO testr SELECT generate_series(1, 10000), generate_series(5001, 15000);
 +CREATE TABLE testh (a int, b int);
 +INSERT INTO testh SELECT generate_series(1, 10000), generate_series(8001, 18000);
 +set enable_mergejoin TO false;
 +set enable_hashjoin TO false;
 +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM testr WHERE NOT EXISTS (SELECT * FROM testh WHERE testr.b = testh.b);
 +                                    QUERY PLAN                                     
 +-----------------------------------------------------------------------------------
 + Finalize Aggregate
 +   Output: count(*)
 +   ->  Remote Subquery Scan on all (datanode_1,datanode_2)
 +         Output: PARTIAL count(*)
 +         ->  Partial Aggregate
 +               Output: PARTIAL count(*)
 +               ->  Nested Loop Anti Join
 +                     Join Filter: (testr.b = testh.b)
 +                     ->  Remote Subquery Scan on all (datanode_1)
 +                           Output: testr.b
 +                           Distribute results by H: b
 +                           ->  Seq Scan on public.testr
 +                                 Output: testr.b
 +                     ->  Materialize
 +                           Output: testh.b
 +                           ->  Remote Subquery Scan on all (datanode_1,datanode_2)
 +                                 Output: testh.b
 +                                 Distribute results by H: b
 +                                 ->  Seq Scan on public.testh
 +                                       Output: testh.b
 +(20 rows)
 +
 +SELECT count(*) FROM testr WHERE NOT EXISTS (SELECT * FROM testh WHERE testr.b = testh.b);
 + count 
 +-------
 +  3000
 +(1 row)
 +
 +
+ --
+ -- test that foreign key join estimation performs sanely for outer joins
+ --
+ begin;
+ create table fkest (a int, b int, c int unique, primary key(a,b));
+ create table fkest1 (a int, b int, primary key(a,b));
+ insert into fkest select x/10, x%10, x from generate_series(1,1000) x;
+ insert into fkest1 select x/10, x%10 from generate_series(1,1000) x;
+ alter table fkest1
+   add constraint fkest1_a_b_fkey foreign key (a,b) references fkest;
+ analyze fkest;
+ analyze fkest1;
+ explain (costs off)
+ select *
+ from fkest f
+   left join fkest1 f1 on f.a = f1.a and f.b = f1.b
+   left join fkest1 f2 on f.a = f2.a and f.b = f2.b
+   left join fkest1 f3 on f.a = f3.a and f.b = f3.b
+ where f.c = 1;
+                             QUERY PLAN                            
+ ------------------------------------------------------------------
+  Nested Loop Left Join
+    ->  Nested Loop Left Join
+          ->  Nested Loop Left Join
+                ->  Index Scan using fkest_c_key on fkest f
+                      Index Cond: (c = 1)
+                ->  Index Only Scan using fkest1_pkey on fkest1 f1
+                      Index Cond: ((a = f.a) AND (b = f.b))
+          ->  Index Only Scan using fkest1_pkey on fkest1 f2
+                Index Cond: ((a = f.a) AND (b = f.b))
+    ->  Index Only Scan using fkest1_pkey on fkest1 f3
+          Index Cond: ((a = f.a) AND (b = f.b))
+ (11 rows)
+ rollback;
  --
  -- test planner's ability to mark joins as unique
  --
Simple merge
Simple merge
Simple merge
Simple merge
index 83c2b5f5e3685d24703ad2c1de2d4b2f7b6e7447,835d67551cd56efed7f72f2575b7ad56c2a10ef0..2f70763034c188577398fd3df939d1708d83af20
@@@ -1778,16 -1733,34 +1778,44 @@@ delete from xx1 using (select * from in
  delete from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss;
  delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss;
  
 +-- demonstrate problem with extrememly slow join
 +CREATE TABLE testr (a int, b int) DISTRIBUTE BY REPLICATION;
 +INSERT INTO testr SELECT generate_series(1, 10000), generate_series(5001, 15000);
 +CREATE TABLE testh (a int, b int);
 +INSERT INTO testh SELECT generate_series(1, 10000), generate_series(8001, 18000);
 +set enable_mergejoin TO false;
 +set enable_hashjoin TO false;
 +EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM testr WHERE NOT EXISTS (SELECT * FROM testh WHERE testr.b = testh.b);
 +SELECT count(*) FROM testr WHERE NOT EXISTS (SELECT * FROM testh WHERE testr.b = testh.b);
 +
+ --
+ -- test that foreign key join estimation performs sanely for outer joins
+ --
+ begin;
+ create table fkest (a int, b int, c int unique, primary key(a,b));
+ create table fkest1 (a int, b int, primary key(a,b));
+ insert into fkest select x/10, x%10, x from generate_series(1,1000) x;
+ insert into fkest1 select x/10, x%10 from generate_series(1,1000) x;
+ alter table fkest1
+   add constraint fkest1_a_b_fkey foreign key (a,b) references fkest;
+ analyze fkest;
+ analyze fkest1;
+ explain (costs off)
+ select *
+ from fkest f
+   left join fkest1 f1 on f.a = f1.a and f.b = f1.b
+   left join fkest1 f2 on f.a = f2.a and f.b = f2.b
+   left join fkest1 f3 on f.a = f3.a and f.b = f3.b
+ where f.c = 1;
+ rollback;
  --
  -- test planner's ability to mark joins as unique
  --
Simple merge
Simple merge
Simple merge