Merge 'remotes/PGSQL/master' into xl10devel
authorPavan Deolasee <[email protected]>
Thu, 15 Jun 2017 07:41:07 +0000 (13:11 +0530)
committerPavan Deolasee <[email protected]>
Thu, 15 Jun 2017 07:41:07 +0000 (13:11 +0530)
Merge upstream master branch upto e800656d9a9b40b2f55afabe76354ab6d93353b3.
Code compiles and regression works ok (with lots and lots of failures though).

97 files changed:
1  2 
doc/src/sgml/catalogs.sgml
doc/src/sgml/config.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/func.sgml
doc/src/sgml/high-availability.sgml
doc/src/sgml/keywords.sgml
doc/src/sgml/libpq.sgml
doc/src/sgml/pgstattuple.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/copy.sgml
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/initdb.sgml
doc/src/sgml/ref/pgbench.sgml
doc/src/sgml/ref/pgupgrade.sgml
doc/src/sgml/ref/set_transaction.sgml
doc/src/sgml/xfunc.sgml
src/Makefile.global.in
src/backend/access/transam/parallel.c
src/backend/access/transam/recovery.conf.sample
src/backend/access/transam/subtrans.c
src/backend/access/transam/twophase.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/catalog.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/namespace.c
src/backend/catalog/objectaddress.c
src/backend/commands/copy.c
src/backend/commands/extension.c
src/backend/commands/indexcmds.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/variable.c
src/backend/executor/execMain.c
src/backend/executor/functions.c
src/backend/executor/nodeForeignscan.c
src/backend/executor/nodeModifyTable.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/util/plancat.c
src/backend/parser/gram.y
src/backend/parser/parse_agg.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_utilcmd.c
src/backend/postmaster/postmaster.c
src/backend/rewrite/rewriteHandler.c
src/backend/storage/ipc/procarray.c
src/backend/storage/ipc/procsignal.c
src/backend/storage/lmgr/predicate.c
src/backend/tcop/postgres.c
src/backend/tcop/utility.c
src/backend/utils/adt/jsonb.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/cache/syscache.c
src/backend/utils/init/globals.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/time/snapmgr.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c
src/bin/pgbench/pgbench.c
src/bin/psql/describe.c
src/bin/psql/tab-complete.c
src/include/Makefile
src/include/catalog/pg_proc.h
src/include/miscadmin.h
src/include/nodes/parsenodes.h
src/include/parser/parse_func.h
src/include/postgres.h
src/include/storage/procarray.h
src/include/storage/procsignal.h
src/include/utils/syscache.h
src/interfaces/libpq/fe-auth.c
src/test/regress/expected/alter_table.out
src/test/regress/expected/create_table.out
src/test/regress/expected/foreign_data.out
src/test/regress/expected/insert.out
src/test/regress/expected/join.out
src/test/regress/expected/plpgsql.out
src/test/regress/expected/rangefuncs.out
src/test/regress/expected/rowsecurity.out
src/test/regress/expected/triggers.out
src/test/regress/expected/updatable_views.out
src/test/regress/sql/alter_table.sql
src/test/regress/sql/insert.sql
src/test/regress/sql/plpgsql.sql
src/test/regress/sql/rangefuncs.sql
src/test/regress/sql/rowsecurity.sql
src/test/regress/sql/triggers.sql
src/test/regress/sql/updatable_views.sql

Simple merge
Simple merge
index 71339bf81de82c543b54a853487f6681c1b14909,ec015e93d07740a24ecc28ab74d12b4b9c33fddd..a70047b34052124a72d66527078dcbd60cfbf255
mode 100755,100644..100755
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 1dfbf6d3c802c12992a2892d92cf3c120dfab71d,69600321e60a61e9305884b48d9b811ec9be9930..c2a484186f6dd2624646398fa8b8762aa1368b3e
mode 100755,100644..100755
Simple merge
index 8d1e4ee487f49c47fad5b83ae080f1e0eb02a887,bc014d0879f671d471276c7921004fdba1702c98..5a3821b25e89448eab4645ef0703a08b45777353
mode 100755,100644..100755
Simple merge
Simple merge
Simple merge
index 11c3bfefcc662ba891047e4fdb5e8eebf6085ff9,188d2ed92ea2f255f4a6559ba7c5ecb6288219dd..e67c29e2ecbeb63c23d573562296ae6d307ed29a
mode 100755,100644..100755
Simple merge
Simple merge
Simple merge
index acb81afd66cc891b633d8789be173e1060cc3a84,8e466126428dc7d0395683d18d538b3acf42a62c..37fbaedaa52fc240cc8bf938242f036678e6f1f8
  # If you want to stop rollforward at a specific point, you
  # must set a recovery target.
  #
- # You may set a recovery target either by transactionId, by name,
- # or by timestamp or by WAL location (LSN) or by barrier. Recovery may either
- # include or exclude the transaction(s) with the recovery target value (ie,
- # stop either just after or just before the given target, respectively). In
- # case of barrier, the recovery stops exactly at that point.
+ # You may set a recovery target either by transactionId, by name, by
 -# timestamp or by WAL location (LSN). Recovery may either include or
++# timestamp or by WAL location (LSN) or by barrier. Recovery may either include or
+ # exclude the transaction(s) with the recovery target value (i.e.,
+ # stop either just after or just before the given target,
 -# respectively).
++# respectively). In case of barrier, the recovery stops exactly at that point.
  #
  #
  #recovery_target_name = ''    # e.g. 'daily backup 2011-01-26'
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 2e8cd10ebb24dbe7cbb617ab07683cdc12745d88,92d943cac7584ff55381b551b37229bedc3ed524..0f7ffef6d01b55eb9296730e55f6f4218704f2d8
  #include "catalog/pg_shseclabel.h"
  #include "catalog/pg_subscription.h"
  #include "catalog/pg_tablespace.h"
+ #include "catalog/pg_type.h"
  #include "catalog/toasting.h"
 +#include "catalog/pgxc_node.h"
 +#include "catalog/pgxc_group.h"
  #include "miscadmin.h"
  #include "storage/fd.h"
  #include "utils/fmgroids.h"
Simple merge
Simple merge
index d7f6075b13cf2cdb0de1c9c2702257a9b5099645,94755d687b74637ce8ea7b910b63dd4dc4cd82a4..a29a232e8b3e88bd23f6e387e07b37a1480f0828
@@@ -3898,18 -3793,8 +3898,18 @@@ InitTempTableNamespace(void
        if (IsParallelWorker())
                ereport(ERROR,
                                (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
-                                errmsg("cannot create temporary tables in parallel mode")));
+                                errmsg("cannot create temporary tables during a parallel operation")));
  
 +#ifdef XCP
 +      /*
 +       * In case of distributed session use MyFirstBackendId for temp objects
 +       */
 +      if (OidIsValid(MyCoordId))
 +              snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d",
 +                               MyFirstBackendId);
 +      else
 +      /* fallback to default */
 +#endif
        snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
  
        namespaceId = get_namespace_oid(namespaceName, true);
Simple merge
Simple merge
Simple merge
Simple merge
index ed50208d51f50adaa704c66aaa2a745beff0252e,2d820e5cebc859bfd9dfbdef4fcb5b0cfd46d870..13f818a0363c85f73a26557cdeecda547a67aef8
@@@ -145,10 -101,9 +145,10 @@@ static Form_pg_sequence_data read_seq_t
  static void init_params(ParseState *pstate, List *options, bool for_identity,
                        bool isInit,
                        Form_pg_sequence seqform,
-                       bool *changed_seqform,
-                       Form_pg_sequence_data seqdataform, List **owned_by,
+                       Form_pg_sequence_data seqdataform,
+                       bool *need_seq_rewrite,
 -                      List **owned_by);
++                      List **owned_by,
 +                      bool *is_restart);
  static void do_setval(Oid relid, int64 next, bool iscalled);
  static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity);
  
@@@ -210,8 -156,9 +210,10 @@@ DefineSequence(ParseState *pstate, Crea
        }
  
        /* Check and set all option values */
-       init_params(pstate, seq->options, seq->for_identity, true, &seqform,
-                       &changed_seqform, &seqdataform, &owned_by, &is_restart);
+       init_params(pstate, seq->options, seq->for_identity, true,
+                               &seqform, &seqdataform,
 -                              &need_seq_rewrite, &owned_by);
++                              &need_seq_rewrite, &owned_by,
++                              &is_restart);
  
        /*
         * Create relation (and fill value[] and null[] for the tuple)
@@@ -497,24 -419,15 +499,24 @@@ AlterSequence(ParseState *pstate, Alter
        SeqTable        elm;
        Relation        seqrel;
        Buffer          buf;
-       HeapTupleData seqdatatuple;
+       HeapTupleData datatuple;
        Form_pg_sequence seqform;
-       Form_pg_sequence_data seqdata;
-       FormData_pg_sequence_data newseqdata;
-       bool            changed_seqform = false;
+       Form_pg_sequence_data newdataform;
+       bool            need_seq_rewrite;
        List       *owned_by;
 +#ifdef PGXC
 +      GTM_Sequence    start_value;
 +      GTM_Sequence    last_value;
 +      GTM_Sequence    min_value;
 +      GTM_Sequence    max_value;
 +      GTM_Sequence    increment;
 +      bool                    cycle;
 +      bool                    is_restart;
 +#endif
        ObjectAddress address;
        Relation        rel;
-       HeapTuple       tuple;
+       HeapTuple       seqtuple;
+       HeapTuple       newdatatuple;
  
        /* Open and lock sequence. */
        relid = RangeVarGetRelid(stmt->sequence,
                elog(ERROR, "cache lookup failed for sequence %u",
                         relid);
  
-       seqform = (Form_pg_sequence) GETSTRUCT(tuple);
+       seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
  
        /* lock page's buffer and read tuple into new sequence structure */
-       seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
+       (void) read_seq_tuple(seqrel, &buf, &datatuple);
+       /* copy the existing sequence data tuple, so it can be modified localy */
+       newdatatuple = heap_copytuple(&datatuple);
+       newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
  
-       /* Copy old sequence data into workspace */
-       memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
+       UnlockReleaseBuffer(buf);
  
        /* Check and set new values */
-       init_params(pstate, stmt->options, stmt->for_identity, false, seqform,
-                       &changed_seqform, &newseqdata, &owned_by, &is_restart);
+       init_params(pstate, stmt->options, stmt->for_identity, false,
+                               seqform, newdataform,
 -                              &need_seq_rewrite, &owned_by);
++                              &need_seq_rewrite, &owned_by,
++                              &is_restart);
  
        /* Clear local cache so that we don't think we have cached numbers */
        /* Note that we do not change the currval() state */
        elm->cached = elm->last;
  
-       /* check the comment above nextval_internal()'s equivalent call. */
-       if (RelationNeedsWAL(seqrel))
-               GetTopTransactionId();
 +      /* Now okay to update the on-disk tuple */
 +#ifdef PGXC
 +      increment = seqform->seqincrement;
 +      min_value = seqform->seqmin;
 +      max_value = seqform->seqmax;
 +      start_value = seqform->seqstart;
 +      last_value = elm->last;
 +      cycle = seqform->seqcycle;
 +#endif
 +
-       START_CRIT_SECTION();
-       memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
-       MarkBufferDirty(buf);
-       /* XLOG stuff */
-       if (RelationNeedsWAL(seqrel))
+       /* If needed, rewrite the sequence relation itself */
+       if (need_seq_rewrite)
        {
-               xl_seq_rec      xlrec;
-               XLogRecPtr      recptr;
-               Page            page = BufferGetPage(buf);
-               XLogBeginInsert();
-               XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
-               xlrec.node = seqrel->rd_node;
-               XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
-               XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
+               /* check the comment above nextval_internal()'s equivalent call. */
+               if (RelationNeedsWAL(seqrel))
+                       GetTopTransactionId();
  
-               recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
+               /*
+                * Create a new storage file for the sequence, making the state
+                * changes transactional.  We want to keep the sequence's relfrozenxid
+                * at 0, since it won't contain any unfrozen XIDs.  Same with
+                * relminmxid, since a sequence will never contain multixacts.
+                */
+               RelationSetNewRelfilenode(seqrel, seqrel->rd_rel->relpersistence,
+                                                                 InvalidTransactionId, InvalidMultiXactId);
  
-               PageSetLSN(page, recptr);
+               /*
+                * Insert the modified tuple into the new storage file.
+                */
+               fill_seq_with_data(seqrel, newdatatuple);
        }
  
-       END_CRIT_SECTION();
-       UnlockReleaseBuffer(buf);
        /* process OWNED BY if given */
        if (owned_by)
                process_owned_by(seqrel, owned_by, stmt->for_identity);
  
        ObjectAddressSet(address, RelationRelationId, relid);
  
-       if (changed_seqform)
-               CatalogTupleUpdate(rel, &tuple->t_self, tuple);
        heap_close(rel, RowExclusiveLock);
        relation_close(seqrel, NoLock);
  
 +#ifdef PGXC
 +      /*
 +       * Remote Coordinator is in charge of create sequence in GTM
 +       * If sequence is temporary, no need to go through GTM.
 +       */
 +      if (IS_PGXC_LOCAL_COORDINATOR && seqrel->rd_backend != MyBackendId)
 +      {
 +              char *seqname = GetGlobalSeqName(seqrel, NULL, NULL);
 +
 +              /* We also need to create it on the GTM */
 +              if (AlterSequenceGTM(seqname,
 +                                                       increment,
 +                                                       min_value,
 +                                                       max_value,
 +                                                       start_value,
 +                                                       last_value,
 +                                                       cycle,
 +                                                       is_restart) < 0)
 +                      ereport(ERROR,
 +                                      (errcode(ERRCODE_CONNECTION_FAILURE),
 +                                       errmsg("GTM error, could not alter sequence")));
 +              pfree(seqname);
 +      }
 +#endif
        return address;
  }
  
@@@ -1485,10 -1236,9 +1464,10 @@@ static voi
  init_params(ParseState *pstate, List *options, bool for_identity,
                        bool isInit,
                        Form_pg_sequence seqform,
-                       bool *changed_seqform,
                        Form_pg_sequence_data seqdataform,
 -                      List **owned_by)
+                       bool *need_seq_rewrite,
 +                      List **owned_by,
 +                      bool *is_restart)
  {
        DefElem    *as_type = NULL;
        DefElem    *start_value = NULL;
        bool            reset_max_value = false;
        bool            reset_min_value = false;
  
 +#ifdef PGXC
 +      *is_restart = false;
 +#endif
 +
+       *need_seq_rewrite = false;
        *owned_by = NIL;
  
        foreach(option, options)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5147eaa4d3150eaec1e16713f8685d79fdc0317a,039910e1f7003da568b8b841424590d9874c525e..935bb196f7bbf7bfcc410ac5cbdea242b143228d
@@@ -4023,15 -2637,9 +4022,15 @@@ parseNodeString(void
                return_value = _readAlternativeSubPlan();
        else if (MATCH("EXTENSIBLENODE", 14))
                return_value = _readExtensibleNode();
-       else if (MATCH("PARTITIONBOUND", 14))
 +      else if (MATCH("REMOTESUBPLAN", 13))
 +              return_value = _readRemoteSubplan();
 +      else if (MATCH("REMOTESTMT", 10))
 +              return_value = _readRemoteStmt();
 +      else if (MATCH("SIMPLESORT", 10))
 +              return_value = _readSimpleSort();
+       else if (MATCH("PARTITIONBOUNDSPEC", 18))
                return_value = _readPartitionBoundSpec();
-       else if (MATCH("PARTRANGEDATUM", 14))
+       else if (MATCH("PARTITIONRANGEDATUM", 19))
                return_value = _readPartitionRangeDatum();
        else
        {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 30aea14385a5c2cb2ca81f8cc8b55d2db17caaa6,bce505a3fac8c309d477ff2d8a2914c6df9a9be7..38c2e493a550aee12491efafd8729cf1fe460b36
@@@ -1741,9 -1745,9 +1745,9 @@@ GetSerializableTransactionSnapshotInt(S
        } while (!sxact);
  
        /* Get the snapshot, or check that it's safe to use */
-       if (!TransactionIdIsValid(sourcexid))
+       if (!sourcevxid)
 -              snapshot = GetSnapshotData(snapshot);
 +              snapshot = GetSnapshotData(snapshot, false);
-       else if (!ProcArrayInstallImportedXmin(snapshot->xmin, sourcexid))
+       else if (!ProcArrayInstallImportedXmin(snapshot->xmin, sourcevxid))
        {
                ReleasePredXact(sxact);
                LWLockRelease(SerializableXactHashLock);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 9534134e61856b58360fb1178d554b4c2776be4d,2a08abfba51ac1200bded0b22796a690f7cf3589..fbd6342de5f56158a13e799008aedf77af3f93a5
@@@ -144,11 -136,7 +145,10 @@@ main(int argc, char *argv[]
                {"no-subscriptions", no_argument, &no_subscriptions, 1},
                {"no-sync", no_argument, NULL, 4},
                {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
-               {"no-role-passwords", no_argument, &no_role_passwords, 1},
 -
 +#ifdef PGXC
 +              {"dump-nodes", no_argument, &dump_nodes, 1},
 +              {"include-nodes", no_argument, &include_nodes, 1},
 +#endif
                {NULL, 0, NULL, 0}
        };
  
Simple merge
Simple merge
Simple merge
index 6afa3cfe25e253c68166809f624fb2a94b9fabea,a689d352b6b99e62c47d58595eac2ba67853ac85..ea3b9245c055b30b8da5f4191b5b623c0c045e5f
@@@ -19,11 -19,11 +19,11 @@@ all: pg_config.h pg_config_ext.h pg_con
  # Subdirectories containing installable headers
  SUBDIRS = access bootstrap catalog commands common datatype \
        executor fe_utils foreign \
 -      lib libpq mb nodes optimizer parser postmaster regex replication \
 +      lib libpq mb nodes optimizer parser pgxc postmaster regex replication \
-       rewrite storage tcop snowball snowball/libstemmer tsearch \
+       rewrite statistics storage tcop snowball snowball/libstemmer tsearch \
        tsearch/dicts utils port port/atomics port/win32 port/win32_msvc \
        port/win32_msvc/sys port/win32/arpa port/win32/netinet \
 -      port/win32/sys portability
 +      port/win32/sys portability gtm
  
  # Install all headers
  install: all installdirs
Simple merge
Simple merge
index 8d4e58ca89cf9158d49473d6f50541a5d14a8285,271564fd23b735fee0306aea915ab587daa82d93..fb3684eb5c3ff260924469e814a6b00a8f892aa9
@@@ -951,12 -942,13 +951,17 @@@ typedef struct RangeTblEntr
         * code that is being actively worked on.  FIXME someday.
         */
  
 +#ifdef PGXC
 +      char            *relname;
 +#endif
 +
        /*
         * Fields valid for a plain relation RTE (else zero):
+        *
+        * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
+        * that the tuple format of the tuplestore is the same as the referenced
+        * relation.  This allows plans referencing AFTER trigger transition
+        * tables to be invalidated if the underlying table is altered.
         */
        Oid                     relid;                  /* OID of the relation */
        char            relkind;                /* relation kind (see pg_class.relkind) */
index e0dad6ac10a9547c5a5a7530c309d803e2e27eb0,68572e9d2a92b4c13eaefdd0139e7ad789ab1016..c684217e33cd9cb8e89537dd7028152a9de1f8e7
@@@ -67,7 -67,7 +67,8 @@@ extern Oid LookupFuncWithArgs(ObjectWit
  extern Oid LookupAggWithArgs(ObjectWithArgs *agg,
                                  bool noError);
  
- extern void check_srf_call_placement(ParseState *pstate, int location);
+ extern void check_srf_call_placement(ParseState *pstate, Node *last_srf,
+                                                int location);
  
 +extern void check_pg_get_expr_args(ParseState *pstate, Oid fnoid, List *args);
  #endif   /* PARSE_FUNC_H */
Simple merge
index bc46229b4265235746e03d2588c42ba6c27b10bc,5cf8ff753843745da59ff732c942233b1b439d43..7dfe37f881a66f88f7af58deadde81536516a2af
@@@ -105,13 -79,11 +105,13 @@@ extern void ExpireOldKnownAssignedTrans
  extern int    GetMaxSnapshotXidCount(void);
  extern int    GetMaxSnapshotSubxidCount(void);
  
 -extern Snapshot GetSnapshotData(Snapshot snapshot);
 +extern Snapshot GetSnapshotData(Snapshot snapshot, bool latest);
  
  extern bool ProcArrayInstallImportedXmin(TransactionId xmin,
-                                                        TransactionId sourcexid);
+                                                        VirtualTransactionId *sourcevxid);
  extern bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc);
 +extern void ProcArrayCheckXminConsistency(TransactionId global_xmin);
 +extern void SetLatestCompletedXid(TransactionId latestCompletedXid);
  
  extern RunningTransactions GetRunningTransactionData(void);
  
index 67cb9138294811adead209279b919d989cd5027a,8f0161bf77f206b9d5a274b0cefdab4844a16d5b..d58c1bede970d3f604bc8d29f0b093a91d1ca191
@@@ -41,11 -31,9 +41,13 @@@ 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  */
  
        /* Recovery conflict reasons */
        PROCSIG_RECOVERY_CONFLICT_DATABASE,
Simple merge
Simple merge
index de22510740617ded55a5b047df598f6cd02f7712,7f2f529393d6682a69702cb32d3975074b97f87d..cdafb90762c35a06fc0cdd005a3f8e349e193339
@@@ -266,73 -283,65 +266,72 @@@ ERROR:  foreign-data wrapper "foo" doe
  
  -- exercise CREATE SERVER
  CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
 -ERROR:  foreign-data wrapper "foo" does not exist
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE FOREIGN DATA WRAPPER foo OPTIONS ("test wrapper" 'true');
 +ERROR:  Postgres-XL does not support FOREIGN DATA WRAPPER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
 -ERROR:  server "s1" already exists
 -CREATE SERVER IF NOT EXISTS s1 FOREIGN DATA WRAPPER foo;      -- No ERROR, just NOTICE
 -NOTICE:  server "s1" already exists, skipping
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s2 FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s3 TYPE 'oracle' FOREIGN DATA WRAPPER foo;
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s4 TYPE 'oracle' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s5 VERSION '15.0' FOREIGN DATA WRAPPER foo;
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s6 VERSION '16.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s7 TYPE 'oracle' VERSION '17.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (foo '1'); -- ERROR
 -ERROR:  invalid option "foo"
 -HINT:  Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db');
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  \des+
 -                                                             List of foreign servers
 - Name |           Owner           | Foreign-data wrapper | Access privileges |  Type  | Version |            FDW options            | Description 
 -------+---------------------------+----------------------+-------------------+--------+---------+-----------------------------------+-------------
 - s1   | regress_foreign_data_user | foo                  |                   |        |         |                                   | 
 - s2   | regress_foreign_data_user | foo                  |                   |        |         | (host 'a', dbname 'b')            | 
 - s3   | regress_foreign_data_user | foo                  |                   | oracle |         |                                   | 
 - s4   | regress_foreign_data_user | foo                  |                   | oracle |         | (host 'a', dbname 'b')            | 
 - s5   | regress_foreign_data_user | foo                  |                   |        | 15.0    |                                   | 
 - s6   | regress_foreign_data_user | foo                  |                   |        | 16.0    | (host 'a', dbname 'b')            | 
 - s7   | regress_foreign_data_user | foo                  |                   | oracle | 17.0    | (host 'a', dbname 'b')            | 
 - s8   | regress_foreign_data_user | postgresql           |                   |        |         | (host 'localhost', dbname 's8db') | 
 -(8 rows)
 -
 +                                       List of foreign servers
 + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description 
 +------+-------+----------------------+-------------------+------+---------+-------------+-------------
 +(0 rows)
  SET ROLE regress_test_role;
  CREATE SERVER t1 FOREIGN DATA WRAPPER foo;                 -- ERROR: no usage on FDW
 -ERROR:  permission denied for foreign-data wrapper foo
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  RESET ROLE;
  GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role;
 +ERROR:  foreign-data wrapper "foo" does not exist
  SET ROLE regress_test_role;
  CREATE SERVER t1 FOREIGN DATA WRAPPER foo;
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  RESET ROLE;
  \des+
 -                                                             List of foreign servers
 - Name |           Owner           | Foreign-data wrapper | Access privileges |  Type  | Version |            FDW options            | Description 
 -------+---------------------------+----------------------+-------------------+--------+---------+-----------------------------------+-------------
 - s1   | regress_foreign_data_user | foo                  |                   |        |         |                                   | 
 - s2   | regress_foreign_data_user | foo                  |                   |        |         | (host 'a', dbname 'b')            | 
 - s3   | regress_foreign_data_user | foo                  |                   | oracle |         |                                   | 
 - s4   | regress_foreign_data_user | foo                  |                   | oracle |         | (host 'a', dbname 'b')            | 
 - s5   | regress_foreign_data_user | foo                  |                   |        | 15.0    |                                   | 
 - s6   | regress_foreign_data_user | foo                  |                   |        | 16.0    | (host 'a', dbname 'b')            | 
 - s7   | regress_foreign_data_user | foo                  |                   | oracle | 17.0    | (host 'a', dbname 'b')            | 
 - s8   | regress_foreign_data_user | postgresql           |                   |        |         | (host 'localhost', dbname 's8db') | 
 - t1   | regress_test_role         | foo                  |                   |        |         |                                   | 
 -(9 rows)
 +                                       List of foreign servers
 + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description 
 +------+-------+----------------------+-------------------+------+---------+-------------+-------------
 +(0 rows)
  
  REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM regress_test_role;
 +ERROR:  foreign-data wrapper "foo" does not exist
  GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_indirect;
 +ERROR:  foreign-data wrapper "foo" does not exist
  SET ROLE regress_test_role;
  CREATE SERVER t2 FOREIGN DATA WRAPPER foo;                 -- ERROR
 -ERROR:  permission denied for foreign-data wrapper foo
 +ERROR:  Postgres-XL does not support SERVER yet
 +DETAIL:  The feature is not currently supported
  RESET ROLE;
  GRANT regress_test_indirect TO regress_test_role;
  SET ROLE regress_test_role;
Simple merge
Simple merge
Simple merge
index 67fd53a2a06a14e62644cae798e84aeee9ec2c6e,26d28f248b14c3c77377caed70fc92c742b1bb84..68c4e740fe11d7cdbd72d69fb44b6076b8c9e1eb
@@@ -784,20 -888,453 +784,456 @@@ SELECT * FROM t1 WHERE f_leak(b)
  (11 rows)
  
  EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
 -        QUERY PLAN         
 ----------------------------
 +                        QUERY PLAN                         
 +-----------------------------------------------------------
   Append
 -   ->  Seq Scan on t1
 -         Filter: f_leak(b)
 -   ->  Seq Scan on t2
 -         Filter: f_leak(b)
 -   ->  Seq Scan on t3
 -         Filter: f_leak(b)
 -(7 rows)
 +   ->  Remote Subquery Scan on all (datanode_1,datanode_2)
 +         ->  Seq Scan on t1
 +               Filter: f_leak(b)
 +   ->  Remote Subquery Scan on all (datanode_1,datanode_2)
 +         ->  Seq Scan on t2
 +               Filter: f_leak(b)
 +   ->  Remote Subquery Scan on all (datanode_1,datanode_2)
 +         ->  Seq Scan on t3
 +               Filter: f_leak(b)
 +(10 rows)
  
+ --
+ -- Partitioned Tables
+ --
+ SET SESSION AUTHORIZATION regress_rls_alice;
+ CREATE TABLE part_document (
+     did         int,
+     cid         int,
+     dlevel      int not null,
+     dauthor     name,
+     dtitle      text
+ ) PARTITION BY RANGE (cid);
+ GRANT ALL ON part_document TO public;
+ -- Create partitions for document categories
+ CREATE TABLE part_document_fiction PARTITION OF part_document FOR VALUES FROM (11) to (12);
+ CREATE TABLE part_document_satire PARTITION OF part_document FOR VALUES FROM (55) to (56);
+ CREATE TABLE part_document_nonfiction PARTITION OF part_document FOR VALUES FROM (99) to (100);
+ GRANT ALL ON part_document_fiction TO public;
+ GRANT ALL ON part_document_satire TO public;
+ GRANT ALL ON part_document_nonfiction TO public;
+ INSERT INTO part_document VALUES
+     ( 1, 11, 1, 'regress_rls_bob', 'my first novel'),
+     ( 2, 11, 2, 'regress_rls_bob', 'my second novel'),
+     ( 3, 99, 2, 'regress_rls_bob', 'my science textbook'),
+     ( 4, 55, 1, 'regress_rls_bob', 'my first satire'),
+     ( 5, 99, 2, 'regress_rls_bob', 'my history book'),
+     ( 6, 11, 1, 'regress_rls_carol', 'great science fiction'),
+     ( 7, 99, 2, 'regress_rls_carol', 'great technology book'),
+     ( 8, 55, 2, 'regress_rls_carol', 'great satire'),
+     ( 9, 11, 1, 'regress_rls_dave', 'awesome science fiction'),
+     (10, 99, 2, 'regress_rls_dave', 'awesome technology book');
+ ALTER TABLE part_document ENABLE ROW LEVEL SECURITY;
+ -- Create policy on parent
+ -- user's security level must be higher than or equal to document's
+ CREATE POLICY pp1 ON part_document AS PERMISSIVE
+     USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user));
+ -- Dave is only allowed to see cid < 55
+ CREATE POLICY pp1r ON part_document AS RESTRICTIVE TO regress_rls_dave
+     USING (cid < 55);
+ \d+ part_document
+                           Table "regress_rls_schema.part_document"
+  Column  |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
+ ---------+---------+-----------+----------+---------+----------+--------------+-------------
+  did     | integer |           |          |         | plain    |              | 
+  cid     | integer |           |          |         | plain    |              | 
+  dlevel  | integer |           | not null |         | plain    |              | 
+  dauthor | name    |           |          |         | plain    |              | 
+  dtitle  | text    |           |          |         | extended |              | 
+ Partition key: RANGE (cid)
+ Policies:
+     POLICY "pp1"
+       USING ((dlevel <= ( SELECT uaccount.seclv
+    FROM uaccount
+   WHERE (uaccount.pguser = CURRENT_USER))))
+     POLICY "pp1r" AS RESTRICTIVE
+       TO regress_rls_dave
+       USING ((cid < 55))
+ Partitions: part_document_fiction FOR VALUES FROM (11) TO (12),
+             part_document_nonfiction FOR VALUES FROM (99) TO (100),
+             part_document_satire FOR VALUES FROM (55) TO (56)
+ SELECT * FROM pg_policies WHERE schemaname = 'regress_rls_schema' AND tablename like '%part_document%' ORDER BY policyname;
+      schemaname     |   tablename   | policyname | permissive  |       roles        | cmd |                    qual                    | with_check 
+ --------------------+---------------+------------+-------------+--------------------+-----+--------------------------------------------+------------
+  regress_rls_schema | part_document | pp1        | PERMISSIVE  | {public}           | ALL | (dlevel <= ( SELECT uaccount.seclv        +| 
+                     |               |            |             |                    |     |    FROM uaccount                          +| 
+                     |               |            |             |                    |     |   WHERE (uaccount.pguser = CURRENT_USER))) | 
+  regress_rls_schema | part_document | pp1r       | RESTRICTIVE | {regress_rls_dave} | ALL | (cid < 55)                                 | 
+ (2 rows)
+ -- viewpoint from regress_rls_bob
+ SET SESSION AUTHORIZATION regress_rls_bob;
+ SET row_security TO ON;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+ NOTICE:  f_leak => my first satire
+  did | cid | dlevel |      dauthor      |         dtitle          
+ -----+-----+--------+-------------------+-------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+ (4 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                      QUERY PLAN                      
+ -----------------------------------------------------
+  Append
+    InitPlan 1 (returns $0)
+      ->  Index Scan using uaccount_pkey on uaccount
+            Index Cond: (pguser = CURRENT_USER)
+    ->  Seq Scan on part_document_fiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_satire
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_nonfiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+ (10 rows)
+ -- viewpoint from regress_rls_carol
+ SET SESSION AUTHORIZATION regress_rls_carol;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+ NOTICE:  f_leak => my first satire
+ NOTICE:  f_leak => great satire
+ NOTICE:  f_leak => my science textbook
+ NOTICE:  f_leak => my history book
+ NOTICE:  f_leak => great technology book
+ NOTICE:  f_leak => awesome technology book
+  did | cid | dlevel |      dauthor      |         dtitle          
+ -----+-----+--------+-------------------+-------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    3 |  99 |      2 | regress_rls_bob   | my science textbook
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    5 |  99 |      2 | regress_rls_bob   | my history book
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+   10 |  99 |      2 | regress_rls_dave  | awesome technology book
+ (10 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                      QUERY PLAN                      
+ -----------------------------------------------------
+  Append
+    InitPlan 1 (returns $0)
+      ->  Index Scan using uaccount_pkey on uaccount
+            Index Cond: (pguser = CURRENT_USER)
+    ->  Seq Scan on part_document_fiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_satire
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_nonfiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+ (10 rows)
+ -- viewpoint from regress_rls_dave
+ SET SESSION AUTHORIZATION regress_rls_dave;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+  did | cid | dlevel |      dauthor      |         dtitle          
+ -----+-----+--------+-------------------+-------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+ (4 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                              QUERY PLAN                             
+ --------------------------------------------------------------------
+  Append
+    InitPlan 1 (returns $0)
+      ->  Index Scan using uaccount_pkey on uaccount
+            Index Cond: (pguser = CURRENT_USER)
+    ->  Seq Scan on part_document_fiction
+          Filter: ((cid < 55) AND (dlevel <= $0) AND f_leak(dtitle))
+ (6 rows)
+ -- pp1 ERROR
+ INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_dave', 'testing pp1'); -- fail
+ ERROR:  new row violates row-level security policy for table "part_document"
+ -- pp1r ERROR
+ INSERT INTO part_document VALUES (100, 99, 1, 'regress_rls_dave', 'testing pp1r'); -- fail
+ ERROR:  new row violates row-level security policy "pp1r" for table "part_document"
+ -- Show that RLS policy does not apply for direct inserts to children
+ -- This should fail with RLS POLICY pp1r violation.
+ INSERT INTO part_document VALUES (100, 55, 1, 'regress_rls_dave', 'testing RLS with partitions'); -- fail
+ ERROR:  new row violates row-level security policy "pp1r" for table "part_document"
+ -- But this should succeed.
+ INSERT INTO part_document_satire VALUES (100, 55, 1, 'regress_rls_dave', 'testing RLS with partitions'); -- success
+ -- We still cannot see the row using the parent
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+  did | cid | dlevel |      dauthor      |         dtitle          
+ -----+-----+--------+-------------------+-------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+ (4 rows)
+ -- But we can if we look directly
+ SELECT * FROM part_document_satire WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first satire
+ NOTICE:  f_leak => great satire
+ NOTICE:  f_leak => testing RLS with partitions
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    8 |  55 |      2 | regress_rls_carol | great satire
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (3 rows)
+ -- Turn on RLS and create policy on child to show RLS is checked before constraints
+ SET SESSION AUTHORIZATION regress_rls_alice;
+ ALTER TABLE part_document_satire ENABLE ROW LEVEL SECURITY;
+ CREATE POLICY pp3 ON part_document_satire AS RESTRICTIVE
+     USING (cid < 55);
+ -- This should fail with RLS violation now.
+ SET SESSION AUTHORIZATION regress_rls_dave;
+ INSERT INTO part_document_satire VALUES (101, 55, 1, 'regress_rls_dave', 'testing RLS with partitions'); -- fail
+ ERROR:  new row violates row-level security policy for table "part_document_satire"
+ -- And now we cannot see directly into the partition either, due to RLS
+ SELECT * FROM part_document_satire WHERE f_leak(dtitle) ORDER BY did;
+  did | cid | dlevel | dauthor | dtitle 
+ -----+-----+--------+---------+--------
+ (0 rows)
+ -- The parent looks same as before
+ -- viewpoint from regress_rls_dave
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+  did | cid | dlevel |      dauthor      |         dtitle          
+ -----+-----+--------+-------------------+-------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+ (4 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                              QUERY PLAN                             
+ --------------------------------------------------------------------
+  Append
+    InitPlan 1 (returns $0)
+      ->  Index Scan using uaccount_pkey on uaccount
+            Index Cond: (pguser = CURRENT_USER)
+    ->  Seq Scan on part_document_fiction
+          Filter: ((cid < 55) AND (dlevel <= $0) AND f_leak(dtitle))
+ (6 rows)
+ -- viewpoint from regress_rls_carol
+ SET SESSION AUTHORIZATION regress_rls_carol;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => awesome science fiction
+ NOTICE:  f_leak => my first satire
+ NOTICE:  f_leak => great satire
+ NOTICE:  f_leak => testing RLS with partitions
+ NOTICE:  f_leak => my science textbook
+ NOTICE:  f_leak => my history book
+ NOTICE:  f_leak => great technology book
+ NOTICE:  f_leak => awesome technology book
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    3 |  99 |      2 | regress_rls_bob   | my science textbook
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    5 |  99 |      2 | regress_rls_bob   | my history book
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+   10 |  99 |      2 | regress_rls_dave  | awesome technology book
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (11 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                      QUERY PLAN                      
+ -----------------------------------------------------
+  Append
+    InitPlan 1 (returns $0)
+      ->  Index Scan using uaccount_pkey on uaccount
+            Index Cond: (pguser = CURRENT_USER)
+    ->  Seq Scan on part_document_fiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_satire
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_nonfiction
+          Filter: ((dlevel <= $0) AND f_leak(dtitle))
+ (10 rows)
+ -- only owner can change policies
+ ALTER POLICY pp1 ON part_document USING (true);    --fail
+ ERROR:  must be owner of relation part_document
+ DROP POLICY pp1 ON part_document;                  --fail
+ ERROR:  must be owner of relation part_document
+ SET SESSION AUTHORIZATION regress_rls_alice;
+ ALTER POLICY pp1 ON part_document USING (dauthor = current_user);
+ -- viewpoint from regress_rls_bob again
+ SET SESSION AUTHORIZATION regress_rls_bob;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => my first novel
+ NOTICE:  f_leak => my second novel
+ NOTICE:  f_leak => my first satire
+ NOTICE:  f_leak => my science textbook
+ NOTICE:  f_leak => my history book
+  did | cid | dlevel |     dauthor     |       dtitle        
+ -----+-----+--------+-----------------+---------------------
+    1 |  11 |      1 | regress_rls_bob | my first novel
+    2 |  11 |      2 | regress_rls_bob | my second novel
+    3 |  99 |      2 | regress_rls_bob | my science textbook
+    4 |  55 |      1 | regress_rls_bob | my first satire
+    5 |  99 |      2 | regress_rls_bob | my history book
+ (5 rows)
+ -- viewpoint from rls_regres_carol again
+ SET SESSION AUTHORIZATION regress_rls_carol;
+ SELECT * FROM part_document WHERE f_leak(dtitle) ORDER BY did;
+ NOTICE:  f_leak => great science fiction
+ NOTICE:  f_leak => great satire
+ NOTICE:  f_leak => great technology book
+  did | cid | dlevel |      dauthor      |        dtitle         
+ -----+-----+--------+-------------------+-----------------------
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+ (3 rows)
+ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
+                           QUERY PLAN                           
+ ---------------------------------------------------------------
+  Append
+    ->  Seq Scan on part_document_fiction
+          Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_satire
+          Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
+    ->  Seq Scan on part_document_nonfiction
+          Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
+ (7 rows)
+ -- database superuser does bypass RLS policy when enabled
+ RESET SESSION AUTHORIZATION;
+ SET row_security TO ON;
+ SELECT * FROM part_document ORDER BY did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    3 |  99 |      2 | regress_rls_bob   | my science textbook
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    5 |  99 |      2 | regress_rls_bob   | my history book
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+   10 |  99 |      2 | regress_rls_dave  | awesome technology book
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (11 rows)
+ SELECT * FROM part_document_satire ORDER by did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    8 |  55 |      2 | regress_rls_carol | great satire
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (3 rows)
+ -- database non-superuser with bypass privilege can bypass RLS policy when disabled
+ SET SESSION AUTHORIZATION regress_rls_exempt_user;
+ SET row_security TO OFF;
+ SELECT * FROM part_document ORDER BY did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    3 |  99 |      2 | regress_rls_bob   | my science textbook
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    5 |  99 |      2 | regress_rls_bob   | my history book
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+   10 |  99 |      2 | regress_rls_dave  | awesome technology book
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (11 rows)
+ SELECT * FROM part_document_satire ORDER by did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    8 |  55 |      2 | regress_rls_carol | great satire
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (3 rows)
+ -- RLS policy does not apply to table owner when RLS enabled.
+ SET SESSION AUTHORIZATION regress_rls_alice;
+ SET row_security TO ON;
+ SELECT * FROM part_document ORDER by did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    1 |  11 |      1 | regress_rls_bob   | my first novel
+    2 |  11 |      2 | regress_rls_bob   | my second novel
+    3 |  99 |      2 | regress_rls_bob   | my science textbook
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    5 |  99 |      2 | regress_rls_bob   | my history book
+    6 |  11 |      1 | regress_rls_carol | great science fiction
+    7 |  99 |      2 | regress_rls_carol | great technology book
+    8 |  55 |      2 | regress_rls_carol | great satire
+    9 |  11 |      1 | regress_rls_dave  | awesome science fiction
+   10 |  99 |      2 | regress_rls_dave  | awesome technology book
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (11 rows)
+ SELECT * FROM part_document_satire ORDER by did;
+  did | cid | dlevel |      dauthor      |           dtitle            
+ -----+-----+--------+-------------------+-----------------------------
+    4 |  55 |      1 | regress_rls_bob   | my first satire
+    8 |  55 |      2 | regress_rls_carol | great satire
+  100 |  55 |      1 | regress_rls_dave  | testing RLS with partitions
+ (3 rows)
+ -- When RLS disabled, other users get ERROR.
+ SET SESSION AUTHORIZATION regress_rls_dave;
+ SET row_security TO OFF;
+ SELECT * FROM part_document ORDER by did;
+ ERROR:  query would be affected by row-level security policy for table "part_document"
+ SELECT * FROM part_document_satire ORDER by did;
+ ERROR:  query would be affected by row-level security policy for table "part_document_satire"
+ -- Check behavior with a policy that uses a SubPlan not an InitPlan.
+ SET SESSION AUTHORIZATION regress_rls_alice;
+ SET row_security TO ON;
+ CREATE POLICY pp3 ON part_document AS RESTRICTIVE
+     USING ((SELECT dlevel <= seclv FROM uaccount WHERE pguser = current_user));
+ SET SESSION AUTHORIZATION regress_rls_carol;
+ INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_carol', 'testing pp3'); -- fail
+ ERROR:  new row violates row-level security policy "pp3" for table "part_document"
  ----- Dependencies -----
  SET SESSION AUTHORIZATION regress_rls_alice;
  SET row_security TO ON;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge