LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - ruleutils.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 89.0 % 4825 4293 16 168 294 54 180 2401 207 1505 293 2539 5 81
Current Date: 2023-04-08 17:13:01 Functions: 98.7 % 154 152 2 141 9 2 2 149
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 91.0 % 188 171 16 1 11 143 17 22
Legend: Lines: hit not hit (120,180] days: 98.2 % 57 56 1 2 50 4 1 4
(180,240] days: 100.0 % 13 13 10 3 1
(240..) days: 88.7 % 4567 4053 168 292 54 180 2388 4 1481 285 2433
Function coverage date bins:
[..60] days: 100.0 % 8 8 1 7
(120,180] days: 100.0 % 1 1 1
(180,240] days: 100.0 % 3 3 3
(240..) days: 48.8 % 287 140 2 137 1 2 2 143

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * ruleutils.c
                                  4                 :  *    Functions to convert stored expressions/querytrees back to
                                  5                 :  *    source text
                                  6                 :  *
                                  7                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  8                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :  *
                                 10                 :  *
                                 11                 :  * IDENTIFICATION
                                 12                 :  *    src/backend/utils/adt/ruleutils.c
                                 13                 :  *
                                 14                 :  *-------------------------------------------------------------------------
                                 15                 :  */
                                 16                 : #include "postgres.h"
                                 17                 : 
                                 18                 : #include <ctype.h>
                                 19                 : #include <unistd.h>
                                 20                 : #include <fcntl.h>
                                 21                 : 
                                 22                 : #include "access/amapi.h"
                                 23                 : #include "access/htup_details.h"
                                 24                 : #include "access/relation.h"
                                 25                 : #include "access/sysattr.h"
                                 26                 : #include "access/table.h"
                                 27                 : #include "catalog/pg_aggregate.h"
                                 28                 : #include "catalog/pg_am.h"
                                 29                 : #include "catalog/pg_authid.h"
                                 30                 : #include "catalog/pg_collation.h"
                                 31                 : #include "catalog/pg_constraint.h"
                                 32                 : #include "catalog/pg_depend.h"
                                 33                 : #include "catalog/pg_language.h"
                                 34                 : #include "catalog/pg_opclass.h"
                                 35                 : #include "catalog/pg_operator.h"
                                 36                 : #include "catalog/pg_partitioned_table.h"
                                 37                 : #include "catalog/pg_proc.h"
                                 38                 : #include "catalog/pg_statistic_ext.h"
                                 39                 : #include "catalog/pg_trigger.h"
                                 40                 : #include "catalog/pg_type.h"
                                 41                 : #include "commands/defrem.h"
                                 42                 : #include "commands/tablespace.h"
                                 43                 : #include "common/keywords.h"
                                 44                 : #include "executor/spi.h"
                                 45                 : #include "funcapi.h"
                                 46                 : #include "mb/pg_wchar.h"
                                 47                 : #include "miscadmin.h"
                                 48                 : #include "nodes/makefuncs.h"
                                 49                 : #include "nodes/nodeFuncs.h"
                                 50                 : #include "nodes/pathnodes.h"
                                 51                 : #include "optimizer/optimizer.h"
                                 52                 : #include "parser/parse_agg.h"
                                 53                 : #include "parser/parse_func.h"
                                 54                 : #include "parser/parse_node.h"
                                 55                 : #include "parser/parse_oper.h"
                                 56                 : #include "parser/parse_relation.h"
                                 57                 : #include "parser/parser.h"
                                 58                 : #include "parser/parsetree.h"
                                 59                 : #include "rewrite/rewriteHandler.h"
                                 60                 : #include "rewrite/rewriteManip.h"
                                 61                 : #include "rewrite/rewriteSupport.h"
                                 62                 : #include "utils/array.h"
                                 63                 : #include "utils/builtins.h"
                                 64                 : #include "utils/fmgroids.h"
                                 65                 : #include "utils/guc.h"
                                 66                 : #include "utils/hsearch.h"
                                 67                 : #include "utils/lsyscache.h"
                                 68                 : #include "utils/partcache.h"
                                 69                 : #include "utils/rel.h"
                                 70                 : #include "utils/ruleutils.h"
                                 71                 : #include "utils/snapmgr.h"
                                 72                 : #include "utils/syscache.h"
                                 73                 : #include "utils/typcache.h"
                                 74                 : #include "utils/varlena.h"
                                 75                 : #include "utils/xml.h"
                                 76                 : 
                                 77                 : /* ----------
                                 78                 :  * Pretty formatting constants
                                 79                 :  * ----------
                                 80                 :  */
                                 81                 : 
                                 82                 : /* Indent counts */
                                 83                 : #define PRETTYINDENT_STD        8
                                 84                 : #define PRETTYINDENT_JOIN       4
                                 85                 : #define PRETTYINDENT_VAR        4
                                 86                 : 
                                 87                 : #define PRETTYINDENT_LIMIT      40  /* wrap limit */
                                 88                 : 
                                 89                 : /* Pretty flags */
                                 90                 : #define PRETTYFLAG_PAREN        0x0001
                                 91                 : #define PRETTYFLAG_INDENT       0x0002
                                 92                 : #define PRETTYFLAG_SCHEMA       0x0004
                                 93                 : 
                                 94                 : /* Standard conversion of a "bool pretty" option to detailed flags */
                                 95                 : #define GET_PRETTY_FLAGS(pretty) \
                                 96                 :     ((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
                                 97                 :      : PRETTYFLAG_INDENT)
                                 98                 : 
                                 99                 : /* Default line length for pretty-print wrapping: 0 means wrap always */
                                100                 : #define WRAP_COLUMN_DEFAULT     0
                                101                 : 
                                102                 : /* macros to test if pretty action needed */
                                103                 : #define PRETTY_PAREN(context)   ((context)->prettyFlags & PRETTYFLAG_PAREN)
                                104                 : #define PRETTY_INDENT(context)  ((context)->prettyFlags & PRETTYFLAG_INDENT)
                                105                 : #define PRETTY_SCHEMA(context)  ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
                                106                 : 
                                107                 : 
                                108                 : /* ----------
                                109                 :  * Local data types
                                110                 :  * ----------
                                111                 :  */
                                112                 : 
                                113                 : /* Context info needed for invoking a recursive querytree display routine */
                                114                 : typedef struct
                                115                 : {
                                116                 :     StringInfo  buf;            /* output buffer to append to */
                                117                 :     List       *namespaces;     /* List of deparse_namespace nodes */
                                118                 :     List       *windowClause;   /* Current query level's WINDOW clause */
                                119                 :     List       *windowTList;    /* targetlist for resolving WINDOW clause */
                                120                 :     int         prettyFlags;    /* enabling of pretty-print functions */
                                121                 :     int         wrapColumn;     /* max line length, or -1 for no limit */
                                122                 :     int         indentLevel;    /* current indent level for pretty-print */
                                123                 :     bool        varprefix;      /* true to print prefixes on Vars */
                                124                 :     ParseExprKind special_exprkind; /* set only for exprkinds needing special
                                125                 :                                      * handling */
                                126                 :     Bitmapset  *appendparents;  /* if not null, map child Vars of these relids
                                127                 :                                  * back to the parent rel */
                                128                 : } deparse_context;
                                129                 : 
                                130                 : /*
                                131                 :  * Each level of query context around a subtree needs a level of Var namespace.
                                132                 :  * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
                                133                 :  * the current context's namespaces list.
                                134                 :  *
                                135                 :  * rtable is the list of actual RTEs from the Query or PlannedStmt.
                                136                 :  * rtable_names holds the alias name to be used for each RTE (either a C
                                137                 :  * string, or NULL for nameless RTEs such as unnamed joins).
                                138                 :  * rtable_columns holds the column alias names to be used for each RTE.
                                139                 :  *
                                140                 :  * subplans is a list of Plan trees for SubPlans and CTEs (it's only used
                                141                 :  * in the PlannedStmt case).
                                142                 :  * ctes is a list of CommonTableExpr nodes (only used in the Query case).
                                143                 :  * appendrels, if not null (it's only used in the PlannedStmt case), is an
                                144                 :  * array of AppendRelInfo nodes, indexed by child relid.  We use that to map
                                145                 :  * child-table Vars to their inheritance parents.
                                146                 :  *
                                147                 :  * In some cases we need to make names of merged JOIN USING columns unique
                                148                 :  * across the whole query, not only per-RTE.  If so, unique_using is true
                                149                 :  * and using_names is a list of C strings representing names already assigned
                                150                 :  * to USING columns.
                                151                 :  *
                                152                 :  * When deparsing plan trees, there is always just a single item in the
                                153                 :  * deparse_namespace list (since a plan tree never contains Vars with
                                154                 :  * varlevelsup > 0).  We store the Plan node that is the immediate
                                155                 :  * parent of the expression to be deparsed, as well as a list of that
                                156                 :  * Plan's ancestors.  In addition, we store its outer and inner subplan nodes,
                                157                 :  * as well as their targetlists, and the index tlist if the current plan node
                                158                 :  * might contain INDEX_VAR Vars.  (These fields could be derived on-the-fly
                                159                 :  * from the current Plan node, but it seems notationally clearer to set them
                                160                 :  * up as separate fields.)
                                161                 :  */
                                162                 : typedef struct
                                163                 : {
                                164                 :     List       *rtable;         /* List of RangeTblEntry nodes */
                                165                 :     List       *rtable_names;   /* Parallel list of names for RTEs */
                                166                 :     List       *rtable_columns; /* Parallel list of deparse_columns structs */
                                167                 :     List       *subplans;       /* List of Plan trees for SubPlans */
                                168                 :     List       *ctes;           /* List of CommonTableExpr nodes */
                                169                 :     AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
                                170                 :     /* Workspace for column alias assignment: */
                                171                 :     bool        unique_using;   /* Are we making USING names globally unique */
                                172                 :     List       *using_names;    /* List of assigned names for USING columns */
                                173                 :     /* Remaining fields are used only when deparsing a Plan tree: */
                                174                 :     Plan       *plan;           /* immediate parent of current expression */
                                175                 :     List       *ancestors;      /* ancestors of plan */
                                176                 :     Plan       *outer_plan;     /* outer subnode, or NULL if none */
                                177                 :     Plan       *inner_plan;     /* inner subnode, or NULL if none */
                                178                 :     List       *outer_tlist;    /* referent for OUTER_VAR Vars */
                                179                 :     List       *inner_tlist;    /* referent for INNER_VAR Vars */
                                180                 :     List       *index_tlist;    /* referent for INDEX_VAR Vars */
                                181                 :     /* Special namespace representing a function signature: */
                                182                 :     char       *funcname;
                                183                 :     int         numargs;
                                184                 :     char      **argnames;
                                185                 : } deparse_namespace;
                                186                 : 
                                187                 : /*
                                188                 :  * Per-relation data about column alias names.
                                189                 :  *
                                190                 :  * Selecting aliases is unreasonably complicated because of the need to dump
                                191                 :  * rules/views whose underlying tables may have had columns added, deleted, or
                                192                 :  * renamed since the query was parsed.  We must nonetheless print the rule/view
                                193                 :  * in a form that can be reloaded and will produce the same results as before.
                                194                 :  *
                                195                 :  * For each RTE used in the query, we must assign column aliases that are
                                196                 :  * unique within that RTE.  SQL does not require this of the original query,
                                197                 :  * but due to factors such as *-expansion we need to be able to uniquely
                                198                 :  * reference every column in a decompiled query.  As long as we qualify all
                                199                 :  * column references, per-RTE uniqueness is sufficient for that.
                                200                 :  *
                                201                 :  * However, we can't ensure per-column name uniqueness for unnamed join RTEs,
                                202                 :  * since they just inherit column names from their input RTEs, and we can't
                                203                 :  * rename the columns at the join level.  Most of the time this isn't an issue
                                204                 :  * because we don't need to reference the join's output columns as such; we
                                205                 :  * can reference the input columns instead.  That approach can fail for merged
                                206                 :  * JOIN USING columns, however, so when we have one of those in an unnamed
                                207                 :  * join, we have to make that column's alias globally unique across the whole
                                208                 :  * query to ensure it can be referenced unambiguously.
                                209                 :  *
                                210                 :  * Another problem is that a JOIN USING clause requires the columns to be
                                211                 :  * merged to have the same aliases in both input RTEs, and that no other
                                212                 :  * columns in those RTEs or their children conflict with the USING names.
                                213                 :  * To handle that, we do USING-column alias assignment in a recursive
                                214                 :  * traversal of the query's jointree.  When descending through a JOIN with
                                215                 :  * USING, we preassign the USING column names to the child columns, overriding
                                216                 :  * other rules for column alias assignment.  We also mark each RTE with a list
                                217                 :  * of all USING column names selected for joins containing that RTE, so that
                                218                 :  * when we assign other columns' aliases later, we can avoid conflicts.
                                219                 :  *
                                220                 :  * Another problem is that if a JOIN's input tables have had columns added or
                                221                 :  * deleted since the query was parsed, we must generate a column alias list
                                222                 :  * for the join that matches the current set of input columns --- otherwise, a
                                223                 :  * change in the number of columns in the left input would throw off matching
                                224                 :  * of aliases to columns of the right input.  Thus, positions in the printable
                                225                 :  * column alias list are not necessarily one-for-one with varattnos of the
                                226                 :  * JOIN, so we need a separate new_colnames[] array for printing purposes.
                                227                 :  */
                                228                 : typedef struct
                                229                 : {
                                230                 :     /*
                                231                 :      * colnames is an array containing column aliases to use for columns that
                                232                 :      * existed when the query was parsed.  Dropped columns have NULL entries.
                                233                 :      * This array can be directly indexed by varattno to get a Var's name.
                                234                 :      *
                                235                 :      * Non-NULL entries are guaranteed unique within the RTE, *except* when
                                236                 :      * this is for an unnamed JOIN RTE.  In that case we merely copy up names
                                237                 :      * from the two input RTEs.
                                238                 :      *
                                239                 :      * During the recursive descent in set_using_names(), forcible assignment
                                240                 :      * of a child RTE's column name is represented by pre-setting that element
                                241                 :      * of the child's colnames array.  So at that stage, NULL entries in this
                                242                 :      * array just mean that no name has been preassigned, not necessarily that
                                243                 :      * the column is dropped.
                                244                 :      */
                                245                 :     int         num_cols;       /* length of colnames[] array */
                                246                 :     char      **colnames;       /* array of C strings and NULLs */
                                247                 : 
                                248                 :     /*
                                249                 :      * new_colnames is an array containing column aliases to use for columns
                                250                 :      * that would exist if the query was re-parsed against the current
                                251                 :      * definitions of its base tables.  This is what to print as the column
                                252                 :      * alias list for the RTE.  This array does not include dropped columns,
                                253                 :      * but it will include columns added since original parsing.  Indexes in
                                254                 :      * it therefore have little to do with current varattno values.  As above,
                                255                 :      * entries are unique unless this is for an unnamed JOIN RTE.  (In such an
                                256                 :      * RTE, we never actually print this array, but we must compute it anyway
                                257                 :      * for possible use in computing column names of upper joins.) The
                                258                 :      * parallel array is_new_col marks which of these columns are new since
                                259                 :      * original parsing.  Entries with is_new_col false must match the
                                260                 :      * non-NULL colnames entries one-for-one.
                                261                 :      */
                                262                 :     int         num_new_cols;   /* length of new_colnames[] array */
                                263                 :     char      **new_colnames;   /* array of C strings */
                                264                 :     bool       *is_new_col;     /* array of bool flags */
                                265                 : 
                                266                 :     /* This flag tells whether we should actually print a column alias list */
                                267                 :     bool        printaliases;
                                268                 : 
                                269                 :     /* This list has all names used as USING names in joins above this RTE */
                                270                 :     List       *parentUsing;    /* names assigned to parent merged columns */
                                271                 : 
                                272                 :     /*
                                273                 :      * If this struct is for a JOIN RTE, we fill these fields during the
                                274                 :      * set_using_names() pass to describe its relationship to its child RTEs.
                                275                 :      *
                                276                 :      * leftattnos and rightattnos are arrays with one entry per existing
                                277                 :      * output column of the join (hence, indexable by join varattno).  For a
                                278                 :      * simple reference to a column of the left child, leftattnos[i] is the
                                279                 :      * child RTE's attno and rightattnos[i] is zero; and conversely for a
                                280                 :      * column of the right child.  But for merged columns produced by JOIN
                                281                 :      * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
                                282                 :      * Note that a simple reference might be to a child RTE column that's been
                                283                 :      * dropped; but that's OK since the column could not be used in the query.
                                284                 :      *
                                285                 :      * If it's a JOIN USING, usingNames holds the alias names selected for the
                                286                 :      * merged columns (these might be different from the original USING list,
                                287                 :      * if we had to modify names to achieve uniqueness).
                                288                 :      */
                                289                 :     int         leftrti;        /* rangetable index of left child */
                                290                 :     int         rightrti;       /* rangetable index of right child */
                                291                 :     int        *leftattnos;     /* left-child varattnos of join cols, or 0 */
                                292                 :     int        *rightattnos;    /* right-child varattnos of join cols, or 0 */
                                293                 :     List       *usingNames;     /* names assigned to merged columns */
                                294                 : } deparse_columns;
                                295                 : 
                                296                 : /* This macro is analogous to rt_fetch(), but for deparse_columns structs */
                                297                 : #define deparse_columns_fetch(rangetable_index, dpns) \
                                298                 :     ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
                                299                 : 
                                300                 : /*
                                301                 :  * Entry in set_rtable_names' hash table
                                302                 :  */
                                303                 : typedef struct
                                304                 : {
                                305                 :     char        name[NAMEDATALEN];  /* Hash key --- must be first */
                                306                 :     int         counter;        /* Largest addition used so far for name */
                                307                 : } NameHashEntry;
                                308                 : 
                                309                 : /* Callback signature for resolve_special_varno() */
                                310                 : typedef void (*rsv_callback) (Node *node, deparse_context *context,
                                311                 :                               void *callback_arg);
                                312                 : 
                                313                 : 
                                314                 : /* ----------
                                315                 :  * Global data
                                316                 :  * ----------
                                317                 :  */
                                318                 : static SPIPlanPtr plan_getrulebyoid = NULL;
                                319                 : static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
                                320                 : static SPIPlanPtr plan_getviewrule = NULL;
                                321                 : static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
                                322                 : 
                                323                 : /* GUC parameters */
                                324                 : bool        quote_all_identifiers = false;
                                325                 : 
                                326                 : 
                                327                 : /* ----------
                                328                 :  * Local functions
                                329                 :  *
                                330                 :  * Most of these functions used to use fixed-size buffers to build their
                                331                 :  * results.  Now, they take an (already initialized) StringInfo object
                                332                 :  * as a parameter, and append their text output to its contents.
                                333                 :  * ----------
                                334                 :  */
                                335                 : static char *deparse_expression_pretty(Node *expr, List *dpcontext,
                                336                 :                                        bool forceprefix, bool showimplicit,
                                337                 :                                        int prettyFlags, int startIndent);
                                338                 : static char *pg_get_viewdef_worker(Oid viewoid,
                                339                 :                                    int prettyFlags, int wrapColumn);
                                340                 : static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
                                341                 : static int  decompile_column_index_array(Datum column_index_array, Oid relId,
                                342                 :                                          StringInfo buf);
                                343                 : static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
                                344                 : static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
                                345                 :                                     const Oid *excludeOps,
                                346                 :                                     bool attrsOnly, bool keysOnly,
                                347                 :                                     bool showTblSpc, bool inherits,
                                348                 :                                     int prettyFlags, bool missing_ok);
                                349                 : static char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
                                350                 :                                          bool missing_ok);
                                351                 : static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
                                352                 :                                       bool attrsOnly, bool missing_ok);
                                353                 : static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                                354                 :                                          int prettyFlags, bool missing_ok);
                                355                 : static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
                                356                 :                                 int prettyFlags);
                                357                 : static int  print_function_arguments(StringInfo buf, HeapTuple proctup,
                                358                 :                                      bool print_table_args, bool print_defaults);
                                359                 : static void print_function_rettype(StringInfo buf, HeapTuple proctup);
                                360                 : static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
                                361                 : static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
                                362                 : static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
                                363                 :                              Bitmapset *rels_used);
                                364                 : static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
                                365                 :                                   List *parent_namespaces);
                                366                 : static void set_simple_column_names(deparse_namespace *dpns);
                                367                 : static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode);
                                368                 : static void set_using_names(deparse_namespace *dpns, Node *jtnode,
                                369                 :                             List *parentUsing);
                                370                 : static void set_relation_column_names(deparse_namespace *dpns,
                                371                 :                                       RangeTblEntry *rte,
                                372                 :                                       deparse_columns *colinfo);
                                373                 : static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
                                374                 :                                   deparse_columns *colinfo);
                                375                 : static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
                                376                 :                               deparse_columns *colinfo);
                                377                 : static char *make_colname_unique(char *colname, deparse_namespace *dpns,
                                378                 :                                  deparse_columns *colinfo);
                                379                 : static void expand_colnames_array_to(deparse_columns *colinfo, int n);
                                380                 : static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
                                381                 :                                   deparse_columns *colinfo);
                                382                 : static char *get_rtable_name(int rtindex, deparse_context *context);
                                383                 : static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
                                384                 : static Plan *find_recursive_union(deparse_namespace *dpns,
                                385                 :                                   WorkTableScan *wtscan);
                                386                 : static void push_child_plan(deparse_namespace *dpns, Plan *plan,
                                387                 :                             deparse_namespace *save_dpns);
                                388                 : static void pop_child_plan(deparse_namespace *dpns,
                                389                 :                            deparse_namespace *save_dpns);
                                390                 : static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
                                391                 :                                deparse_namespace *save_dpns);
                                392                 : static void pop_ancestor_plan(deparse_namespace *dpns,
                                393                 :                               deparse_namespace *save_dpns);
                                394                 : static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
                                395                 :                          int prettyFlags);
                                396                 : static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
                                397                 :                          int prettyFlags, int wrapColumn);
                                398                 : static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
                                399                 :                           TupleDesc resultDesc, bool colNamesVisible,
                                400                 :                           int prettyFlags, int wrapColumn, int startIndent);
                                401                 : static void get_values_def(List *values_lists, deparse_context *context);
                                402                 : static void get_with_clause(Query *query, deparse_context *context);
                                403                 : static void get_select_query_def(Query *query, deparse_context *context,
                                404                 :                                  TupleDesc resultDesc, bool colNamesVisible);
                                405                 : static void get_insert_query_def(Query *query, deparse_context *context,
                                406                 :                                  bool colNamesVisible);
                                407                 : static void get_update_query_def(Query *query, deparse_context *context,
                                408                 :                                  bool colNamesVisible);
                                409                 : static void get_update_query_targetlist_def(Query *query, List *targetList,
                                410                 :                                             deparse_context *context,
                                411                 :                                             RangeTblEntry *rte);
                                412                 : static void get_delete_query_def(Query *query, deparse_context *context,
                                413                 :                                  bool colNamesVisible);
                                414                 : static void get_utility_query_def(Query *query, deparse_context *context);
                                415                 : static void get_basic_select_query(Query *query, deparse_context *context,
                                416                 :                                    TupleDesc resultDesc, bool colNamesVisible);
                                417                 : static void get_target_list(List *targetList, deparse_context *context,
                                418                 :                             TupleDesc resultDesc, bool colNamesVisible);
                                419                 : static void get_setop_query(Node *setOp, Query *query,
                                420                 :                             deparse_context *context,
                                421                 :                             TupleDesc resultDesc, bool colNamesVisible);
                                422                 : static Node *get_rule_sortgroupclause(Index ref, List *tlist,
                                423                 :                                       bool force_colno,
                                424                 :                                       deparse_context *context);
                                425                 : static void get_rule_groupingset(GroupingSet *gset, List *targetlist,
                                426                 :                                  bool omit_parens, deparse_context *context);
                                427                 : static void get_rule_orderby(List *orderList, List *targetList,
                                428                 :                              bool force_colno, deparse_context *context);
                                429                 : static void get_rule_windowclause(Query *query, deparse_context *context);
                                430                 : static void get_rule_windowspec(WindowClause *wc, List *targetList,
                                431                 :                                 deparse_context *context);
                                432                 : static char *get_variable(Var *var, int levelsup, bool istoplevel,
                                433                 :                           deparse_context *context);
                                434                 : static void get_special_variable(Node *node, deparse_context *context,
                                435                 :                                  void *callback_arg);
                                436                 : static void resolve_special_varno(Node *node, deparse_context *context,
                                437                 :                                   rsv_callback callback, void *callback_arg);
                                438                 : static Node *find_param_referent(Param *param, deparse_context *context,
                                439                 :                                  deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
                                440                 : static void get_parameter(Param *param, deparse_context *context);
                                441                 : static const char *get_simple_binary_op_name(OpExpr *expr);
                                442                 : static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
                                443                 : static void appendContextKeyword(deparse_context *context, const char *str,
                                444                 :                                  int indentBefore, int indentAfter, int indentPlus);
                                445                 : static void removeStringInfoSpaces(StringInfo str);
                                446                 : static void get_rule_expr(Node *node, deparse_context *context,
                                447                 :                           bool showimplicit);
                                448                 : static void get_rule_expr_toplevel(Node *node, deparse_context *context,
                                449                 :                                    bool showimplicit);
                                450                 : static void get_rule_list_toplevel(List *lst, deparse_context *context,
                                451                 :                                    bool showimplicit);
                                452                 : static void get_rule_expr_funccall(Node *node, deparse_context *context,
                                453                 :                                    bool showimplicit);
                                454                 : static bool looks_like_function(Node *node);
                                455                 : static void get_oper_expr(OpExpr *expr, deparse_context *context);
                                456                 : static void get_func_expr(FuncExpr *expr, deparse_context *context,
                                457                 :                           bool showimplicit);
                                458                 : static void get_agg_expr(Aggref *aggref, deparse_context *context,
                                459                 :                          Aggref *original_aggref);
                                460                 : static void get_agg_expr_helper(Aggref *aggref, deparse_context *context,
                                461                 :                                 Aggref *original_aggref, const char *funcname,
                                462                 :                                 const char *options, bool is_json_objectagg);
                                463                 : static void get_agg_combine_expr(Node *node, deparse_context *context,
                                464                 :                                  void *callback_arg);
                                465                 : static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
                                466                 : static void get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
                                467                 :                                        const char *funcname, const char *options,
                                468                 :                                        bool is_json_objectagg);
                                469                 : static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context);
                                470                 : static void get_coercion_expr(Node *arg, deparse_context *context,
                                471                 :                               Oid resulttype, int32 resulttypmod,
                                472                 :                               Node *parentNode);
                                473                 : static void get_const_expr(Const *constval, deparse_context *context,
                                474                 :                            int showtype);
                                475                 : static void get_const_collation(Const *constval, deparse_context *context);
                                476                 : static void get_json_format(JsonFormat *format, StringInfo buf);
                                477                 : static void get_json_constructor(JsonConstructorExpr *ctor,
                                478                 :                                  deparse_context *context, bool showimplicit);
                                479                 : static void get_json_constructor_options(JsonConstructorExpr *ctor,
                                480                 :                                          StringInfo buf);
                                481                 : static void get_json_agg_constructor(JsonConstructorExpr *ctor,
                                482                 :                                      deparse_context *context,
                                483                 :                                      const char *funcname,
                                484                 :                                      bool is_json_objectagg);
                                485                 : static void simple_quote_literal(StringInfo buf, const char *val);
                                486                 : static void get_sublink_expr(SubLink *sublink, deparse_context *context);
                                487                 : static void get_tablefunc(TableFunc *tf, deparse_context *context,
                                488                 :                           bool showimplicit);
                                489                 : static void get_from_clause(Query *query, const char *prefix,
                                490                 :                             deparse_context *context);
                                491                 : static void get_from_clause_item(Node *jtnode, Query *query,
                                492                 :                                  deparse_context *context);
                                493                 : static void get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
                                494                 :                           deparse_context *context);
                                495                 : static void get_column_alias_list(deparse_columns *colinfo,
                                496                 :                                   deparse_context *context);
                                497                 : static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
                                498                 :                                        deparse_columns *colinfo,
                                499                 :                                        deparse_context *context);
                                500                 : static void get_tablesample_def(TableSampleClause *tablesample,
                                501                 :                                 deparse_context *context);
                                502                 : static void get_opclass_name(Oid opclass, Oid actual_datatype,
                                503                 :                              StringInfo buf);
                                504                 : static Node *processIndirection(Node *node, deparse_context *context);
                                505                 : static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
                                506                 : static char *get_relation_name(Oid relid);
                                507                 : static char *generate_relation_name(Oid relid, List *namespaces);
                                508                 : static char *generate_qualified_relation_name(Oid relid);
                                509                 : static char *generate_function_name(Oid funcid, int nargs,
                                510                 :                                     List *argnames, Oid *argtypes,
                                511                 :                                     bool has_variadic, bool *use_variadic_p,
                                512                 :                                     ParseExprKind special_exprkind);
                                513                 : static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
                                514                 : static void add_cast_to(StringInfo buf, Oid typid);
                                515                 : static char *generate_qualified_type_name(Oid typid);
                                516                 : static text *string_to_text(char *str);
                                517                 : static char *flatten_reloptions(Oid relid);
                                518                 : static void get_reloptions(StringInfo buf, Datum reloptions);
                                519                 : 
                                520                 : #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
                                521                 : 
                                522                 : 
                                523                 : /* ----------
                                524                 :  * pg_get_ruledef       - Do it all and return a text
                                525                 :  *                that could be used as a statement
                                526                 :  *                to recreate the rule
                                527                 :  * ----------
                                528                 :  */
                                529                 : Datum
 8312 tgl                       530 GIC         219 : pg_get_ruledef(PG_FUNCTION_ARGS)
                                531                 : {
 7661                           532             219 :     Oid         ruleoid = PG_GETARG_OID(0);
                                533                 :     int         prettyFlags;
                                534                 :     char       *res;
                                535                 : 
 3717                           536             219 :     prettyFlags = PRETTYFLAG_INDENT;
                                537                 : 
 2448 rhaas                     538             219 :     res = pg_get_ruledef_worker(ruleoid, prettyFlags);
                                539                 : 
                                540             219 :     if (res == NULL)
                                541               3 :         PG_RETURN_NULL();
                                542                 : 
                                543             216 :     PG_RETURN_TEXT_P(string_to_text(res));
                                544                 : }
 7193 tgl                       545 ECB             : 
                                546                 : 
                                547                 : Datum
 7193 tgl                       548 GIC          48 : pg_get_ruledef_ext(PG_FUNCTION_ARGS)
                                549                 : {
                                550              48 :     Oid         ruleoid = PG_GETARG_OID(0);
 7193 tgl                       551 CBC          48 :     bool        pretty = PG_GETARG_BOOL(1);
                                552                 :     int         prettyFlags;
 2448 rhaas                     553 ECB             :     char       *res;
                                554                 : 
  377 tgl                       555 CBC          48 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
 2448 rhaas                     556 ECB             : 
 2448 rhaas                     557 GIC          48 :     res = pg_get_ruledef_worker(ruleoid, prettyFlags);
 2448 rhaas                     558 ECB             : 
 2448 rhaas                     559 GIC          48 :     if (res == NULL)
 2448 rhaas                     560 UIC           0 :         PG_RETURN_NULL();
                                561                 : 
 2448 rhaas                     562 GIC          48 :     PG_RETURN_TEXT_P(string_to_text(res));
 7193 tgl                       563 ECB             : }
                                564                 : 
                                565                 : 
 6913                           566                 : static char *
 7193 tgl                       567 GIC         267 : pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
                                568                 : {
                                569                 :     Datum       args[1];
 7661 tgl                       570 ECB             :     char        nulls[1];
                                571                 :     int         spirc;
 8986 bruce                     572                 :     HeapTuple   ruletup;
                                573                 :     TupleDesc   rulettc;
 8397                           574                 :     StringInfoData buf;
 6913 tgl                       575 EUB             : 
                                576                 :     /*
 6913 tgl                       577 ECB             :      * Do this first so that string is alloc'd in outer context not SPI's.
                                578                 :      */
 6913 tgl                       579 GIC         267 :     initStringInfo(&buf);
                                580                 : 
                                581                 :     /*
 8986 bruce                     582 ECB             :      * Connect to SPI manager
                                583                 :      */
 8986 bruce                     584 GIC         267 :     if (SPI_connect() != SPI_OK_CONNECT)
 7196 tgl                       585 UIC           0 :         elog(ERROR, "SPI_connect failed");
                                586                 : 
                                587                 :     /*
                                588                 :      * On the first call prepare the plan to lookup pg_rewrite. We read
                                589                 :      * pg_rewrite over the SPI manager instead of using the syscache to be
                                590                 :      * checked for read access on pg_rewrite.
                                591                 :      */
 7661 tgl                       592 GIC         267 :     if (plan_getrulebyoid == NULL)
                                593                 :     {
 8986 bruce                     594 ECB             :         Oid         argtypes[1];
                                595                 :         SPIPlanPtr  plan;
                                596                 : 
 7661 tgl                       597 GIC          17 :         argtypes[0] = OIDOID;
                                598              17 :         plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
 8986 bruce                     599 CBC          17 :         if (plan == NULL)
 7196 tgl                       600 UBC           0 :             elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
 4223 tgl                       601 GIC          17 :         SPI_keepplan(plan);
                                602              17 :         plan_getrulebyoid = plan;
                                603                 :     }
                                604                 : 
                                605                 :     /*
                                606                 :      * Get the pg_rewrite tuple for this rule
 8986 bruce                     607 ECB             :      */
 7661 tgl                       608 GIC         267 :     args[0] = ObjectIdGetDatum(ruleoid);
                                609             267 :     nulls[0] = ' ';
 3424 peter_e                   610             267 :     spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0);
 8986 bruce                     611             267 :     if (spirc != SPI_OK_SELECT)
 7196 tgl                       612 LBC           0 :         elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
 8986 bruce                     613 CBC         267 :     if (SPI_processed != 1)
 2448 rhaas                     614 ECB             :     {
 2448 rhaas                     615 EUB             :         /*
 2448 rhaas                     616 ECB             :          * There is no tuple data available here, just keep the output buffer
                                617                 :          * empty.
                                618                 :          */
                                619                 :     }
                                620                 :     else
                                621                 :     {
                                622                 :         /*
 6123 neilc                     623                 :          * Get the rule's definition and put it into executor's memory
 6913 tgl                       624                 :          */
 6913 tgl                       625 CBC         264 :         ruletup = SPI_tuptable->vals[0];
                                626             264 :         rulettc = SPI_tuptable->tupdesc;
 6913 tgl                       627 GBC         264 :         make_ruledef(&buf, ruletup, rulettc, prettyFlags);
 8986 bruce                     628 ECB             :     }
                                629                 : 
                                630                 :     /*
                                631                 :      * Disconnect from SPI manager
                                632                 :      */
 8986 bruce                     633 GIC         267 :     if (SPI_finish() != SPI_OK_FINISH)
 7196 tgl                       634 UIC           0 :         elog(ERROR, "SPI_finish failed");
                                635                 : 
 2448 rhaas                     636 GIC         267 :     if (buf.len == 0)
                                637               3 :         return NULL;
                                638                 : 
 6913 tgl                       639             264 :     return buf.data;
 8994 bruce                     640 ECB             : }
                                641                 : 
                                642                 : 
                                643                 : /* ----------
                                644                 :  * pg_get_viewdef       - Mainly the same thing, but we
                                645                 :  *                only return the SELECT part of a view
                                646                 :  * ----------
                                647                 :  */
 8312 tgl                       648                 : Datum
 8312 tgl                       649 GBC         947 : pg_get_viewdef(PG_FUNCTION_ARGS)
                                650                 : {
 7661 tgl                       651 ECB             :     /* By OID */
 7661 tgl                       652 CBC         947 :     Oid         viewoid = PG_GETARG_OID(0);
                                653                 :     int         prettyFlags;
 2448 rhaas                     654 ECB             :     char       *res;
                                655                 : 
 3717 tgl                       656 GIC         947 :     prettyFlags = PRETTYFLAG_INDENT;
                                657                 : 
 2448 rhaas                     658             947 :     res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
                                659                 : 
                                660             947 :     if (res == NULL)
                                661               3 :         PG_RETURN_NULL();
                                662                 : 
                                663             944 :     PG_RETURN_TEXT_P(string_to_text(res));
 7193 tgl                       664 ECB             : }
                                665                 : 
                                666                 : 
                                667                 : Datum
 7193 tgl                       668 GIC         233 : pg_get_viewdef_ext(PG_FUNCTION_ARGS)
                                669                 : {
                                670                 :     /* By OID */
 7193 tgl                       671 CBC         233 :     Oid         viewoid = PG_GETARG_OID(0);
 7193 tgl                       672 GIC         233 :     bool        pretty = PG_GETARG_BOOL(1);
 7193 tgl                       673 ECB             :     int         prettyFlags;
                                674                 :     char       *res;
                                675                 : 
  377 tgl                       676 CBC         233 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                                677                 : 
 2448 rhaas                     678             233 :     res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
                                679                 : 
 2448 rhaas                     680 GIC         233 :     if (res == NULL)
 2448 rhaas                     681 UIC           0 :         PG_RETURN_NULL();
                                682                 : 
 2448 rhaas                     683 CBC         233 :     PG_RETURN_TEXT_P(string_to_text(res));
                                684                 : }
                                685                 : 
 4067 andrew                    686 ECB             : Datum
 4067 andrew                    687 CBC           3 : pg_get_viewdef_wrap(PG_FUNCTION_ARGS)
                                688                 : {
                                689                 :     /* By OID */
 4067 andrew                    690 GIC           3 :     Oid         viewoid = PG_GETARG_OID(0);
 3955 bruce                     691 CBC           3 :     int         wrap = PG_GETARG_INT32(1);
                                692                 :     int         prettyFlags;
 2448 rhaas                     693 ECB             :     char       *res;
                                694                 : 
 4067 andrew                    695                 :     /* calling this implies we want pretty printing */
  377 tgl                       696 GBC           3 :     prettyFlags = GET_PRETTY_FLAGS(true);
                                697                 : 
 2448 rhaas                     698 CBC           3 :     res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap);
                                699                 : 
 2448 rhaas                     700 GIC           3 :     if (res == NULL)
 2448 rhaas                     701 UIC           0 :         PG_RETURN_NULL();
 2448 rhaas                     702 ECB             : 
 2448 rhaas                     703 GIC           3 :     PG_RETURN_TEXT_P(string_to_text(res));
                                704                 : }
 4067 andrew                    705 ECB             : 
 7661 tgl                       706                 : Datum
 7661 tgl                       707 GIC          36 : pg_get_viewdef_name(PG_FUNCTION_ARGS)
                                708                 : {
                                709                 :     /* By qualified name */
 2219 noah                      710              36 :     text       *viewname = PG_GETARG_TEXT_PP(0);
 3717 tgl                       711 ECB             :     int         prettyFlags;
                                712                 :     RangeVar   *viewrel;
 7661                           713                 :     Oid         viewoid;
                                714                 :     char       *res;
                                715                 : 
 3717 tgl                       716 GBC          36 :     prettyFlags = PRETTYFLAG_INDENT;
                                717                 : 
 4293 rhaas                     718 ECB             :     /* Look up view name.  Can't lock it - we might not have privileges. */
 6526 neilc                     719 GIC          36 :     viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
 4148 rhaas                     720              36 :     viewoid = RangeVarGetRelid(viewrel, NoLock, false);
                                721                 : 
 2448 rhaas                     722 CBC          36 :     res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
                                723                 : 
 2448 rhaas                     724 GIC          36 :     if (res == NULL)
 2448 rhaas                     725 LBC           0 :         PG_RETURN_NULL();
                                726                 : 
 2448 rhaas                     727 GIC          36 :     PG_RETURN_TEXT_P(string_to_text(res));
                                728                 : }
                                729                 : 
                                730                 : 
 7193 tgl                       731 ECB             : Datum
 7193 tgl                       732 GIC         192 : pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
                                733                 : {
 7193 tgl                       734 ECB             :     /* By qualified name */
 2219 noah                      735 CBC         192 :     text       *viewname = PG_GETARG_TEXT_PP(0);
 7193 tgl                       736 GIC         192 :     bool        pretty = PG_GETARG_BOOL(1);
 7193 tgl                       737 ECB             :     int         prettyFlags;
                                738                 :     RangeVar   *viewrel;
                                739                 :     Oid         viewoid;
 2436 tgl                       740 EUB             :     char       *res;
                                741                 : 
  377 tgl                       742 CBC         192 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                                743                 : 
                                744                 :     /* Look up view name.  Can't lock it - we might not have privileges. */
 6526 neilc                     745 GIC         192 :     viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
 4148 rhaas                     746             192 :     viewoid = RangeVarGetRelid(viewrel, NoLock, false);
 7193 tgl                       747 ECB             : 
 2436 tgl                       748 GIC         192 :     res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT);
                                749                 : 
 2436 tgl                       750 CBC         192 :     if (res == NULL)
 2436 tgl                       751 LBC           0 :         PG_RETURN_NULL();
                                752                 : 
 2436 tgl                       753 GIC         192 :     PG_RETURN_TEXT_P(string_to_text(res));
                                754                 : }
                                755                 : 
                                756                 : /*
 7661 tgl                       757 ECB             :  * Common code for by-OID and by-name variants of pg_get_viewdef
                                758                 :  */
                                759                 : static char *
 3758 tgl                       760 CBC        1411 : pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn)
 7661 tgl                       761 ECB             : {
                                762                 :     Datum       args[2];
                                763                 :     char        nulls[2];
                                764                 :     int         spirc;
 8986 bruce                     765                 :     HeapTuple   ruletup;
 8986 bruce                     766 EUB             :     TupleDesc   rulettc;
                                767                 :     StringInfoData buf;
 6913 tgl                       768 ECB             : 
                                769                 :     /*
                                770                 :      * Do this first so that string is alloc'd in outer context not SPI's.
                                771                 :      */
 6913 tgl                       772 GIC        1411 :     initStringInfo(&buf);
                                773                 : 
                                774                 :     /*
 8986 bruce                     775 ECB             :      * Connect to SPI manager
                                776                 :      */
 8986 bruce                     777 GIC        1411 :     if (SPI_connect() != SPI_OK_CONNECT)
 7196 tgl                       778 UIC           0 :         elog(ERROR, "SPI_connect failed");
                                779                 : 
                                780                 :     /*
                                781                 :      * On the first call prepare the plan to lookup pg_rewrite. We read
                                782                 :      * pg_rewrite over the SPI manager instead of using the syscache to be
                                783                 :      * checked for read access on pg_rewrite.
                                784                 :      */
 7661 tgl                       785 GIC        1411 :     if (plan_getviewrule == NULL)
                                786                 :     {
 7661 tgl                       787 ECB             :         Oid         argtypes[2];
                                788                 :         SPIPlanPtr  plan;
                                789                 : 
 7661 tgl                       790 GIC         108 :         argtypes[0] = OIDOID;
                                791             108 :         argtypes[1] = NAMEOID;
 7661 tgl                       792 CBC         108 :         plan = SPI_prepare(query_getviewrule, 2, argtypes);
 8986 bruce                     793 GBC         108 :         if (plan == NULL)
 7196 tgl                       794 UIC           0 :             elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
 4223 tgl                       795 GIC         108 :         SPI_keepplan(plan);
                                796             108 :         plan_getviewrule = plan;
                                797                 :     }
                                798                 : 
                                799                 :     /*
 7661 tgl                       800 ECB             :      * Get the pg_rewrite tuple for the view's SELECT rule
                                801                 :      */
 7661 tgl                       802 GIC        1411 :     args[0] = ObjectIdGetDatum(viewoid);
 3424 peter_e                   803            1411 :     args[1] = DirectFunctionCall1(namein, CStringGetDatum(ViewSelectRuleName));
 8986 bruce                     804            1411 :     nulls[0] = ' ';
 7661 tgl                       805 CBC        1411 :     nulls[1] = ' ';
 3424 peter_e                   806            1411 :     spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0);
 8986 bruce                     807            1411 :     if (spirc != SPI_OK_SELECT)
 7646 tgl                       808 LBC           0 :         elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
 8986 bruce                     809 GBC        1411 :     if (SPI_processed != 1)
 2448 rhaas                     810 ECB             :     {
                                811                 :         /*
                                812                 :          * There is no tuple data available here, just keep the output buffer
                                813                 :          * empty.
                                814                 :          */
                                815                 :     }
                                816                 :     else
 8986 bruce                     817                 :     {
 8053                           818                 :         /*
 6123 neilc                     819                 :          * Get the rule's definition and put it into executor's memory
 8986 bruce                     820                 :          */
 8986 bruce                     821 CBC        1408 :         ruletup = SPI_tuptable->vals[0];
                                822            1408 :         rulettc = SPI_tuptable->tupdesc;
 3758 tgl                       823 GBC        1408 :         make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn);
 8986 bruce                     824 ECB             :     }
                                825                 : 
                                826                 :     /*
                                827                 :      * Disconnect from SPI manager
                                828                 :      */
 8986 bruce                     829 GIC        1411 :     if (SPI_finish() != SPI_OK_FINISH)
 7196 tgl                       830 UIC           0 :         elog(ERROR, "SPI_finish failed");
                                831                 : 
 2448 rhaas                     832 GIC        1411 :     if (buf.len == 0)
                                833               3 :         return NULL;
                                834                 : 
 6913 tgl                       835            1408 :     return buf.data;
 8994 bruce                     836 ECB             : }
                                837                 : 
 7325                           838                 : /* ----------
                                839                 :  * pg_get_triggerdef        - Get the definition of a trigger
                                840                 :  * ----------
                                841                 :  */
                                842                 : Datum
 7325 bruce                     843 GIC         102 : pg_get_triggerdef(PG_FUNCTION_ARGS)
 7325 bruce                     844 ECB             : {
 7325 bruce                     845 GBC         102 :     Oid         trigid = PG_GETARG_OID(0);
                                846                 :     char       *res;
 2448 rhaas                     847 ECB             : 
 2448 rhaas                     848 CBC         102 :     res = pg_get_triggerdef_worker(trigid, false);
                                849                 : 
                                850             102 :     if (res == NULL)
 2448 rhaas                     851 GIC           3 :         PG_RETURN_NULL();
                                852                 : 
                                853              99 :     PG_RETURN_TEXT_P(string_to_text(res));
                                854                 : }
                                855                 : 
                                856                 : Datum
 4930 peter_e                   857             576 : pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
 4930 peter_e                   858 ECB             : {
 4930 peter_e                   859 GIC         576 :     Oid         trigid = PG_GETARG_OID(0);
 4930 peter_e                   860 CBC         576 :     bool        pretty = PG_GETARG_BOOL(1);
                                861                 :     char       *res;
                                862                 : 
 2448 rhaas                     863             576 :     res = pg_get_triggerdef_worker(trigid, pretty);
                                864                 : 
                                865             576 :     if (res == NULL)
 2448 rhaas                     866 LBC           0 :         PG_RETURN_NULL();
                                867                 : 
 2448 rhaas                     868 CBC         576 :     PG_RETURN_TEXT_P(string_to_text(res));
                                869                 : }
                                870                 : 
                                871                 : static char *
 4930 peter_e                   872             678 : pg_get_triggerdef_worker(Oid trigid, bool pretty)
                                873                 : {
 7325 bruce                     874 ECB             :     HeapTuple   ht_trig;
                                875                 :     Form_pg_trigger trigrec;
                                876                 :     StringInfoData buf;
                                877                 :     Relation    tgrel;
 7264 tgl                       878                 :     ScanKeyData skey[1];
                                879                 :     SysScanDesc tgscan;
 7264 tgl                       880 CBC         678 :     int         findx = 0;
 7188 bruce                     881 EUB             :     char       *tgname;
                                882                 :     char       *tgoldtable;
 2347 kgrittn                   883 ECB             :     char       *tgnewtable;
                                884                 :     Datum       value;
                                885                 :     bool        isnull;
                                886                 : 
 7325 bruce                     887                 :     /*
                                888                 :      * Fetch the pg_trigger tuple by the Oid of the trigger
                                889                 :      */
 1539 andres                    890 GIC         678 :     tgrel = table_open(TriggerRelationId, AccessShareLock);
                                891                 : 
 7088 tgl                       892             678 :     ScanKeyInit(&skey[0],
                                893                 :                 Anum_pg_trigger_oid,
                                894                 :                 BTEqualStrategyNumber, F_OIDEQ,
 7088 tgl                       895 ECB             :                 ObjectIdGetDatum(trigid));
                                896                 : 
 6569 tgl                       897 GIC         678 :     tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
                                898                 :                                 NULL, 1, skey);
                                899                 : 
 7264                           900             678 :     ht_trig = systable_getnext(tgscan);
                                901                 : 
                                902             678 :     if (!HeapTupleIsValid(ht_trig))
                                903                 :     {
 2448 rhaas                     904               3 :         systable_endscan(tgscan);
 1539 andres                    905 CBC           3 :         table_close(tgrel, AccessShareLock);
 2448 rhaas                     906 GIC           3 :         return NULL;
 2448 rhaas                     907 ECB             :     }
                                908                 : 
 7325 bruce                     909 GIC         675 :     trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
                                910                 : 
                                911                 :     /*
 6385 bruce                     912 ECB             :      * Start the trigger definition. Note that the trigger's name should never
                                913                 :      * be schema-qualified, but the trigger rel's name may be.
                                914                 :      */
 7325 bruce                     915 CBC         675 :     initStringInfo(&buf);
                                916                 : 
                                917             675 :     tgname = NameStr(trigrec->tgname);
 4826 itagaki.takahiro          918 GIC        1350 :     appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
 4830 tgl                       919 CBC         675 :                      OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
 7325 bruce                     920 ECB             :                      quote_identifier(tgname));
                                921                 : 
 7325 bruce                     922 GIC         675 :     if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
 3447 rhaas                     923             259 :         appendStringInfoString(&buf, "BEFORE");
 4564 tgl                       924 CBC         416 :     else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
 3447 rhaas                     925 GIC         404 :         appendStringInfoString(&buf, "AFTER");
 4564 tgl                       926              12 :     else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
 3447 rhaas                     927              12 :         appendStringInfoString(&buf, "INSTEAD OF");
                                928                 :     else
 4564 tgl                       929 UIC           0 :         elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
 4564 tgl                       930 ECB             : 
 7325 bruce                     931 GIC         675 :     if (TRIGGER_FOR_INSERT(trigrec->tgtype))
 7325 bruce                     932 ECB             :     {
 3447 rhaas                     933 CBC         443 :         appendStringInfoString(&buf, " INSERT");
 7325 bruce                     934             443 :         findx++;
                                935                 :     }
 7325 bruce                     936 GIC         675 :     if (TRIGGER_FOR_DELETE(trigrec->tgtype))
 7325 bruce                     937 ECB             :     {
 7325 bruce                     938 CBC         113 :         if (findx > 0)
 3447 rhaas                     939              45 :             appendStringInfoString(&buf, " OR DELETE");
 7325 bruce                     940 ECB             :         else
 3447 rhaas                     941 CBC          68 :             appendStringInfoString(&buf, " DELETE");
 7325 bruce                     942             113 :         findx++;
                                943                 :     }
 7325 bruce                     944 GBC         675 :     if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
                                945                 :     {
 7325 bruce                     946 CBC         324 :         if (findx > 0)
 3447 rhaas                     947 GIC         160 :             appendStringInfoString(&buf, " OR UPDATE");
 7325 bruce                     948 ECB             :         else
 3447 rhaas                     949 CBC         164 :             appendStringInfoString(&buf, " UPDATE");
 4888 tgl                       950 GIC         324 :         findx++;
 4925 tgl                       951 ECB             :         /* tgattr is first var-width field, so OK to access directly */
 4925 tgl                       952 GIC         324 :         if (trigrec->tgattr.dim1 > 0)
 4925 tgl                       953 ECB             :         {
 4790 bruce                     954                 :             int         i;
                                955                 : 
 4925 tgl                       956 CBC          38 :             appendStringInfoString(&buf, " OF ");
                                957              84 :             for (i = 0; i < trigrec->tgattr.dim1; i++)
                                958                 :             {
 4790 bruce                     959 ECB             :                 char       *attname;
                                960                 : 
 4925 tgl                       961 CBC          46 :                 if (i > 0)
                                962               8 :                     appendStringInfoString(&buf, ", ");
 1882 alvherre                  963 GIC          46 :                 attname = get_attname(trigrec->tgrelid,
 1882 alvherre                  964 CBC          46 :                                       trigrec->tgattr.values[i], false);
 4925 tgl                       965              46 :                 appendStringInfoString(&buf, quote_identifier(attname));
                                966                 :             }
 4925 tgl                       967 ECB             :         }
                                968                 :     }
 5490 tgl                       969 GIC         675 :     if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
                                970                 :     {
 5490 tgl                       971 LBC           0 :         if (findx > 0)
 3447 rhaas                     972               0 :             appendStringInfoString(&buf, " OR TRUNCATE");
                                973                 :         else
 3447 rhaas                     974 UIC           0 :             appendStringInfoString(&buf, " TRUNCATE");
 4888 tgl                       975               0 :         findx++;
 5490 tgl                       976 ECB             :     }
 1868                           977                 : 
                                978                 :     /*
                                979                 :      * In non-pretty mode, always schema-qualify the target table name for
                                980                 :      * safety.  In pretty mode, schema-qualify only if not visible.
                                981                 :      */
 4826 itagaki.takahiro          982 GIC        1350 :     appendStringInfo(&buf, " ON %s ",
                                983                 :                      pretty ?
 1868 tgl                       984 CBC          69 :                      generate_relation_name(trigrec->tgrelid, NIL) :
 1868 tgl                       985 GIC         606 :                      generate_qualified_relation_name(trigrec->tgrelid));
 7325 bruce                     986 EUB             : 
 4830 tgl                       987 GBC         675 :     if (OidIsValid(trigrec->tgconstraint))
                                988                 :     {
 4888 tgl                       989 UBC           0 :         if (OidIsValid(trigrec->tgconstrrelid))
 4826 itagaki.takahiro          990               0 :             appendStringInfo(&buf, "FROM %s ",
                                991                 :                              generate_relation_name(trigrec->tgconstrrelid, NIL));
 7325 bruce                     992 UIC           0 :         if (!trigrec->tgdeferrable)
 3447 rhaas                     993               0 :             appendStringInfoString(&buf, "NOT ");
                                994               0 :         appendStringInfoString(&buf, "DEFERRABLE INITIALLY ");
 7325 bruce                     995               0 :         if (trigrec->tginitdeferred)
 3447 rhaas                     996               0 :             appendStringInfoString(&buf, "DEFERRED ");
 7325 bruce                     997 ECB             :         else
 3447 rhaas                     998 UIC           0 :             appendStringInfoString(&buf, "IMMEDIATE ");
 7325 bruce                     999 ECB             :     }
                               1000                 : 
 2347 kgrittn                  1001 GIC         675 :     value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable,
 2347 kgrittn                  1002 ECB             :                         tgrel->rd_att, &isnull);
 2347 kgrittn                  1003 GIC         675 :     if (!isnull)
 1633 tgl                      1004 GBC          49 :         tgoldtable = NameStr(*DatumGetName(value));
 2347 kgrittn                  1005 EUB             :     else
 2347 kgrittn                  1006 GIC         626 :         tgoldtable = NULL;
 2347 kgrittn                  1007 GBC         675 :     value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable,
 2347 kgrittn                  1008 EUB             :                         tgrel->rd_att, &isnull);
 2347 kgrittn                  1009 GBC         675 :     if (!isnull)
 1633 tgl                      1010              54 :         tgnewtable = NameStr(*DatumGetName(value));
 2347 kgrittn                  1011 EUB             :     else
 2347 kgrittn                  1012 GIC         621 :         tgnewtable = NULL;
 2347 kgrittn                  1013 GBC         675 :     if (tgoldtable != NULL || tgnewtable != NULL)
                               1014                 :     {
 2347 kgrittn                  1015 GIC          76 :         appendStringInfoString(&buf, "REFERENCING ");
 2347 kgrittn                  1016 CBC          76 :         if (tgoldtable != NULL)
 1633 tgl                      1017 GIC          49 :             appendStringInfo(&buf, "OLD TABLE AS %s ",
 1633 tgl                      1018 ECB             :                              quote_identifier(tgoldtable));
 2347 kgrittn                  1019 CBC          76 :         if (tgnewtable != NULL)
 1633 tgl                      1020 GIC          54 :             appendStringInfo(&buf, "NEW TABLE AS %s ",
 1633 tgl                      1021 ECB             :                              quote_identifier(tgnewtable));
 2347 kgrittn                  1022                 :     }
                               1023                 : 
 7325 bruce                    1024 CBC         675 :     if (TRIGGER_FOR_ROW(trigrec->tgtype))
 3447 rhaas                    1025             520 :         appendStringInfoString(&buf, "FOR EACH ROW ");
                               1026                 :     else
                               1027             155 :         appendStringInfoString(&buf, "FOR EACH STATEMENT ");
 7325 bruce                    1028 ECB             : 
                               1029                 :     /* If the trigger has a WHEN qualification, add that */
 4888 tgl                      1030 CBC         675 :     value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
 4888 tgl                      1031 ECB             :                         tgrel->rd_att, &isnull);
 4888 tgl                      1032 CBC         675 :     if (!isnull)
                               1033                 :     {
 4790 bruce                    1034 ECB             :         Node       *qual;
 4429 tgl                      1035                 :         char        relkind;
                               1036                 :         deparse_context context;
                               1037                 :         deparse_namespace dpns;
                               1038                 :         RangeTblEntry *oldrte;
 4790 bruce                    1039                 :         RangeTblEntry *newrte;
 4888 tgl                      1040                 : 
 4888 tgl                      1041 GIC          72 :         appendStringInfoString(&buf, "WHEN (");
 4888 tgl                      1042 ECB             : 
 4888 tgl                      1043 GIC          72 :         qual = stringToNode(TextDatumGetCString(value));
                               1044                 : 
 4429 tgl                      1045 CBC          72 :         relkind = get_rel_relkind(trigrec->tgrelid);
                               1046                 : 
 4888 tgl                      1047 ECB             :         /* Build minimal OLD and NEW RTEs for the rel */
 4888 tgl                      1048 GIC          72 :         oldrte = makeNode(RangeTblEntry);
                               1049              72 :         oldrte->rtekind = RTE_RELATION;
                               1050              72 :         oldrte->relid = trigrec->tgrelid;
 4429                          1051              72 :         oldrte->relkind = relkind;
 1652                          1052              72 :         oldrte->rellockmode = AccessShareLock;
 3852                          1053              72 :         oldrte->alias = makeAlias("old", NIL);
                               1054              72 :         oldrte->eref = oldrte->alias;
 3897                          1055              72 :         oldrte->lateral = false;
 4888 tgl                      1056 CBC          72 :         oldrte->inh = false;
 4888 tgl                      1057 GIC          72 :         oldrte->inFromCl = true;
 4888 tgl                      1058 ECB             : 
 4888 tgl                      1059 GIC          72 :         newrte = makeNode(RangeTblEntry);
 4888 tgl                      1060 CBC          72 :         newrte->rtekind = RTE_RELATION;
 4888 tgl                      1061 GIC          72 :         newrte->relid = trigrec->tgrelid;
 4429                          1062              72 :         newrte->relkind = relkind;
 1652 tgl                      1063 CBC          72 :         newrte->rellockmode = AccessShareLock;
 3852                          1064              72 :         newrte->alias = makeAlias("new", NIL);
                               1065              72 :         newrte->eref = newrte->alias;
 3897                          1066              72 :         newrte->lateral = false;
 4888                          1067              72 :         newrte->inh = false;
                               1068              72 :         newrte->inFromCl = true;
 4888 tgl                      1069 ECB             : 
                               1070                 :         /* Build two-element rtable */
 4653 tgl                      1071 CBC          72 :         memset(&dpns, 0, sizeof(dpns));
 4888                          1072              72 :         dpns.rtable = list_make2(oldrte, newrte);
 1215 tgl                      1073 GIC          72 :         dpns.subplans = NIL;
 4888 tgl                      1074 CBC          72 :         dpns.ctes = NIL;
 1215                          1075              72 :         dpns.appendrels = NULL;
 3852                          1076              72 :         set_rtable_names(&dpns, NIL, NULL);
 3751                          1077              72 :         set_simple_column_names(&dpns);
 4888 tgl                      1078 ECB             : 
                               1079                 :         /* Set up context with one-deep namespace stack */
 4888 tgl                      1080 CBC          72 :         context.buf = &buf;
                               1081              72 :         context.namespaces = list_make1(&dpns);
                               1082              72 :         context.windowClause = NIL;
                               1083              72 :         context.windowTList = NIL;
 4888 tgl                      1084 GIC          72 :         context.varprefix = true;
  377                          1085              72 :         context.prettyFlags = GET_PRETTY_FLAGS(pretty);
 3758 tgl                      1086 CBC          72 :         context.wrapColumn = WRAP_COLUMN_DEFAULT;
 4888                          1087              72 :         context.indentLevel = PRETTYINDENT_STD;
 2885 andres                   1088              72 :         context.special_exprkind = EXPR_KIND_NONE;
 1215 tgl                      1089              72 :         context.appendparents = NULL;
 4888 tgl                      1090 ECB             : 
 4888 tgl                      1091 CBC          72 :         get_rule_expr(qual, &context, false);
 4888 tgl                      1092 ECB             : 
 3447 rhaas                    1093 GIC          72 :         appendStringInfoString(&buf, ") ");
                               1094                 :     }
 4888 tgl                      1095 ECB             : 
 1522 peter                    1096 CBC         675 :     appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
 4931 tgl                      1097 ECB             :                      generate_function_name(trigrec->tgfoid, 0,
 1244                          1098                 :                                             NIL, NULL,
 2885 andres                   1099                 :                                             false, NULL, EXPR_KIND_NONE));
 7325 bruce                    1100                 : 
 7264 tgl                      1101 CBC         675 :     if (trigrec->tgnargs > 0)
 7325 bruce                    1102 ECB             :     {
 7264 tgl                      1103                 :         char       *p;
                               1104                 :         int         i;
                               1105                 : 
 4888 tgl                      1106 CBC         225 :         value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
                               1107                 :                             tgrel->rd_att, &isnull);
 7264                          1108             225 :         if (isnull)
 7264 tgl                      1109 UIC           0 :             elog(ERROR, "tgargs is null for trigger %u", trigid);
 2219 noah                     1110 GIC         225 :         p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
 7264 tgl                      1111 CBC         598 :         for (i = 0; i < trigrec->tgnargs; i++)
                               1112                 :         {
 7264 tgl                      1113 GIC         373 :             if (i > 0)
 3447 rhaas                    1114             148 :                 appendStringInfoString(&buf, ", ");
 5328 tgl                      1115             373 :             simple_quote_literal(&buf, p);
 6160 tgl                      1116 ECB             :             /* advance p to next string embedded in tgargs */
 5328 tgl                      1117 GIC        3378 :             while (*p)
                               1118            3005 :                 p++;
 6160                          1119             373 :             p++;
                               1120                 :         }
 7325 bruce                    1121 ECB             :     }
                               1122                 : 
 7264 tgl                      1123                 :     /* We deliberately do not put semi-colon at end */
 3447 rhaas                    1124 GBC         675 :     appendStringInfoChar(&buf, ')');
 7325 bruce                    1125 ECB             : 
 6913 tgl                      1126                 :     /* Clean up */
 7264 tgl                      1127 GIC         675 :     systable_endscan(tgscan);
 7264 tgl                      1128 ECB             : 
 1539 andres                   1129 CBC         675 :     table_close(tgrel, AccessShareLock);
 7325 bruce                    1130 ECB             : 
 4930 peter_e                  1131 GIC         675 :     return buf.data;
 7325 bruce                    1132 ECB             : }
 8994                          1133                 : 
 8955                          1134                 : /* ----------
                               1135                 :  * pg_get_indexdef          - Get the definition of an index
                               1136                 :  *
                               1137                 :  * In the extended version, there is a colno argument as well as pretty bool.
                               1138                 :  *  if colno == 0, we want a complete index definition.
 7193 tgl                      1139                 :  *  if colno > 0, we only want the Nth index key's variable or expression.
                               1140                 :  *
                               1141                 :  * Note that the SQL-function versions of this omit any info about the
 5657                          1142                 :  * index tablespace; this is intentional because pg_dump wants it that way.
                               1143                 :  * However pg_get_indexdef_string() includes the index tablespace.
 8955 bruce                    1144                 :  * ----------
                               1145                 :  */
 8339 tgl                      1146                 : Datum
 8339 tgl                      1147 GIC        2088 : pg_get_indexdef(PG_FUNCTION_ARGS)
                               1148                 : {
                               1149            2088 :     Oid         indexrelid = PG_GETARG_OID(0);
                               1150                 :     int         prettyFlags;
                               1151                 :     char       *res;
                               1152                 : 
 3717                          1153            2088 :     prettyFlags = PRETTYFLAG_INDENT;
                               1154                 : 
 1725                          1155            2088 :     res = pg_get_indexdef_worker(indexrelid, 0, NULL,
                               1156                 :                                  false, false,
                               1157                 :                                  false, false,
                               1158                 :                                  prettyFlags, true);
                               1159                 : 
 2448 rhaas                    1160            2088 :     if (res == NULL)
                               1161               3 :         PG_RETURN_NULL();
 2448 rhaas                    1162 ECB             : 
 2448 rhaas                    1163 GIC        2085 :     PG_RETURN_TEXT_P(string_to_text(res));
 7193 tgl                      1164 ECB             : }
                               1165                 : 
                               1166                 : Datum
 7193 tgl                      1167 GIC         850 : pg_get_indexdef_ext(PG_FUNCTION_ARGS)
 7193 tgl                      1168 ECB             : {
 7193 tgl                      1169 GIC         850 :     Oid         indexrelid = PG_GETARG_OID(0);
 7188 bruce                    1170 CBC         850 :     int32       colno = PG_GETARG_INT32(1);
 7193 tgl                      1171 GIC         850 :     bool        pretty = PG_GETARG_BOOL(2);
                               1172                 :     int         prettyFlags;
                               1173                 :     char       *res;
                               1174                 : 
  377 tgl                      1175 CBC         850 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
 2448 rhaas                    1176 ECB             : 
 1725 tgl                      1177 GIC         850 :     res = pg_get_indexdef_worker(indexrelid, colno, NULL,
 1725 tgl                      1178 ECB             :                                  colno != 0, false,
                               1179                 :                                  false, false,
                               1180                 :                                  prettyFlags, true);
                               1181                 : 
 2448 rhaas                    1182 CBC         850 :     if (res == NULL)
 2448 rhaas                    1183 UIC           0 :         PG_RETURN_NULL();
 2448 rhaas                    1184 ECB             : 
 2448 rhaas                    1185 CBC         850 :     PG_RETURN_TEXT_P(string_to_text(res));
 6913 tgl                      1186 ECB             : }
                               1187                 : 
                               1188                 : /*
                               1189                 :  * Internal version for use by ALTER TABLE.
 2328                          1190                 :  * Includes a tablespace clause in the result.
                               1191                 :  * Returns a palloc'd C string; no pretty-printing.
                               1192                 :  */
                               1193                 : char *
 6913 tgl                      1194 GIC          97 : pg_get_indexdef_string(Oid indexrelid)
                               1195                 : {
 1725                          1196              97 :     return pg_get_indexdef_worker(indexrelid, 0, NULL,
 1725 tgl                      1197 ECB             :                                   false, false,
 1725 tgl                      1198 EUB             :                                   true, true,
                               1199                 :                                   0, false);
 4999 tgl                      1200 ECB             : }
                               1201                 : 
                               1202                 : /* Internal version that just reports the key-column definitions */
                               1203                 : char *
 4999 tgl                      1204 GIC         550 : pg_get_indexdef_columns(Oid indexrelid, bool pretty)
                               1205                 : {
                               1206                 :     int         prettyFlags;
                               1207                 : 
  377                          1208             550 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
 1868 tgl                      1209 ECB             : 
 1725 tgl                      1210 GIC         550 :     return pg_get_indexdef_worker(indexrelid, 0, NULL,
 1725 tgl                      1211 ECB             :                                   true, true,
                               1212                 :                                   false, false,
                               1213                 :                                   prettyFlags, false);
                               1214                 : }
                               1215                 : 
                               1216                 : /*
                               1217                 :  * Internal workhorse to decompile an index definition.
                               1218                 :  *
 4871                          1219                 :  * This is now used for exclusion constraints as well: if excludeOps is not
                               1220                 :  * NULL then it points to an array of exclusion operator OIDs.
                               1221                 :  */
                               1222                 : static char *
 4999 tgl                      1223 CBC        3637 : pg_get_indexdef_worker(Oid indexrelid, int colno,
                               1224                 :                        const Oid *excludeOps,
 1725 tgl                      1225 ECB             :                        bool attrsOnly, bool keysOnly,
                               1226                 :                        bool showTblSpc, bool inherits,
                               1227                 :                        int prettyFlags, bool missing_ok)
                               1228                 : {
                               1229                 :     /* might want a separate isConstraint parameter later */
 4871 tgl                      1230 GIC        3637 :     bool        isConstraint = (excludeOps != NULL);
                               1231                 :     HeapTuple   ht_idx;
                               1232                 :     HeapTuple   ht_idxrel;
                               1233                 :     HeapTuple   ht_am;
                               1234                 :     Form_pg_index idxrec;
                               1235                 :     Form_pg_class idxrelrec;
                               1236                 :     Form_pg_am  amrec;
                               1237                 :     IndexAmRoutine *amroutine;
 7256 tgl                      1238 ECB             :     List       *indexprs;
                               1239                 :     ListCell   *indexpr_item;
                               1240                 :     List       *context;
                               1241                 :     Oid         indrelid;
                               1242                 :     int         keyno;
                               1243                 :     Datum       indcollDatum;
                               1244                 :     Datum       indclassDatum;
 5934                          1245                 :     Datum       indoptionDatum;
                               1246                 :     oidvector  *indcollation;
                               1247                 :     oidvector  *indclass;
                               1248                 :     int2vector *indoption;
                               1249                 :     StringInfoData buf;
                               1250                 :     char       *str;
                               1251                 :     char       *sep;
                               1252                 : 
                               1253                 :     /*
                               1254                 :      * Fetch the pg_index tuple by the Oid of the index
                               1255                 :      */
 4802 rhaas                    1256 GIC        3637 :     ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
 8955 bruce                    1257            3637 :     if (!HeapTupleIsValid(ht_idx))
                               1258                 :     {
 2448 rhaas                    1259               3 :         if (missing_ok)
                               1260               3 :             return NULL;
 7196 tgl                      1261 UIC           0 :         elog(ERROR, "cache lookup failed for index %u", indexrelid);
                               1262                 :     }
 8720 bruce                    1263 GIC        3634 :     idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
                               1264                 : 
 7646 tgl                      1265            3634 :     indrelid = idxrec->indrelid;
                               1266            3634 :     Assert(indexrelid == idxrec->indexrelid);
                               1267                 : 
                               1268                 :     /* Must get indcollation, indclass, and indoption the hard way */
   15 dgustafsson              1269 GNC        3634 :     indcollDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1270                 :                                           Anum_pg_index_indcollation);
 4443 peter_e                  1271 GIC        3634 :     indcollation = (oidvector *) DatumGetPointer(indcollDatum);
 4443 peter_e                  1272 ECB             : 
   15 dgustafsson              1273 GNC        3634 :     indclassDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1274                 :                                            Anum_pg_index_indclass);
 6585 tgl                      1275 CBC        3634 :     indclass = (oidvector *) DatumGetPointer(indclassDatum);
                               1276                 : 
   15 dgustafsson              1277 GNC        3634 :     indoptionDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1278                 :                                             Anum_pg_index_indoption);
 5934 tgl                      1279 GIC        3634 :     indoption = (int2vector *) DatumGetPointer(indoptionDatum);
 6585 tgl                      1280 ECB             : 
                               1281                 :     /*
 8955 bruce                    1282                 :      * Fetch the pg_class tuple of the index relation
                               1283                 :      */
 4802 rhaas                    1284 CBC        3634 :     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
 8955 bruce                    1285 GIC        3634 :     if (!HeapTupleIsValid(ht_idxrel))
 7196 tgl                      1286 LBC           0 :         elog(ERROR, "cache lookup failed for relation %u", indexrelid);
 8720 bruce                    1287 GIC        3634 :     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
 8955 bruce                    1288 ECB             : 
                               1289                 :     /*
 7860 tgl                      1290                 :      * Fetch the pg_am tuple of the index' access method
                               1291                 :      */
 4802 rhaas                    1292 GIC        3634 :     ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
 7719 tgl                      1293            3634 :     if (!HeapTupleIsValid(ht_am))
 7196 tgl                      1294 UIC           0 :         elog(ERROR, "cache lookup failed for access method %u",
 7196 tgl                      1295 ECB             :              idxrelrec->relam);
 7719 tgl                      1296 CBC        3634 :     amrec = (Form_pg_am) GETSTRUCT(ht_am);
 8955 bruce                    1297 EUB             : 
 2639 tgl                      1298 ECB             :     /* Fetch the index AM's API struct */
 2639 tgl                      1299 GIC        3634 :     amroutine = GetIndexAmRoutine(amrec->amhandler);
                               1300                 : 
                               1301                 :     /*
                               1302                 :      * Get the index expressions, if any.  (NOTE: we do not use the relcache
 6385 bruce                    1303 ECB             :      * versions of the expressions and predicate, because we want to display
                               1304                 :      * non-const-folded expressions.)
 7256 tgl                      1305 EUB             :      */
 1838 andrew                   1306 GIC        3634 :     if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
 7256 tgl                      1307 ECB             :     {
                               1308                 :         Datum       exprsDatum;
                               1309                 :         char       *exprsString;
                               1310                 : 
   15 dgustafsson              1311 GNC         276 :         exprsDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1312                 :                                             Anum_pg_index_indexprs);
 5493 tgl                      1313 GIC         276 :         exprsString = TextDatumGetCString(exprsDatum);
 7256                          1314             276 :         indexprs = (List *) stringToNode(exprsString);
 7256 tgl                      1315 CBC         276 :         pfree(exprsString);
                               1316                 :     }
                               1317                 :     else
 7256 tgl                      1318 GIC        3358 :         indexprs = NIL;
                               1319                 : 
 6892 neilc                    1320 CBC        3634 :     indexpr_item = list_head(indexprs);
                               1321                 : 
 4541 tgl                      1322            3634 :     context = deparse_context_for(get_relation_name(indrelid), indrelid);
 7256 tgl                      1323 ECB             : 
 8053 bruce                    1324                 :     /*
                               1325                 :      * Start the index definition.  Note that the index's name should never be
                               1326                 :      * schema-qualified, but the indexed rel's name may be.
 8955                          1327                 :      */
 8590 tgl                      1328 GIC        3634 :     initStringInfo(&buf);
 7193 tgl                      1329 ECB             : 
 4999 tgl                      1330 GIC        3634 :     if (!attrsOnly)
 4871 tgl                      1331 ECB             :     {
 4871 tgl                      1332 GIC        2859 :         if (!isConstraint)
 1906 alvherre                 1333            5614 :             appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (",
 4871 tgl                      1334            2807 :                              idxrec->indisunique ? "UNIQUE " : "",
                               1335            2807 :                              quote_identifier(NameStr(idxrelrec->relname)),
 1906 alvherre                 1336            2807 :                              idxrelrec->relkind == RELKIND_PARTITIONED_INDEX
 1906 alvherre                 1337 CBC         318 :                              && !inherits ? "ONLY " : "",
 1868 tgl                      1338 GIC        2807 :                              (prettyFlags & PRETTYFLAG_SCHEMA) ?
 1868 tgl                      1339 CBC         625 :                              generate_relation_name(indrelid, NIL) :
 1868 tgl                      1340 GIC        2182 :                              generate_qualified_relation_name(indrelid),
 4871 tgl                      1341 CBC        2807 :                              quote_identifier(NameStr(amrec->amname)));
 2118 tgl                      1342 ECB             :         else                    /* currently, must be EXCLUDE constraint */
 4871 tgl                      1343 CBC          52 :             appendStringInfo(&buf, "EXCLUDE USING %s (",
                               1344              52 :                              quote_identifier(NameStr(amrec->amname)));
 4871 tgl                      1345 ECB             :     }
 8720 bruce                    1346                 : 
 8053                          1347                 :     /*
 7256 tgl                      1348                 :      * Report the indexed attributes
 8955 bruce                    1349                 :      */
 8955 bruce                    1350 CBC        3634 :     sep = "";
 7256 tgl                      1351 GIC        8973 :     for (keyno = 0; keyno < idxrec->indnatts; keyno++)
 8955 bruce                    1352 ECB             :     {
 6585 tgl                      1353 CBC        5387 :         AttrNumber  attnum = idxrec->indkey.values[keyno];
                               1354                 :         Oid         keycoltype;
                               1355                 :         Oid         keycolcollation;
                               1356                 : 
                               1357                 :         /*
                               1358                 :          * Ignore non-key attributes if told to.
 1828 teodor                   1359 ECB             :          */
 1725 tgl                      1360 CBC        5387 :         if (keysOnly && keyno >= idxrec->indnkeyatts)
 1828 teodor                   1361 GIC          48 :             break;
 1828 teodor                   1362 ECB             : 
                               1363                 :         /* Otherwise, print INCLUDE to divide key and non-key attrs. */
 1725 tgl                      1364 GIC        5339 :         if (!colno && keyno == idxrec->indnkeyatts)
                               1365                 :         {
 1828 teodor                   1366             124 :             appendStringInfoString(&buf, ") INCLUDE (");
                               1367             124 :             sep = "";
                               1368                 :         }
 1828 teodor                   1369 ECB             : 
 7193 tgl                      1370 CBC        5339 :         if (!colno)
 6553 neilc                    1371 GIC        5024 :             appendStringInfoString(&buf, sep);
 8955 bruce                    1372            5339 :         sep = ", ";
 8955 bruce                    1373 ECB             : 
 7256 tgl                      1374 GIC        5339 :         if (attnum != 0)
 7256 tgl                      1375 ECB             :         {
                               1376                 :             /* Simple index column */
                               1377                 :             char       *attname;
                               1378                 :             int32       keycoltypmod;
 8955 bruce                    1379                 : 
 1882 alvherre                 1380 CBC        4984 :             attname = get_attname(indrelid, attnum, false);
 7188 bruce                    1381            4984 :             if (!colno || colno == keyno + 1)
 7008 neilc                    1382 GIC        4900 :                 appendStringInfoString(&buf, quote_identifier(attname));
 4397 tgl                      1383 CBC        4984 :             get_atttypetypmodcoll(indrelid, attnum,
                               1384                 :                                   &keycoltype, &keycoltypmod,
                               1385                 :                                   &keycolcollation);
                               1386                 :         }
                               1387                 :         else
                               1388                 :         {
 7256 tgl                      1389 ECB             :             /* expressional index */
                               1390                 :             Node       *indexkey;
                               1391                 : 
 6892 neilc                    1392 CBC         355 :             if (indexpr_item == NULL)
 7256 tgl                      1393 UIC           0 :                 elog(ERROR, "too few entries in indexprs list");
 6892 neilc                    1394 GIC         355 :             indexkey = (Node *) lfirst(indexpr_item);
 1364 tgl                      1395             355 :             indexpr_item = lnext(indexprs, indexpr_item);
                               1396                 :             /* Deparse */
 7193                          1397             355 :             str = deparse_expression_pretty(indexkey, context, false, false,
                               1398                 :                                             prettyFlags, 0);
 7188 bruce                    1399             355 :             if (!colno || colno == keyno + 1)
                               1400                 :             {
 7188 bruce                    1401 ECB             :                 /* Need parens if it's not a bare function call */
 2096 tgl                      1402 GBC         349 :                 if (looks_like_function(indexkey))
 7008 neilc                    1403 CBC          26 :                     appendStringInfoString(&buf, str);
 7188 bruce                    1404 ECB             :                 else
 7193 tgl                      1405 GIC         323 :                     appendStringInfo(&buf, "(%s)", str);
 7193 tgl                      1406 ECB             :             }
 7256 tgl                      1407 GIC         355 :             keycoltype = exprType(indexkey);
 4399 tgl                      1408 CBC         355 :             keycolcollation = exprCollation(indexkey);
                               1409                 :         }
                               1410                 : 
 1725 tgl                      1411 ECB             :         /* Print additional decoration for (selected) key columns */
 1725 tgl                      1412 CBC        5339 :         if (!attrsOnly && keyno < idxrec->indnkeyatts &&
 1725 tgl                      1413 UIC           0 :             (!colno || colno == keyno + 1))
 5589 tgl                      1414 ECB             :         {
 1463 tgl                      1415 GIC        4169 :             int16       opt = indoption->values[keyno];
 1463 tgl                      1416 CBC        4169 :             Oid         indcoll = indcollation->values[keyno];
 1105 akorotkov                1417            4169 :             Datum       attoptions = get_attoptions(indexrelid, keyno + 1);
 1105 akorotkov                1418 GIC        4169 :             bool        has_options = attoptions != (Datum) 0;
                               1419                 : 
                               1420                 :             /* Add collation, if not default for column */
 4399 tgl                      1421 CBC        4169 :             if (OidIsValid(indcoll) && indcoll != keycolcollation)
 4399 tgl                      1422 GBC          54 :                 appendStringInfo(&buf, " COLLATE %s",
                               1423                 :                                  generate_collation_name((indcoll)));
 4443 peter_e                  1424 ECB             : 
 5589 tgl                      1425                 :             /* Add the operator class name, if not default */
 1105 akorotkov                1426 CBC        4169 :             get_opclass_name(indclass->values[keyno],
 1105 akorotkov                1427 ECB             :                              has_options ? InvalidOid : keycoltype, &buf);
                               1428                 : 
 1105 akorotkov                1429 GIC        4169 :             if (has_options)
 1105 akorotkov                1430 ECB             :             {
 1105 akorotkov                1431 CBC          15 :                 appendStringInfoString(&buf, " (");
 1105 akorotkov                1432 GIC          15 :                 get_reloptions(&buf, attoptions);
                               1433              15 :                 appendStringInfoChar(&buf, ')');
                               1434                 :             }
 5934 tgl                      1435 ECB             : 
                               1436                 :             /* Add options if relevant */
 2639 tgl                      1437 GIC        4169 :             if (amroutine->amcanorder)
 5934 tgl                      1438 ECB             :             {
                               1439                 :                 /* if it supports sort ordering, report DESC and NULLS opts */
 5589 tgl                      1440 CBC        3520 :                 if (opt & INDOPTION_DESC)
 5589 tgl                      1441 ECB             :                 {
 3447 rhaas                    1442 LBC           0 :                     appendStringInfoString(&buf, " DESC");
                               1443                 :                     /* NULLS FIRST is the default in this case */
 5589 tgl                      1444 UIC           0 :                     if (!(opt & INDOPTION_NULLS_FIRST))
 3447 rhaas                    1445               0 :                         appendStringInfoString(&buf, " NULLS LAST");
 5589 tgl                      1446 ECB             :                 }
                               1447                 :                 else
                               1448                 :                 {
 5589 tgl                      1449 CBC        3520 :                     if (opt & INDOPTION_NULLS_FIRST)
 3447 rhaas                    1450 UIC           0 :                         appendStringInfoString(&buf, " NULLS FIRST");
 5589 tgl                      1451 EUB             :                 }
                               1452                 :             }
 4871                          1453                 : 
                               1454                 :             /* Add the exclusion operator if relevant */
 4871 tgl                      1455 GIC        4169 :             if (excludeOps != NULL)
                               1456              62 :                 appendStringInfo(&buf, " WITH %s",
                               1457              62 :                                  generate_operator_name(excludeOps[keyno],
 4871 tgl                      1458 ECB             :                                                         keycoltype,
 4871 tgl                      1459 EUB             :                                                         keycoltype));
                               1460                 :         }
                               1461                 :     }
                               1462                 : 
 4999 tgl                      1463 GIC        3634 :     if (!attrsOnly)
 6124 tgl                      1464 ECB             :     {
 7188 bruce                    1465 CBC        2859 :         appendStringInfoChar(&buf, ')');
 7860 tgl                      1466 ECB             : 
  430 peter                    1467 GIC        2859 :         if (idxrec->indnullsnotdistinct)
  215 drowley                  1468 GNC           6 :             appendStringInfoString(&buf, " NULLS NOT DISTINCT");
                               1469                 : 
                               1470                 :         /*
                               1471                 :          * If it has options, append "WITH (options)"
 6124 tgl                      1472 ECB             :          */
 6124 tgl                      1473 GIC        2859 :         str = flatten_reloptions(indexrelid);
 6124 tgl                      1474 CBC        2859 :         if (str)
                               1475                 :         {
                               1476             105 :             appendStringInfo(&buf, " WITH (%s)", str);
                               1477             105 :             pfree(str);
                               1478                 :         }
                               1479                 : 
                               1480                 :         /*
                               1481                 :          * Print tablespace, but only if requested
 6124 tgl                      1482 ECB             :          */
 5657 tgl                      1483 CBC        2859 :         if (showTblSpc)
                               1484                 :         {
 5657 tgl                      1485 ECB             :             Oid         tblspc;
                               1486                 : 
 5657 tgl                      1487 GIC          97 :             tblspc = get_rel_tablespace(indexrelid);
 1445 alvherre                 1488              97 :             if (OidIsValid(tblspc))
                               1489                 :             {
                               1490              27 :                 if (isConstraint)
 1445 alvherre                 1491 UIC           0 :                     appendStringInfoString(&buf, " USING INDEX");
 1445 alvherre                 1492 CBC          27 :                 appendStringInfo(&buf, " TABLESPACE %s",
 1445 alvherre                 1493 GIC          27 :                                  quote_identifier(get_tablespace_name(tblspc)));
                               1494                 :             }
                               1495                 :         }
 6125 bruce                    1496 ECB             : 
 7188                          1497                 :         /*
                               1498                 :          * If it's a partial index, decompile and append the predicate
                               1499                 :          */
 1838 andrew                   1500 GBC        2859 :         if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
 7188 bruce                    1501 ECB             :         {
 7193 tgl                      1502                 :             Node       *node;
                               1503                 :             Datum       predDatum;
                               1504                 :             char       *predString;
                               1505                 : 
                               1506                 :             /* Convert text string to node tree */
   15 dgustafsson              1507 GNC         154 :             predDatum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1508                 :                                                Anum_pg_index_indpred);
 5493 tgl                      1509 GIC         154 :             predString = TextDatumGetCString(predDatum);
 7193                          1510             154 :             node = (Node *) stringToNode(predString);
                               1511             154 :             pfree(predString);
                               1512                 : 
                               1513                 :             /* Deparse */
 7193 tgl                      1514 CBC         154 :             str = deparse_expression_pretty(node, context, false, false,
                               1515                 :                                             prettyFlags, 0);
 4871                          1516             154 :             if (isConstraint)
                               1517              21 :                 appendStringInfo(&buf, " WHERE (%s)", str);
 4871 tgl                      1518 ECB             :             else
 4871 tgl                      1519 GIC         133 :                 appendStringInfo(&buf, " WHERE %s", str);
                               1520                 :         }
 7860 tgl                      1521 ECB             :     }
                               1522                 : 
 6913                          1523                 :     /* Clean up */
 8179 tgl                      1524 CBC        3634 :     ReleaseSysCache(ht_idx);
 8179 tgl                      1525 GIC        3634 :     ReleaseSysCache(ht_idxrel);
 7719 tgl                      1526 CBC        3634 :     ReleaseSysCache(ht_am);
                               1527                 : 
 6913 tgl                      1528 GIC        3634 :     return buf.data;
                               1529                 : }
                               1530                 : 
  377 tgl                      1531 ECB             : /* ----------
                               1532                 :  * pg_get_querydef
                               1533                 :  *
                               1534                 :  * Public entry point to deparse one query parsetree.
                               1535                 :  * The pretty flags are determined by GET_PRETTY_FLAGS(pretty).
                               1536                 :  *
                               1537                 :  * The result is a palloc'd C string.
                               1538                 :  * ----------
                               1539                 :  */
                               1540                 : char *
  377 tgl                      1541 UIC           0 : pg_get_querydef(Query *query, bool pretty)
                               1542                 : {
                               1543                 :     StringInfoData buf;
                               1544                 :     int         prettyFlags;
                               1545                 : 
                               1546               0 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                               1547                 : 
  377 tgl                      1548 UBC           0 :     initStringInfo(&buf);
                               1549                 : 
  323 tgl                      1550 UIC           0 :     get_query_def(query, &buf, NIL, NULL, true,
                               1551                 :                   prettyFlags, WRAP_COLUMN_DEFAULT, 0);
                               1552                 : 
  377 tgl                      1553 UBC           0 :     return buf.data;
                               1554                 : }
  377 tgl                      1555 EUB             : 
                               1556                 : /*
 2156                          1557                 :  * pg_get_statisticsobjdef
                               1558                 :  *      Get the definition of an extended statistics object
                               1559                 :  */
 2207 alvherre                 1560                 : Datum
 2156 tgl                      1561 GIC         134 : pg_get_statisticsobjdef(PG_FUNCTION_ARGS)
                               1562                 : {
 2207 alvherre                 1563             134 :     Oid         statextid = PG_GETARG_OID(0);
                               1564                 :     char       *res;
                               1565                 : 
  744 tomas.vondra             1566             134 :     res = pg_get_statisticsobj_worker(statextid, false, true);
                               1567                 : 
  744 tomas.vondra             1568 CBC         134 :     if (res == NULL)
  744 tomas.vondra             1569 GIC           3 :         PG_RETURN_NULL();
  744 tomas.vondra             1570 ECB             : 
  744 tomas.vondra             1571 GIC         131 :     PG_RETURN_TEXT_P(string_to_text(res));
                               1572                 : }
  744 tomas.vondra             1573 ECB             : 
                               1574                 : /*
                               1575                 :  * Internal version for use by ALTER TABLE.
                               1576                 :  * Includes a tablespace clause in the result.
                               1577                 :  * Returns a palloc'd C string; no pretty-printing.
                               1578                 :  */
                               1579                 : char *
  744 tomas.vondra             1580 GIC           7 : pg_get_statisticsobjdef_string(Oid statextid)
                               1581                 : {
                               1582               7 :     return pg_get_statisticsobj_worker(statextid, false, false);
                               1583                 : }
                               1584                 : 
                               1585                 : /*
                               1586                 :  * pg_get_statisticsobjdef_columns
  744 tomas.vondra             1587 ECB             :  *      Get columns and expressions for an extended statistics object
                               1588                 :  */
                               1589                 : Datum
  744 tomas.vondra             1590 GIC         198 : pg_get_statisticsobjdef_columns(PG_FUNCTION_ARGS)
                               1591                 : {
                               1592             198 :     Oid         statextid = PG_GETARG_OID(0);
                               1593                 :     char       *res;
                               1594                 : 
                               1595             198 :     res = pg_get_statisticsobj_worker(statextid, true, true);
                               1596                 : 
 2207 alvherre                 1597 CBC         198 :     if (res == NULL)
 2207 alvherre                 1598 UIC           0 :         PG_RETURN_NULL();
 2207 alvherre                 1599 ECB             : 
 2207 alvherre                 1600 GIC         198 :     PG_RETURN_TEXT_P(string_to_text(res));
                               1601                 : }
 2207 alvherre                 1602 ECB             : 
                               1603                 : /*
                               1604                 :  * Internal workhorse to decompile an extended statistics object.
 2207 alvherre                 1605 EUB             :  */
                               1606                 : static char *
  744 tomas.vondra             1607 CBC         339 : pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
                               1608                 : {
                               1609                 :     Form_pg_statistic_ext statextrec;
                               1610                 :     HeapTuple   statexttup;
                               1611                 :     StringInfoData buf;
                               1612                 :     int         colno;
                               1613                 :     char       *nsp;
 2195 simon                    1614 ECB             :     ArrayType  *arr;
                               1615                 :     char       *enabled;
                               1616                 :     Datum       datum;
                               1617                 :     bool        ndistinct_enabled;
                               1618                 :     bool        dependencies_enabled;
                               1619                 :     bool        mcv_enabled;
                               1620                 :     int         i;
                               1621                 :     List       *context;
                               1622                 :     ListCell   *lc;
  744 tomas.vondra             1623 GIC         339 :     List       *exprs = NIL;
                               1624                 :     bool        has_exprs;
                               1625                 :     int         ncolumns;
                               1626                 : 
 2207 alvherre                 1627             339 :     statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
                               1628                 : 
 2207 alvherre                 1629 CBC         339 :     if (!HeapTupleIsValid(statexttup))
                               1630                 :     {
 2207 alvherre                 1631 GIC           3 :         if (missing_ok)
                               1632               3 :             return NULL;
 2156 tgl                      1633 LBC           0 :         elog(ERROR, "cache lookup failed for statistics object %u", statextid);
                               1634                 :     }
 2207 alvherre                 1635 ECB             : 
                               1636                 :     /* has the statistics expressions? */
  744 tomas.vondra             1637 CBC         336 :     has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
 2207 alvherre                 1638 ECB             : 
  744 tomas.vondra             1639 GBC         336 :     statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
                               1640                 : 
                               1641                 :     /*
                               1642                 :      * Get the statistics expressions, if any.  (NOTE: we do not use the
  744 tomas.vondra             1643 ECB             :      * relcache versions of the expressions, because we want to display
                               1644                 :      * non-const-folded expressions.)
 2195 simon                    1645                 :      */
  744 tomas.vondra             1646 GIC         336 :     if (has_exprs)
                               1647                 :     {
                               1648                 :         Datum       exprsDatum;
                               1649                 :         char       *exprsString;
                               1650                 : 
   15 dgustafsson              1651 GNC          71 :         exprsDatum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
                               1652                 :                                             Anum_pg_statistic_ext_stxexprs);
  744 tomas.vondra             1653 GIC          71 :         exprsString = TextDatumGetCString(exprsDatum);
                               1654              71 :         exprs = (List *) stringToNode(exprsString);
  744 tomas.vondra             1655 CBC          71 :         pfree(exprsString);
                               1656                 :     }
  744 tomas.vondra             1657 ECB             :     else
  744 tomas.vondra             1658 CBC         265 :         exprs = NIL;
 2195 simon                    1659 ECB             : 
                               1660                 :     /* count the number of columns (attributes and expressions) */
  744 tomas.vondra             1661 GIC         336 :     ncolumns = statextrec->stxkeys.dim1 + list_length(exprs);
 1474 tomas.vondra             1662 ECB             : 
  744 tomas.vondra             1663 GIC         336 :     initStringInfo(&buf);
                               1664                 : 
  744 tomas.vondra             1665 CBC         336 :     if (!columns_only)
                               1666                 :     {
  621 tgl                      1667             138 :         nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
  744 tomas.vondra             1668 GIC         138 :         appendStringInfo(&buf, "CREATE STATISTICS %s",
  744 tomas.vondra             1669 ECB             :                          quote_qualified_identifier(nsp,
  744 tomas.vondra             1670 GIC         138 :                                                     NameStr(statextrec->stxname)));
 1474 tomas.vondra             1671 ECB             : 
  744                          1672                 :         /*
                               1673                 :          * Decode the stxkind column so that we know which stats types to
                               1674                 :          * print.
                               1675                 :          */
   15 dgustafsson              1676 GNC         138 :         datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
                               1677                 :                                        Anum_pg_statistic_ext_stxkind);
  744 tomas.vondra             1678 GIC         138 :         arr = DatumGetArrayTypeP(datum);
  744 tomas.vondra             1679 CBC         138 :         if (ARR_NDIM(arr) != 1 ||
  744 tomas.vondra             1680 GIC         138 :             ARR_HASNULL(arr) ||
  744 tomas.vondra             1681 CBC         138 :             ARR_ELEMTYPE(arr) != CHAROID)
  744 tomas.vondra             1682 LBC           0 :             elog(ERROR, "stxkind is not a 1-D char array");
  744 tomas.vondra             1683 CBC         138 :         enabled = (char *) ARR_DATA_PTR(arr);
  744 tomas.vondra             1684 ECB             : 
  744 tomas.vondra             1685 GBC         138 :         ndistinct_enabled = false;
  744 tomas.vondra             1686 CBC         138 :         dependencies_enabled = false;
  744 tomas.vondra             1687 GIC         138 :         mcv_enabled = false;
  744 tomas.vondra             1688 ECB             : 
  744 tomas.vondra             1689 CBC         359 :         for (i = 0; i < ARR_DIMS(arr)[0]; i++)
 1474 tomas.vondra             1690 ECB             :         {
  744 tomas.vondra             1691 GIC         221 :             if (enabled[i] == STATS_EXT_NDISTINCT)
  744 tomas.vondra             1692 CBC          75 :                 ndistinct_enabled = true;
  744 tomas.vondra             1693 GIC         146 :             else if (enabled[i] == STATS_EXT_DEPENDENCIES)
  744 tomas.vondra             1694 CBC          48 :                 dependencies_enabled = true;
                               1695              98 :             else if (enabled[i] == STATS_EXT_MCV)
                               1696              57 :                 mcv_enabled = true;
  744 tomas.vondra             1697 ECB             : 
                               1698                 :             /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */
 1474                          1699                 :         }
                               1700                 : 
                               1701                 :         /*
                               1702                 :          * If any option is disabled, then we'll need to append the types
                               1703                 :          * clause to show which options are enabled.  We omit the types clause
                               1704                 :          * on purpose when all options are enabled, so a pg_dump/pg_restore
                               1705                 :          * will create all statistics types on a newer postgres version, if
                               1706                 :          * the statistics had all options enabled on the original version.
                               1707                 :          *
                               1708                 :          * But if the statistics is defined on just a single column, it has to
                               1709                 :          * be an expression statistics. In that case we don't need to specify
                               1710                 :          * kinds.
                               1711                 :          */
  744 tomas.vondra             1712 GIC         138 :         if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) &&
                               1713                 :             (ncolumns > 1))
                               1714                 :         {
  744 tomas.vondra             1715 CBC          63 :             bool        gotone = false;
                               1716                 : 
  744 tomas.vondra             1717 GIC          63 :             appendStringInfoString(&buf, " (");
 1474 tomas.vondra             1718 ECB             : 
  744 tomas.vondra             1719 GIC          63 :             if (ndistinct_enabled)
  744 tomas.vondra             1720 ECB             :             {
  744 tomas.vondra             1721 GIC          36 :                 appendStringInfoString(&buf, "ndistinct");
  744 tomas.vondra             1722 CBC          36 :                 gotone = true;
                               1723                 :             }
 2195 simon                    1724 ECB             : 
  744 tomas.vondra             1725 CBC          63 :             if (dependencies_enabled)
                               1726                 :             {
  744 tomas.vondra             1727 GIC           9 :                 appendStringInfo(&buf, "%sdependencies", gotone ? ", " : "");
  744 tomas.vondra             1728 CBC           9 :                 gotone = true;
                               1729                 :             }
  744 tomas.vondra             1730 ECB             : 
  744 tomas.vondra             1731 CBC          63 :             if (mcv_enabled)
  744 tomas.vondra             1732 GIC          18 :                 appendStringInfo(&buf, "%smcv", gotone ? ", " : "");
                               1733                 : 
  744 tomas.vondra             1734 CBC          63 :             appendStringInfoChar(&buf, ')');
  744 tomas.vondra             1735 ECB             :         }
                               1736                 : 
  744 tomas.vondra             1737 CBC         138 :         appendStringInfoString(&buf, " ON ");
                               1738                 :     }
                               1739                 : 
  744 tomas.vondra             1740 ECB             :     /* decode simple column references */
 2183 alvherre                 1741 GIC         956 :     for (colno = 0; colno < statextrec->stxkeys.dim1; colno++)
                               1742                 :     {
                               1743             620 :         AttrNumber  attnum = statextrec->stxkeys.values[colno];
 2207 alvherre                 1744 ECB             :         char       *attname;
                               1745                 : 
 2207 alvherre                 1746 CBC         620 :         if (colno > 0)
 2207 alvherre                 1747 GIC         349 :             appendStringInfoString(&buf, ", ");
                               1748                 : 
 1882 alvherre                 1749 CBC         620 :         attname = get_attname(statextrec->stxrelid, attnum, false);
 2207 alvherre                 1750 ECB             : 
 2207 alvherre                 1751 GIC         620 :         appendStringInfoString(&buf, quote_identifier(attname));
 2207 alvherre                 1752 ECB             :     }
                               1753                 : 
  744 tomas.vondra             1754 CBC         336 :     context = deparse_context_for(get_relation_name(statextrec->stxrelid),
                               1755                 :                                   statextrec->stxrelid);
                               1756                 : 
                               1757             450 :     foreach(lc, exprs)
                               1758                 :     {
  744 tomas.vondra             1759 GIC         114 :         Node       *expr = (Node *) lfirst(lc);
  744 tomas.vondra             1760 ECB             :         char       *str;
  585 tomas.vondra             1761 GIC         114 :         int         prettyFlags = PRETTYFLAG_PAREN;
  744 tomas.vondra             1762 ECB             : 
  744 tomas.vondra             1763 GIC         114 :         str = deparse_expression_pretty(expr, context, false, false,
  744 tomas.vondra             1764 ECB             :                                         prettyFlags, 0);
                               1765                 : 
  744 tomas.vondra             1766 CBC         114 :         if (colno > 0)
  744 tomas.vondra             1767 GIC          49 :             appendStringInfoString(&buf, ", ");
                               1768                 : 
  744 tomas.vondra             1769 ECB             :         /* Need parens if it's not a bare function call */
  744 tomas.vondra             1770 CBC         114 :         if (looks_like_function(expr))
  744 tomas.vondra             1771 GIC          17 :             appendStringInfoString(&buf, str);
                               1772                 :         else
  744 tomas.vondra             1773 CBC          97 :             appendStringInfo(&buf, "(%s)", str);
  744 tomas.vondra             1774 ECB             : 
  744 tomas.vondra             1775 GIC         114 :         colno++;
  744 tomas.vondra             1776 ECB             :     }
                               1777                 : 
  744 tomas.vondra             1778 CBC         336 :     if (!columns_only)
  744 tomas.vondra             1779 GIC         138 :         appendStringInfo(&buf, " FROM %s",
                               1780                 :                          generate_relation_name(statextrec->stxrelid, NIL));
 2207 alvherre                 1781 ECB             : 
 2207 alvherre                 1782 CBC         336 :     ReleaseSysCache(statexttup);
                               1783                 : 
 2207 alvherre                 1784 GIC         336 :     return buf.data;
 2207 alvherre                 1785 ECB             : }
                               1786                 : 
  744 tomas.vondra             1787                 : /*
                               1788                 :  * Generate text array of expressions for statistics object.
                               1789                 :  */
                               1790                 : Datum
  744 tomas.vondra             1791 UIC           0 : pg_get_statisticsobjdef_expressions(PG_FUNCTION_ARGS)
                               1792                 : {
                               1793               0 :     Oid         statextid = PG_GETARG_OID(0);
  744 tomas.vondra             1794 EUB             :     Form_pg_statistic_ext statextrec;
                               1795                 :     HeapTuple   statexttup;
                               1796                 :     Datum       datum;
                               1797                 :     List       *context;
                               1798                 :     ListCell   *lc;
  744 tomas.vondra             1799 UIC           0 :     List       *exprs = NIL;
                               1800                 :     bool        has_exprs;
  744 tomas.vondra             1801 EUB             :     char       *tmp;
  744 tomas.vondra             1802 UIC           0 :     ArrayBuildState *astate = NULL;
                               1803                 : 
  744 tomas.vondra             1804 UBC           0 :     statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid));
                               1805                 : 
                               1806               0 :     if (!HeapTupleIsValid(statexttup))
  702 tomas.vondra             1807 UIC           0 :         PG_RETURN_NULL();
  744 tomas.vondra             1808 EUB             : 
  702                          1809                 :     /* Does the stats object have expressions? */
  744 tomas.vondra             1810 UIC           0 :     has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL);
                               1811                 : 
  744 tomas.vondra             1812 EUB             :     /* no expressions? we're done */
  744 tomas.vondra             1813 UIC           0 :     if (!has_exprs)
                               1814                 :     {
  744 tomas.vondra             1815 UBC           0 :         ReleaseSysCache(statexttup);
  744 tomas.vondra             1816 UIC           0 :         PG_RETURN_NULL();
  744 tomas.vondra             1817 EUB             :     }
                               1818                 : 
  744 tomas.vondra             1819 UIC           0 :     statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
                               1820                 : 
  744 tomas.vondra             1821 EUB             :     /*
                               1822                 :      * Get the statistics expressions, and deparse them into text values.
                               1823                 :      */
   15 dgustafsson              1824 UNC           0 :     datum = SysCacheGetAttrNotNull(STATEXTOID, statexttup,
                               1825                 :                                    Anum_pg_statistic_ext_stxexprs);
  744 tomas.vondra             1826 UBC           0 :     tmp = TextDatumGetCString(datum);
                               1827               0 :     exprs = (List *) stringToNode(tmp);
                               1828               0 :     pfree(tmp);
                               1829                 : 
                               1830               0 :     context = deparse_context_for(get_relation_name(statextrec->stxrelid),
                               1831                 :                                   statextrec->stxrelid);
                               1832                 : 
                               1833               0 :     foreach(lc, exprs)
                               1834                 :     {
                               1835               0 :         Node       *expr = (Node *) lfirst(lc);
                               1836                 :         char       *str;
                               1837               0 :         int         prettyFlags = PRETTYFLAG_INDENT;
                               1838                 : 
                               1839               0 :         str = deparse_expression_pretty(expr, context, false, false,
                               1840                 :                                         prettyFlags, 0);
                               1841                 : 
                               1842               0 :         astate = accumArrayResult(astate,
                               1843               0 :                                   PointerGetDatum(cstring_to_text(str)),
                               1844                 :                                   false,
                               1845                 :                                   TEXTOID,
                               1846                 :                                   CurrentMemoryContext);
                               1847                 :     }
                               1848                 : 
                               1849               0 :     ReleaseSysCache(statexttup);
                               1850                 : 
                               1851               0 :     PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
                               1852                 : }
                               1853                 : 
                               1854                 : /*
                               1855                 :  * pg_get_partkeydef
                               1856                 :  *
                               1857                 :  * Returns the partition key specification, ie, the following:
                               1858                 :  *
                               1859                 :  * { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...])
                               1860                 :  */
                               1861                 : Datum
 2314 rhaas                    1862 CBC         586 : pg_get_partkeydef(PG_FUNCTION_ARGS)
                               1863                 : {
                               1864             586 :     Oid         relid = PG_GETARG_OID(0);
                               1865                 :     char       *res;
                               1866                 : 
 2174 sfrost                   1867             586 :     res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true);
                               1868                 : 
                               1869             586 :     if (res == NULL)
                               1870               3 :         PG_RETURN_NULL();
                               1871                 : 
                               1872             583 :     PG_RETURN_TEXT_P(string_to_text(res));
                               1873                 : }
                               1874                 : 
                               1875                 : /* Internal version that just reports the column definitions */
                               1876                 : char *
 2228 rhaas                    1877              68 : pg_get_partkeydef_columns(Oid relid, bool pretty)
                               1878                 : {
                               1879                 :     int         prettyFlags;
                               1880                 : 
  377 tgl                      1881              68 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                               1882                 : 
 2174 sfrost                   1883              68 :     return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
                               1884                 : }
                               1885                 : 
                               1886                 : /*
                               1887                 :  * Internal workhorse to decompile a partition key definition.
                               1888                 :  */
                               1889                 : static char *
 2228 rhaas                    1890             654 : pg_get_partkeydef_worker(Oid relid, int prettyFlags,
                               1891                 :                          bool attrsOnly, bool missing_ok)
                               1892                 : {
                               1893                 :     Form_pg_partitioned_table form;
                               1894                 :     HeapTuple   tuple;
                               1895                 :     oidvector  *partclass;
                               1896                 :     oidvector  *partcollation;
                               1897                 :     List       *partexprs;
                               1898                 :     ListCell   *partexpr_item;
                               1899                 :     List       *context;
                               1900                 :     Datum       datum;
                               1901                 :     StringInfoData buf;
                               1902                 :     int         keyno;
                               1903                 :     char       *str;
                               1904                 :     char       *sep;
 2314 rhaas                    1905 ECB             : 
 2314 rhaas                    1906 CBC         654 :     tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
 2314 rhaas                    1907 GIC         654 :     if (!HeapTupleIsValid(tuple))
 2174 sfrost                   1908 ECB             :     {
 2174 sfrost                   1909 CBC           3 :         if (missing_ok)
 2174 sfrost                   1910 GBC           3 :             return NULL;
 2314 rhaas                    1911 UIC           0 :         elog(ERROR, "cache lookup failed for partition key of %u", relid);
                               1912                 :     }
 2314 rhaas                    1913 ECB             : 
 2314 rhaas                    1914 GIC         651 :     form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
 2314 rhaas                    1915 ECB             : 
 2314 rhaas                    1916 GIC         651 :     Assert(form->partrelid == relid);
                               1917                 : 
 2314 rhaas                    1918 ECB             :     /* Must get partclass and partcollation the hard way */
   15 dgustafsson              1919 GNC         651 :     datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
                               1920                 :                                    Anum_pg_partitioned_table_partclass);
 2314 rhaas                    1921 CBC         651 :     partclass = (oidvector *) DatumGetPointer(datum);
                               1922                 : 
   15 dgustafsson              1923 GNC         651 :     datum = SysCacheGetAttrNotNull(PARTRELID, tuple,
                               1924                 :                                    Anum_pg_partitioned_table_partcollation);
 2314 rhaas                    1925 GIC         651 :     partcollation = (oidvector *) DatumGetPointer(datum);
                               1926                 : 
                               1927                 : 
                               1928                 :     /*
                               1929                 :      * Get the expressions, if any.  (NOTE: we do not use the relcache
 2266 rhaas                    1930 ECB             :      * versions of the expressions, because we want to display
                               1931                 :      * non-const-folded expressions.)
                               1932                 :      */
 1838 andrew                   1933 GIC         651 :     if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL))
                               1934                 :     {
 2314 rhaas                    1935 ECB             :         Datum       exprsDatum;
                               1936                 :         char       *exprsString;
                               1937                 : 
   15 dgustafsson              1938 GNC          73 :         exprsDatum = SysCacheGetAttrNotNull(PARTRELID, tuple,
                               1939                 :                                             Anum_pg_partitioned_table_partexprs);
 2314 rhaas                    1940 GIC          73 :         exprsString = TextDatumGetCString(exprsDatum);
                               1941              73 :         partexprs = (List *) stringToNode(exprsString);
 2314 rhaas                    1942 ECB             : 
 2314 rhaas                    1943 GIC          73 :         if (!IsA(partexprs, List))
 2314 rhaas                    1944 UIC           0 :             elog(ERROR, "unexpected node type found in partexprs: %d",
 2266 rhaas                    1945 ECB             :                  (int) nodeTag(partexprs));
                               1946                 : 
 2314 rhaas                    1947 CBC          73 :         pfree(exprsString);
 2314 rhaas                    1948 ECB             :     }
                               1949                 :     else
 2314 rhaas                    1950 CBC         578 :         partexprs = NIL;
                               1951                 : 
                               1952             651 :     partexpr_item = list_head(partexprs);
 2314 rhaas                    1953 GIC         651 :     context = deparse_context_for(get_relation_name(relid), relid);
 2314 rhaas                    1954 ECB             : 
 2314 rhaas                    1955 CBC         651 :     initStringInfo(&buf);
 2314 rhaas                    1956 ECB             : 
 2314 rhaas                    1957 CBC         651 :     switch (form->partstrat)
 2314 rhaas                    1958 ECB             :     {
 1977 rhaas                    1959 CBC          27 :         case PARTITION_STRATEGY_HASH:
                               1960              27 :             if (!attrsOnly)
 1375 drowley                  1961              27 :                 appendStringInfoString(&buf, "HASH");
 1977 rhaas                    1962              27 :             break;
 2314                          1963             220 :         case PARTITION_STRATEGY_LIST:
 2228                          1964             220 :             if (!attrsOnly)
 2063 peter_e                  1965             200 :                 appendStringInfoString(&buf, "LIST");
 2314 rhaas                    1966 GBC         220 :             break;
                               1967             404 :         case PARTITION_STRATEGY_RANGE:
 2228 rhaas                    1968 GIC         404 :             if (!attrsOnly)
 2063 peter_e                  1969             356 :                 appendStringInfoString(&buf, "RANGE");
 2314 rhaas                    1970             404 :             break;
 2314 rhaas                    1971 LBC           0 :         default:
                               1972               0 :             elog(ERROR, "unexpected partition strategy: %d",
 2266 rhaas                    1973 ECB             :                  (int) form->partstrat);
 2314                          1974                 :     }
                               1975                 : 
 2228 rhaas                    1976 CBC         651 :     if (!attrsOnly)
 2063 peter_e                  1977 GIC         583 :         appendStringInfoString(&buf, " (");
 2314 rhaas                    1978             651 :     sep = "";
                               1979            1378 :     for (keyno = 0; keyno < form->partnatts; keyno++)
                               1980                 :     {
 2314 rhaas                    1981 CBC         727 :         AttrNumber  attnum = form->partattrs.values[keyno];
 2314 rhaas                    1982 ECB             :         Oid         keycoltype;
                               1983                 :         Oid         keycolcollation;
                               1984                 :         Oid         partcoll;
                               1985                 : 
 2314 rhaas                    1986 GIC         727 :         appendStringInfoString(&buf, sep);
                               1987             727 :         sep = ", ";
                               1988             727 :         if (attnum != 0)
 2314 rhaas                    1989 ECB             :         {
                               1990                 :             /* Simple attribute reference */
                               1991                 :             char       *attname;
                               1992                 :             int32       keycoltypmod;
                               1993                 : 
 1882 alvherre                 1994 GIC         648 :             attname = get_attname(relid, attnum, false);
 2314 rhaas                    1995             648 :             appendStringInfoString(&buf, quote_identifier(attname));
                               1996             648 :             get_atttypetypmodcoll(relid, attnum,
                               1997                 :                                   &keycoltype, &keycoltypmod,
                               1998                 :                                   &keycolcollation);
                               1999                 :         }
 2314 rhaas                    2000 ECB             :         else
 2314 rhaas                    2001 EUB             :         {
 2314 rhaas                    2002 ECB             :             /* Expression */
                               2003                 :             Node       *partkey;
                               2004                 : 
 2314 rhaas                    2005 GIC          79 :             if (partexpr_item == NULL)
 2314 rhaas                    2006 LBC           0 :                 elog(ERROR, "too few entries in partexprs list");
 2314 rhaas                    2007 GIC          79 :             partkey = (Node *) lfirst(partexpr_item);
 1364 tgl                      2008              79 :             partexpr_item = lnext(partexprs, partexpr_item);
 2096 tgl                      2009 ECB             : 
 2314 rhaas                    2010                 :             /* Deparse */
 2314 rhaas                    2011 GIC          79 :             str = deparse_expression_pretty(partkey, context, false, false,
 2096 tgl                      2012 ECB             :                                             prettyFlags, 0);
                               2013                 :             /* Need parens if it's not a bare function call */
 2096 tgl                      2014 CBC          79 :             if (looks_like_function(partkey))
                               2015              28 :                 appendStringInfoString(&buf, str);
                               2016                 :             else
 2096 tgl                      2017 GIC          51 :                 appendStringInfo(&buf, "(%s)", str);
                               2018                 : 
 2314 rhaas                    2019 CBC          79 :             keycoltype = exprType(partkey);
                               2020              79 :             keycolcollation = exprCollation(partkey);
 2314 rhaas                    2021 ECB             :         }
                               2022                 : 
                               2023                 :         /* Add collation, if not default for column */
 2314 rhaas                    2024 GIC         727 :         partcoll = partcollation->values[keyno];
 2228 rhaas                    2025 CBC         727 :         if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation)
 2314                          2026               3 :             appendStringInfo(&buf, " COLLATE %s",
                               2027                 :                              generate_collation_name((partcoll)));
                               2028                 : 
 2314 rhaas                    2029 ECB             :         /* Add the operator class name, if not default */
 2228 rhaas                    2030 CBC         727 :         if (!attrsOnly)
 2228 rhaas                    2031 GIC         632 :             get_opclass_name(partclass->values[keyno], keycoltype, &buf);
                               2032                 :     }
 2228 rhaas                    2033 ECB             : 
 2228 rhaas                    2034 GIC         651 :     if (!attrsOnly)
 2228 rhaas                    2035 CBC         583 :         appendStringInfoChar(&buf, ')');
                               2036                 : 
                               2037                 :     /* Clean up */
 2314 rhaas                    2038 GIC         651 :     ReleaseSysCache(tuple);
                               2039                 : 
                               2040             651 :     return buf.data;
                               2041                 : }
                               2042                 : 
                               2043                 : /*
 2157 rhaas                    2044 ECB             :  * pg_get_partition_constraintdef
                               2045                 :  *
                               2046                 :  * Returns partition constraint expression as a string for the input relation
                               2047                 :  */
                               2048                 : Datum
 2157 rhaas                    2049 GIC          78 : pg_get_partition_constraintdef(PG_FUNCTION_ARGS)
                               2050                 : {
 2153 bruce                    2051              78 :     Oid         relationId = PG_GETARG_OID(0);
 2153 bruce                    2052 ECB             :     Expr       *constr_expr;
                               2053                 :     int         prettyFlags;
                               2054                 :     List       *context;
                               2055                 :     char       *consrc;
 2157 rhaas                    2056                 : 
 2157 rhaas                    2057 GIC          78 :     constr_expr = get_partition_qual_relid(relationId);
                               2058                 : 
                               2059                 :     /* Quick exit if no partition constraint */
                               2060              78 :     if (constr_expr == NULL)
 2157 rhaas                    2061 CBC           9 :         PG_RETURN_NULL();
 2157 rhaas                    2062 ECB             : 
                               2063                 :     /*
                               2064                 :      * Deparse and return the constraint expression.
                               2065                 :      */
 2157 rhaas                    2066 CBC          69 :     prettyFlags = PRETTYFLAG_INDENT;
 2157 rhaas                    2067 GIC          69 :     context = deparse_context_for(get_relation_name(relationId), relationId);
                               2068              69 :     consrc = deparse_expression_pretty((Node *) constr_expr, context, false,
                               2069                 :                                        false, prettyFlags, 0);
                               2070                 : 
                               2071              69 :     PG_RETURN_TEXT_P(string_to_text(consrc));
                               2072                 : }
                               2073                 : 
                               2074                 : /*
                               2075                 :  * pg_get_partconstrdef_string
 1467 alvherre                 2076 ECB             :  *
                               2077                 :  * Returns the partition constraint as a C-string for the input relation, with
                               2078                 :  * the given alias.  No pretty-printing.
                               2079                 :  */
                               2080                 : char *
 1467 alvherre                 2081 CBC          43 : pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
 1467 alvherre                 2082 ECB             : {
                               2083                 :     Expr       *constr_expr;
                               2084                 :     List       *context;
                               2085                 : 
 1467 alvherre                 2086 GIC          43 :     constr_expr = get_partition_qual_relid(partitionId);
                               2087              43 :     context = deparse_context_for(aliasname, partitionId);
                               2088                 : 
                               2089              43 :     return deparse_expression((Node *) constr_expr, context, true, false);
                               2090                 : }
                               2091                 : 
                               2092                 : /*
                               2093                 :  * pg_get_constraintdef
 7541 tgl                      2094 ECB             :  *
                               2095                 :  * Returns the definition for the constraint, ie, everything that needs to
                               2096                 :  * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
                               2097                 :  */
                               2098                 : Datum
 7541 tgl                      2099 GIC         843 : pg_get_constraintdef(PG_FUNCTION_ARGS)
 7541 tgl                      2100 ECB             : {
 7522 bruce                    2101 GIC         843 :     Oid         constraintId = PG_GETARG_OID(0);
 3717 tgl                      2102 ECB             :     int         prettyFlags;
                               2103                 :     char       *res;
 7193                          2104                 : 
 3717 tgl                      2105 CBC         843 :     prettyFlags = PRETTYFLAG_INDENT;
                               2106                 : 
 2448 rhaas                    2107             843 :     res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
                               2108                 : 
 2448 rhaas                    2109 GIC         843 :     if (res == NULL)
                               2110               3 :         PG_RETURN_NULL();
 2448 rhaas                    2111 ECB             : 
 2448 rhaas                    2112 GIC         840 :     PG_RETURN_TEXT_P(string_to_text(res));
 7193 tgl                      2113 ECB             : }
                               2114                 : 
                               2115                 : Datum
 7193 tgl                      2116 GIC        1521 : pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
                               2117                 : {
 7193 tgl                      2118 CBC        1521 :     Oid         constraintId = PG_GETARG_OID(0);
 7193 tgl                      2119 GIC        1521 :     bool        pretty = PG_GETARG_BOOL(1);
 7193 tgl                      2120 ECB             :     int         prettyFlags;
                               2121                 :     char       *res;
                               2122                 : 
  377 tgl                      2123 GBC        1521 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                               2124                 : 
 2448 rhaas                    2125 CBC        1521 :     res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true);
                               2126                 : 
 2448 rhaas                    2127 GIC        1521 :     if (res == NULL)
 2448 rhaas                    2128 UIC           0 :         PG_RETURN_NULL();
                               2129                 : 
 2448 rhaas                    2130 GIC        1521 :     PG_RETURN_TEXT_P(string_to_text(res));
                               2131                 : }
 7193 tgl                      2132 ECB             : 
                               2133                 : /*
 2697                          2134                 :  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
                               2135                 :  */
                               2136                 : char *
 2697 tgl                      2137 GIC         202 : pg_get_constraintdef_command(Oid constraintId)
                               2138                 : {
 2448 rhaas                    2139             202 :     return pg_get_constraintdef_worker(constraintId, true, 0, false);
                               2140                 : }
 7193 tgl                      2141 ECB             : 
                               2142                 : /*
                               2143                 :  * As of 9.4, we now use an MVCC snapshot for this.
                               2144                 :  */
                               2145                 : static char *
 6913 tgl                      2146 GIC        2566 : pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                               2147                 :                             int prettyFlags, bool missing_ok)
                               2148                 : {
 7522 bruce                    2149 ECB             :     HeapTuple   tup;
                               2150                 :     Form_pg_constraint conForm;
                               2151                 :     StringInfoData buf;
 3260                          2152                 :     SysScanDesc scandesc;
                               2153                 :     ScanKeyData scankey[1];
 3260 bruce                    2154 GIC        2566 :     Snapshot    snapshot = RegisterSnapshot(GetTransactionSnapshot());
 1539 andres                   2155            2566 :     Relation    relation = table_open(ConstraintRelationId, AccessShareLock);
                               2156                 : 
 3290 simon                    2157 CBC        2566 :     ScanKeyInit(&scankey[0],
                               2158                 :                 Anum_pg_constraint_oid,
                               2159                 :                 BTEqualStrategyNumber, F_OIDEQ,
                               2160                 :                 ObjectIdGetDatum(constraintId));
                               2161                 : 
 3290 simon                    2162 GIC        2566 :     scandesc = systable_beginscan(relation,
                               2163                 :                                   ConstraintOidIndexId,
                               2164                 :                                   true,
                               2165                 :                                   snapshot,
                               2166                 :                                   1,
                               2167                 :                                   scankey);
 3290 simon                    2168 ECB             : 
                               2169                 :     /*
 3260 bruce                    2170                 :      * We later use the tuple with SysCacheGetAttr() as if we had obtained it
                               2171                 :      * via SearchSysCache, which works fine.
 3290 simon                    2172                 :      */
 3290 simon                    2173 GIC        2566 :     tup = systable_getnext(scandesc);
 3290 simon                    2174 ECB             : 
 3290 simon                    2175 GIC        2566 :     UnregisterSnapshot(snapshot);
 7541 tgl                      2176 ECB             : 
 2448 rhaas                    2177 CBC        2566 :     if (!HeapTupleIsValid(tup))
 2448 rhaas                    2178 ECB             :     {
 2448 rhaas                    2179 GIC           3 :         if (missing_ok)
 2448 rhaas                    2180 EUB             :         {
 2448 rhaas                    2181 GIC           3 :             systable_endscan(scandesc);
 1539 andres                   2182               3 :             table_close(relation, AccessShareLock);
 2448 rhaas                    2183 CBC           3 :             return NULL;
                               2184                 :         }
 2135 tgl                      2185 LBC           0 :         elog(ERROR, "could not find tuple for constraint %u", constraintId);
                               2186                 :     }
 3290 simon                    2187 ECB             : 
 7541 tgl                      2188 GIC        2563 :     conForm = (Form_pg_constraint) GETSTRUCT(tup);
 7541 tgl                      2189 ECB             : 
 7541 tgl                      2190 GIC        2563 :     initStringInfo(&buf);
                               2191                 : 
 2697                          2192            2563 :     if (fullCommand)
                               2193                 :     {
 1985                          2194             202 :         if (OidIsValid(conForm->conrelid))
                               2195                 :         {
                               2196                 :             /*
                               2197                 :              * Currently, callers want ALTER TABLE (without ONLY) for CHECK
 1985 tgl                      2198 ECB             :              * constraints, and other types of constraints don't inherit
                               2199                 :              * anyway so it doesn't matter whether we say ONLY or not. Someday
                               2200                 :              * we might need to let callers specify whether to put ONLY in the
                               2201                 :              * command.
                               2202                 :              */
 1985 tgl                      2203 GIC         195 :             appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ",
                               2204                 :                              generate_qualified_relation_name(conForm->conrelid),
 1985 tgl                      2205 CBC         195 :                              quote_identifier(NameStr(conForm->conname)));
 1985 tgl                      2206 ECB             :         }
                               2207                 :         else
                               2208                 :         {
                               2209                 :             /* Must be a domain constraint */
 1985 tgl                      2210 GIC           7 :             Assert(OidIsValid(conForm->contypid));
                               2211               7 :             appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ",
 1985 tgl                      2212 ECB             :                              generate_qualified_type_name(conForm->contypid),
 1985 tgl                      2213 GIC           7 :                              quote_identifier(NameStr(conForm->conname)));
 1985 tgl                      2214 ECB             :         }
                               2215                 :     }
                               2216                 : 
 7541 tgl                      2217 GIC        2563 :     switch (conForm->contype)
                               2218                 :     {
                               2219             314 :         case CONSTRAINT_FOREIGN:
                               2220                 :             {
 7522 bruce                    2221 ECB             :                 Datum       val;
                               2222                 :                 bool        isnull;
                               2223                 :                 const char *string;
 7541 tgl                      2224                 : 
                               2225                 :                 /* Start off the constraint definition */
 3447 rhaas                    2226 GIC         314 :                 appendStringInfoString(&buf, "FOREIGN KEY (");
 7541 tgl                      2227 ECB             : 
                               2228                 :                 /* Fetch and build referencing-column list */
   15 dgustafsson              2229 GNC         314 :                 val = SysCacheGetAttrNotNull(CONSTROID, tup,
                               2230                 :                                              Anum_pg_constraint_conkey);
                               2231                 : 
 7522 bruce                    2232 CBC         314 :                 decompile_column_index_array(val, conForm->conrelid, &buf);
                               2233                 : 
                               2234                 :                 /* add foreign relation name */
                               2235             314 :                 appendStringInfo(&buf, ") REFERENCES %s(",
                               2236                 :                                  generate_relation_name(conForm->confrelid,
 5298 tgl                      2237 ECB             :                                                         NIL));
                               2238                 : 
                               2239                 :                 /* Fetch and build referenced-column list */
   15 dgustafsson              2240 GNC         314 :                 val = SysCacheGetAttrNotNull(CONSTROID, tup,
                               2241                 :                                              Anum_pg_constraint_confkey);
 7541 tgl                      2242 EUB             : 
 7522 bruce                    2243 GBC         314 :                 decompile_column_index_array(val, conForm->confrelid, &buf);
 7541 tgl                      2244 EUB             : 
 3447 rhaas                    2245 CBC         314 :                 appendStringInfoChar(&buf, ')');
 7541 tgl                      2246 ECB             : 
 7522 bruce                    2247                 :                 /* Add match type */
 7522 bruce                    2248 GBC         314 :                 switch (conForm->confmatchtype)
 7522 bruce                    2249 EUB             :                 {
 7522 bruce                    2250 GIC          17 :                     case FKCONSTR_MATCH_FULL:
                               2251              17 :                         string = " MATCH FULL";
                               2252              17 :                         break;
 7522 bruce                    2253 UIC           0 :                     case FKCONSTR_MATCH_PARTIAL:
 7522 bruce                    2254 LBC           0 :                         string = " MATCH PARTIAL";
 7522 bruce                    2255 UIC           0 :                         break;
 3948 tgl                      2256 GIC         297 :                     case FKCONSTR_MATCH_SIMPLE:
 7522 bruce                    2257 CBC         297 :                         string = "";
 7522 bruce                    2258 GIC         297 :                         break;
 7522 bruce                    2259 LBC           0 :                     default:
 7196 tgl                      2260               0 :                         elog(ERROR, "unrecognized confmatchtype: %d",
 7196 tgl                      2261 ECB             :                              conForm->confmatchtype);
 7522 bruce                    2262 EUB             :                         string = "";  /* keep compiler quiet */
                               2263                 :                         break;
                               2264                 :                 }
 7008 neilc                    2265 CBC         314 :                 appendStringInfoString(&buf, string);
 7541 tgl                      2266 ECB             : 
 7370                          2267                 :                 /* Add ON UPDATE and ON DELETE clauses, if needed */
 7522 bruce                    2268 CBC         314 :                 switch (conForm->confupdtype)
 7522 bruce                    2269 ECB             :                 {
 7522 bruce                    2270 CBC         252 :                     case FKCONSTR_ACTION_NOACTION:
 7188 bruce                    2271 GBC         252 :                         string = NULL;  /* suppress default */
 7522                          2272             252 :                         break;
 7522 bruce                    2273 UBC           0 :                     case FKCONSTR_ACTION_RESTRICT:
                               2274               0 :                         string = "RESTRICT";
                               2275               0 :                         break;
 7522 bruce                    2276 GIC          48 :                     case FKCONSTR_ACTION_CASCADE:
                               2277              48 :                         string = "CASCADE";
                               2278              48 :                         break;
                               2279              14 :                     case FKCONSTR_ACTION_SETNULL:
 7522 bruce                    2280 CBC          14 :                         string = "SET NULL";
                               2281              14 :                         break;
 7522 bruce                    2282 UIC           0 :                     case FKCONSTR_ACTION_SETDEFAULT:
 7522 bruce                    2283 LBC           0 :                         string = "SET DEFAULT";
 7522 bruce                    2284 UIC           0 :                         break;
 7522 bruce                    2285 LBC           0 :                     default:
 7196 tgl                      2286               0 :                         elog(ERROR, "unrecognized confupdtype: %d",
 7196 tgl                      2287 ECB             :                              conForm->confupdtype);
 7370 tgl                      2288 EUB             :                         string = NULL;  /* keep compiler quiet */
 7522 bruce                    2289                 :                         break;
                               2290                 :                 }
 7370 tgl                      2291 CBC         314 :                 if (string)
      bruce                    2292              62 :                     appendStringInfo(&buf, " ON UPDATE %s", string);
 7541 tgl                      2293 ECB             : 
 7522 bruce                    2294 CBC         314 :                 switch (conForm->confdeltype)
 7522 bruce                    2295 ECB             :                 {
 7522 bruce                    2296 CBC         254 :                     case FKCONSTR_ACTION_NOACTION:
 7188                          2297             254 :                         string = NULL;  /* suppress default */
 7522                          2298             254 :                         break;
 7522 bruce                    2299 LBC           0 :                     case FKCONSTR_ACTION_RESTRICT:
 7522 bruce                    2300 UBC           0 :                         string = "RESTRICT";
                               2301               0 :                         break;
 7522 bruce                    2302 GIC          48 :                     case FKCONSTR_ACTION_CASCADE:
                               2303              48 :                         string = "CASCADE";
                               2304              48 :                         break;
                               2305               9 :                     case FKCONSTR_ACTION_SETNULL:
 7522 bruce                    2306 CBC           9 :                         string = "SET NULL";
                               2307               9 :                         break;
 7522 bruce                    2308 GIC           3 :                     case FKCONSTR_ACTION_SETDEFAULT:
                               2309               3 :                         string = "SET DEFAULT";
                               2310               3 :                         break;
 7522 bruce                    2311 UIC           0 :                     default:
 7196 tgl                      2312               0 :                         elog(ERROR, "unrecognized confdeltype: %d",
 7196 tgl                      2313 ECB             :                              conForm->confdeltype);
                               2314                 :                         string = NULL;  /* keep compiler quiet */
 7522 bruce                    2315                 :                         break;
                               2316                 :                 }
 7370 tgl                      2317 CBC         314 :                 if (string)
      bruce                    2318              60 :                     appendStringInfo(&buf, " ON DELETE %s", string);
 7541 tgl                      2319 ECB             : 
                               2320                 :                 /*
                               2321                 :                  * Add columns specified to SET NULL or SET DEFAULT if
  332                          2322                 :                  * provided.
                               2323                 :                  */
  487 peter                    2324 CBC         314 :                 val = SysCacheGetAttr(CONSTROID, tup,
                               2325                 :                                       Anum_pg_constraint_confdelsetcols, &isnull);
  487 peter                    2326 GIC         314 :                 if (!isnull)
                               2327                 :                 {
  215 drowley                  2328 GNC           6 :                     appendStringInfoString(&buf, " (");
  487 peter                    2329 GIC           6 :                     decompile_column_index_array(val, conForm->conrelid, &buf);
  215 drowley                  2330 GNC           6 :                     appendStringInfoChar(&buf, ')');
                               2331                 :                 }
                               2332                 : 
 7522 bruce                    2333 CBC         314 :                 break;
 7522 bruce                    2334 ECB             :             }
 7360 bruce                    2335 GIC        1199 :         case CONSTRAINT_PRIMARY:
 7360 bruce                    2336 ECB             :         case CONSTRAINT_UNIQUE:
                               2337                 :             {
                               2338                 :                 Datum       val;
 5657 tgl                      2339                 :                 Oid         indexId;
 1679 alvherre                 2340                 :                 int         keyatts;
 1679 alvherre                 2341 EUB             :                 HeapTuple   indtup;
 7360 bruce                    2342 ECB             : 
                               2343                 :                 /* Start off the constraint definition */
 7360 bruce                    2344 GBC        1199 :                 if (conForm->contype == CONSTRAINT_PRIMARY)
  430 peter                    2345 GIC        1047 :                     appendStringInfoString(&buf, "PRIMARY KEY ");
 7360 bruce                    2346 ECB             :                 else
  430 peter                    2347 GIC         152 :                     appendStringInfoString(&buf, "UNIQUE ");
                               2348                 : 
  430 peter                    2349 CBC        1199 :                 indexId = conForm->conindid;
                               2350                 : 
  430 peter                    2351 GIC        1199 :                 indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
  430 peter                    2352 CBC        1199 :                 if (!HeapTupleIsValid(indtup))
  430 peter                    2353 UIC           0 :                     elog(ERROR, "cache lookup failed for index %u", indexId);
  430 peter                    2354 CBC        1199 :                 if (conForm->contype == CONSTRAINT_UNIQUE &&
  430 peter                    2355 GIC         152 :                     ((Form_pg_index) GETSTRUCT(indtup))->indnullsnotdistinct)
  430 peter                    2356 UIC           0 :                     appendStringInfoString(&buf, "NULLS NOT DISTINCT ");
  430 peter                    2357 ECB             : 
  215 drowley                  2358 GNC        1199 :                 appendStringInfoChar(&buf, '(');
 7360 bruce                    2359 ECB             : 
                               2360                 :                 /* Fetch and build target column list */
   15 dgustafsson              2361 GNC        1199 :                 val = SysCacheGetAttrNotNull(CONSTROID, tup,
                               2362                 :                                              Anum_pg_constraint_conkey);
 7360 bruce                    2363 ECB             : 
 1679 alvherre                 2364 GIC        1199 :                 keyatts = decompile_column_index_array(val, conForm->conrelid, &buf);
 7360 bruce                    2365 ECB             : 
 3447 rhaas                    2366 GIC        1199 :                 appendStringInfoChar(&buf, ')');
                               2367                 : 
 1679 alvherre                 2368 ECB             :                 /* Build including column list (from pg_index.indkeys) */
   15 dgustafsson              2369 GNC        1199 :                 val = SysCacheGetAttrNotNull(INDEXRELID, indtup,
                               2370                 :                                              Anum_pg_index_indnatts);
 1679 alvherre                 2371 GIC        1199 :                 if (DatumGetInt32(val) > keyatts)
                               2372                 :                 {
 1679 alvherre                 2373 ECB             :                     Datum       cols;
                               2374                 :                     Datum      *keys;
                               2375                 :                     int         nKeys;
                               2376                 :                     int         j;
                               2377                 : 
 1828 teodor                   2378 GIC          41 :                     appendStringInfoString(&buf, " INCLUDE (");
                               2379                 : 
   15 dgustafsson              2380 GNC          41 :                     cols = SysCacheGetAttrNotNull(INDEXRELID, indtup,
                               2381                 :                                                   Anum_pg_index_indkey);
                               2382                 : 
  282 peter                    2383              41 :                     deconstruct_array_builtin(DatumGetArrayTypeP(cols), INT2OID,
                               2384                 :                                               &keys, NULL, &nKeys);
                               2385                 : 
 1679 alvherre                 2386 GIC         123 :                     for (j = keyatts; j < nKeys; j++)
 1679 alvherre                 2387 ECB             :                     {
                               2388                 :                         char       *colName;
 1679 alvherre                 2389 EUB             : 
 1679 alvherre                 2390 GBC          82 :                         colName = get_attname(conForm->conrelid,
 1679 alvherre                 2391 GIC          82 :                                               DatumGetInt16(keys[j]), false);
                               2392              82 :                         if (j > keyatts)
                               2393              41 :                             appendStringInfoString(&buf, ", ");
                               2394              82 :                         appendStringInfoString(&buf, quote_identifier(colName));
                               2395                 :                     }
                               2396                 : 
 1828 teodor                   2397              41 :                     appendStringInfoChar(&buf, ')');
                               2398                 :                 }
 1679 alvherre                 2399 CBC        1199 :                 ReleaseSysCache(indtup);
 5657 tgl                      2400 ECB             : 
                               2401                 :                 /* XXX why do we only print these bits if fullCommand? */
 5657 tgl                      2402 CBC        1199 :                 if (fullCommand && OidIsValid(indexId))
                               2403                 :                 {
 5657 tgl                      2404 GIC          90 :                     char       *options = flatten_reloptions(indexId);
 5657 tgl                      2405 ECB             :                     Oid         tblspc;
                               2406                 : 
 6125 bruce                    2407 CBC          90 :                     if (options)
                               2408                 :                     {
 6125 bruce                    2409 UIC           0 :                         appendStringInfo(&buf, " WITH (%s)", options);
                               2410               0 :                         pfree(options);
                               2411                 :                     }
                               2412                 : 
                               2413                 :                     /*
                               2414                 :                      * Print the tablespace, unless it's the database default.
                               2415                 :                      * This is to help ALTER TABLE usage of this facility,
 1445 alvherre                 2416 ECB             :                      * which needs this behavior to recreate exact catalog
                               2417                 :                      * state.
                               2418                 :                      */
 5657 tgl                      2419 CBC          90 :                     tblspc = get_rel_tablespace(indexId);
                               2420              90 :                     if (OidIsValid(tblspc))
 5657 tgl                      2421 GIC          12 :                         appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
 2118                          2422              12 :                                          quote_identifier(get_tablespace_name(tblspc)));
 6125 bruce                    2423 ECB             :                 }
                               2424                 : 
 7360 bruce                    2425 GIC        1199 :                 break;
 7360 bruce                    2426 ECB             :             }
 7360 bruce                    2427 GIC         971 :         case CONSTRAINT_CHECK:
                               2428                 :             {
                               2429                 :                 Datum       val;
                               2430                 :                 char       *conbin;
 7228 bruce                    2431 ECB             :                 char       *consrc;
                               2432                 :                 Node       *expr;
                               2433                 :                 List       *context;
 7360                          2434                 : 
                               2435                 :                 /* Fetch constraint expression in parsetree form */
   15 dgustafsson              2436 GNC         971 :                 val = SysCacheGetAttrNotNull(CONSTROID, tup,
                               2437                 :                                              Anum_pg_constraint_conbin);
                               2438                 : 
 5493 tgl                      2439 GIC         971 :                 conbin = TextDatumGetCString(val);
 7228 bruce                    2440             971 :                 expr = stringToNode(conbin);
                               2441                 : 
                               2442                 :                 /* Set up deparsing context for Var nodes in constraint */
                               2443             971 :                 if (conForm->conrelid != InvalidOid)
                               2444                 :                 {
                               2445                 :                     /* relation constraint */
 4541 tgl                      2446 CBC         880 :                     context = deparse_context_for(get_relation_name(conForm->conrelid),
                               2447                 :                                                   conForm->conrelid);
 7127 tgl                      2448 ECB             :                 }
 7228 bruce                    2449                 :                 else
                               2450                 :                 {
 7127 tgl                      2451                 :                     /* domain constraint --- can't have Vars */
 7127 tgl                      2452 GIC          91 :                     context = NIL;
                               2453                 :                 }
                               2454                 : 
 7193 tgl                      2455 CBC         971 :                 consrc = deparse_expression_pretty(expr, context, false, false,
                               2456                 :                                                    prettyFlags, 0);
 7228 bruce                    2457 ECB             : 
 7127 tgl                      2458                 :                 /*
                               2459                 :                  * Now emit the constraint definition, adding NO INHERIT if
 4006 alvherre                 2460                 :                  * necessary.
 4006 alvherre                 2461 EUB             :                  *
 3955 bruce                    2462 ECB             :                  * There are cases where the constraint expression will be
                               2463                 :                  * fully parenthesized and we don't need the outer parens ...
                               2464                 :                  * but there are other cases where we do need 'em.  Be
 3955 bruce                    2465 EUB             :                  * conservative for now.
                               2466                 :                  *
                               2467                 :                  * Note that simply checking for leading '(' and trailing ')'
                               2468                 :                  * would NOT be good enough, consider "(x > 0) AND (y > 0)".
                               2469                 :                  */
 3911 alvherre                 2470 GIC         971 :                 appendStringInfo(&buf, "CHECK (%s)%s",
                               2471                 :                                  consrc,
                               2472             971 :                                  conForm->connoinherit ? " NO INHERIT" : "");
 7360 bruce                    2473 GBC         971 :                 break;
 7360 bruce                    2474 EUB             :             }
    2 alvherre                 2475 GNC          27 :         case CONSTRAINT_NOTNULL:
                               2476                 :             {
                               2477                 :                 AttrNumber  attnum;
                               2478                 : 
                               2479              27 :                 attnum = extractNotNullColumn(tup);
                               2480                 : 
                               2481              27 :                 appendStringInfo(&buf, "NOT NULL %s",
                               2482              27 :                                  quote_identifier(get_attname(conForm->conrelid,
                               2483                 :                                                               attnum, false)));
                               2484              27 :                 if (((Form_pg_constraint) GETSTRUCT(tup))->connoinherit)
    2 alvherre                 2485 UNC           0 :                     appendStringInfoString(&buf, " NO INHERIT");
    2 alvherre                 2486 GNC          27 :                 break;
                               2487                 :             }
                               2488                 : 
 4830 tgl                      2489 LBC           0 :         case CONSTRAINT_TRIGGER:
                               2490                 : 
 4830 tgl                      2491 ECB             :             /*
                               2492                 :              * There isn't an ALTER TABLE syntax for creating a user-defined
                               2493                 :              * constraint trigger, but it seems better to print something than
                               2494                 :              * throw an error; if we throw error then this function couldn't
                               2495                 :              * safely be applied to all rows of pg_constraint.
                               2496                 :              */
 3447 rhaas                    2497 UIC           0 :             appendStringInfoString(&buf, "TRIGGER");
 4830 tgl                      2498               0 :             break;
 4871 tgl                      2499 CBC          52 :         case CONSTRAINT_EXCLUSION:
                               2500                 :             {
 4790 bruce                    2501 GIC          52 :                 Oid         indexOid = conForm->conindid;
 4790 bruce                    2502 ECB             :                 Datum       val;
                               2503                 :                 Datum      *elems;
                               2504                 :                 int         nElems;
                               2505                 :                 int         i;
                               2506                 :                 Oid        *operators;
                               2507                 : 
                               2508                 :                 /* Extract operator OIDs from the pg_constraint tuple */
   15 dgustafsson              2509 GNC          52 :                 val = SysCacheGetAttrNotNull(CONSTROID, tup,
                               2510                 :                                              Anum_pg_constraint_conexclop);
                               2511                 : 
  282 peter                    2512              52 :                 deconstruct_array_builtin(DatumGetArrayTypeP(val), OIDOID,
                               2513                 :                                           &elems, NULL, &nElems);
                               2514                 : 
 4871 tgl                      2515 CBC          52 :                 operators = (Oid *) palloc(nElems * sizeof(Oid));
 4871 tgl                      2516 GIC         114 :                 for (i = 0; i < nElems; i++)
 4871 tgl                      2517 GBC          62 :                     operators[i] = DatumGetObjectId(elems[i]);
 4871 tgl                      2518 EUB             : 
                               2519                 :                 /* pg_get_indexdef_worker does the rest */
                               2520                 :                 /* suppress tablespace because pg_dump wants it that way */
 4871 tgl                      2521 GIC          52 :                 appendStringInfoString(&buf,
 4871 tgl                      2522 CBC          52 :                                        pg_get_indexdef_worker(indexOid,
 4871 tgl                      2523 ECB             :                                                               0,
                               2524                 :                                                               operators,
 4871 tgl                      2525 EUB             :                                                               false,
 4871 tgl                      2526 ECB             :                                                               false,
 1906 alvherre                 2527                 :                                                               false,
                               2528                 :                                                               false,
                               2529                 :                                                               prettyFlags,
 2448 rhaas                    2530                 :                                                               false));
 4871 tgl                      2531 CBC          52 :                 break;
                               2532                 :             }
 7541 tgl                      2533 LBC           0 :         default:
 7146 peter_e                  2534 UIC           0 :             elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
                               2535                 :             break;
                               2536                 :     }
                               2537                 : 
 5002 tgl                      2538 GIC        2563 :     if (conForm->condeferrable)
 3447 rhaas                    2539              20 :         appendStringInfoString(&buf, " DEFERRABLE");
 5002 tgl                      2540            2563 :     if (conForm->condeferred)
 3447 rhaas                    2541 UIC           0 :         appendStringInfoString(&buf, " INITIALLY DEFERRED");
 4329 alvherre                 2542 GIC        2563 :     if (!conForm->convalidated)
 4329 alvherre                 2543 CBC          47 :         appendStringInfoString(&buf, " NOT VALID");
                               2544                 : 
                               2545                 :     /* Cleanup */
 3290 simon                    2546 GIC        2563 :     systable_endscan(scandesc);
 1539 andres                   2547            2563 :     table_close(relation, AccessShareLock);
                               2548                 : 
 6913 tgl                      2549            2563 :     return buf.data;
                               2550                 : }
 7541 tgl                      2551 ECB             : 
                               2552                 : 
                               2553                 : /*
                               2554                 :  * Convert an int16[] Datum into a comma-separated list of column names
                               2555                 :  * for the indicated relation; append the list to buf.  Returns the number
                               2556                 :  * of keys.
                               2557                 :  */
 1679 alvherre                 2558                 : static int
 7541 tgl                      2559 GIC        1833 : decompile_column_index_array(Datum column_index_array, Oid relId,
 7541 tgl                      2560 ECB             :                              StringInfo buf)
                               2561                 : {
                               2562                 :     Datum      *keys;
                               2563                 :     int         nKeys;
                               2564                 :     int         j;
                               2565                 : 
                               2566                 :     /* Extract data from array of int16 */
  282 peter                    2567 GNC        1833 :     deconstruct_array_builtin(DatumGetArrayTypeP(column_index_array), INT2OID,
                               2568                 :                               &keys, NULL, &nKeys);
                               2569                 : 
 7541 tgl                      2570 GIC        4229 :     for (j = 0; j < nKeys; j++)
                               2571                 :     {
                               2572                 :         char       *colName;
                               2573                 : 
 1882 alvherre                 2574            2396 :         colName = get_attname(relId, DatumGetInt16(keys[j]), false);
                               2575                 : 
 7541 tgl                      2576            2396 :         if (j == 0)
 7008 neilc                    2577            1833 :             appendStringInfoString(buf, quote_identifier(colName));
                               2578                 :         else
                               2579             563 :             appendStringInfo(buf, ", %s", quote_identifier(colName));
                               2580                 :     }
                               2581                 : 
 1679 alvherre                 2582            1833 :     return nKeys;
                               2583                 : }
                               2584                 : 
                               2585                 : 
                               2586                 : /* ----------
                               2587                 :  * pg_get_expr          - Decompile an expression tree
                               2588                 :  *
 7937 tgl                      2589 ECB             :  * Input: an expression tree in nodeToString form, and a relation OID
                               2590                 :  *
                               2591                 :  * Output: reverse-listed expression
                               2592                 :  *
                               2593                 :  * Currently, the expression can only refer to a single relation, namely
                               2594                 :  * the one specified by the second parameter.  This is sufficient for
                               2595                 :  * partial indexes, column default expressions, etc.  We also support
 5066                          2596                 :  * Var-free expressions, for which the OID can be InvalidOid.
                               2597                 :  *
  455                          2598                 :  * We expect this function to work, or throw a reasonably clean error,
                               2599                 :  * for any node tree that can appear in a catalog pg_node_tree column.
                               2600                 :  * Query trees, such as those appearing in pg_rewrite.ev_action, are
                               2601                 :  * not supported.  Nor are expressions in more than one relation, which
                               2602                 :  * can appear in places like pg_rewrite.ev_qual.
                               2603                 :  * ----------
                               2604                 :  */
                               2605                 : Datum
 7937 tgl                      2606 GIC        3353 : pg_get_expr(PG_FUNCTION_ARGS)
                               2607                 : {
 2219 noah                     2608            3353 :     text       *expr = PG_GETARG_TEXT_PP(0);
 7188 bruce                    2609 CBC        3353 :     Oid         relid = PG_GETARG_OID(1);
 3717 tgl                      2610 EUB             :     int         prettyFlags;
                               2611                 :     char       *relname;
                               2612                 : 
 3717 tgl                      2613 GBC        3353 :     prettyFlags = PRETTYFLAG_INDENT;
                               2614                 : 
 5066 tgl                      2615 CBC        3353 :     if (OidIsValid(relid))
                               2616                 :     {
                               2617                 :         /* Get the name for the relation */
 5066 tgl                      2618 GIC        3353 :         relname = get_rel_name(relid);
 5066 tgl                      2619 ECB             : 
                               2620                 :         /*
                               2621                 :          * If the OID isn't actually valid, don't throw an error, just return
                               2622                 :          * NULL.  This is a bit questionable, but it's what we've done
                               2623                 :          * historically, and it can help avoid unwanted failures when
                               2624                 :          * examining catalog entries for just-deleted relations.
                               2625                 :          */
 5066 tgl                      2626 GIC        3353 :         if (relname == NULL)
 5066 tgl                      2627 LBC           0 :             PG_RETURN_NULL();
                               2628                 :     }
 5066 tgl                      2629 ECB             :     else
 5066 tgl                      2630 UIC           0 :         relname = NULL;
                               2631                 : 
 3717 tgl                      2632 CBC        3353 :     PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
                               2633                 : }
 7193 tgl                      2634 ECB             : 
 7193 tgl                      2635 EUB             : Datum
 7193 tgl                      2636 GIC         203 : pg_get_expr_ext(PG_FUNCTION_ARGS)
                               2637                 : {
 2219 noah                     2638 GBC         203 :     text       *expr = PG_GETARG_TEXT_PP(0);
 7188 bruce                    2639 GIC         203 :     Oid         relid = PG_GETARG_OID(1);
 7193 tgl                      2640 CBC         203 :     bool        pretty = PG_GETARG_BOOL(2);
                               2641                 :     int         prettyFlags;
                               2642                 :     char       *relname;
                               2643                 : 
  377                          2644             203 :     prettyFlags = GET_PRETTY_FLAGS(pretty);
                               2645                 : 
 5066 tgl                      2646 GIC         203 :     if (OidIsValid(relid))
                               2647                 :     {
                               2648                 :         /* Get the name for the relation */
                               2649             203 :         relname = get_rel_name(relid);
                               2650                 :         /* See notes above */
                               2651             203 :         if (relname == NULL)
 5066 tgl                      2652 UIC           0 :             PG_RETURN_NULL();
                               2653                 :     }
 5066 tgl                      2654 ECB             :     else
 5066 tgl                      2655 UIC           0 :         relname = NULL;
                               2656                 : 
 5066 tgl                      2657 CBC         203 :     PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
                               2658                 : }
 7193 tgl                      2659 ECB             : 
                               2660                 : static text *
 5066 tgl                      2661 GIC        3556 : pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
                               2662                 : {
                               2663                 :     Node       *node;
                               2664                 :     Node       *tst;
                               2665                 :     Relids      relids;
                               2666                 :     List       *context;
 7193 tgl                      2667 ECB             :     char       *exprstr;
                               2668                 :     char       *str;
 7193 tgl                      2669 EUB             : 
  455 tgl                      2670 ECB             :     /* Convert input pg_node_tree (really TEXT) object to C string */
 5493 tgl                      2671 GBC        3556 :     exprstr = text_to_cstring(expr);
                               2672                 : 
                               2673                 :     /* Convert expression to node tree */
 7937 tgl                      2674 GIC        3556 :     node = (Node *) stringToNode(exprstr);
                               2675                 : 
 5066                          2676            3556 :     pfree(exprstr);
                               2677                 : 
                               2678                 :     /*
  455 tgl                      2679 ECB             :      * Throw error if the input is a querytree rather than an expression tree.
                               2680                 :      * While we could support queries here, there seems no very good reason
                               2681                 :      * to.  In most such catalog columns, we'll see a List of Query nodes, or
                               2682                 :      * even nested Lists, so drill down to a non-List node before checking.
  455 tgl                      2683 EUB             :      */
  455 tgl                      2684 GIC        3556 :     tst = node;
                               2685            3556 :     while (tst && IsA(tst, List))
  455 tgl                      2686 UIC           0 :         tst = linitial((List *) tst);
  455 tgl                      2687 GIC        3556 :     if (tst && IsA(tst, Query))
  455 tgl                      2688 UIC           0 :         ereport(ERROR,
  455 tgl                      2689 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2690                 :                  errmsg("input is a query, not an expression")));
                               2691                 : 
                               2692                 :     /*
                               2693                 :      * Throw error if the expression contains Vars we won't be able to
                               2694                 :      * deparse.
                               2695                 :      */
  455 tgl                      2696 CBC        3556 :     relids = pull_varnos(NULL, node);
                               2697            3556 :     if (OidIsValid(relid))
                               2698                 :     {
  455 tgl                      2699 GBC        3556 :         if (!bms_is_subset(relids, bms_make_singleton(1)))
  455 tgl                      2700 UIC           0 :             ereport(ERROR,
                               2701                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  455 tgl                      2702 ECB             :                      errmsg("expression contains variables of more than one relation")));
                               2703                 :     }
                               2704                 :     else
                               2705                 :     {
  455 tgl                      2706 UIC           0 :         if (!bms_is_empty(relids))
                               2707               0 :             ereport(ERROR,
                               2708                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2709                 :                      errmsg("expression contains variables")));
                               2710                 :     }
                               2711                 : 
                               2712                 :     /* Prepare deparse context if needed */
 5066 tgl                      2713 GIC        3556 :     if (OidIsValid(relid))
                               2714            3556 :         context = deparse_context_for(relname, relid);
 5066 tgl                      2715 ECB             :     else
 5066 tgl                      2716 UIC           0 :         context = NIL;
 5066 tgl                      2717 ECB             : 
                               2718                 :     /* Deparse */
 7193 tgl                      2719 GIC        3556 :     str = deparse_expression_pretty(node, context, false, false,
                               2720                 :                                     prettyFlags, 0);
                               2721                 : 
 5066                          2722            3556 :     return string_to_text(str);
                               2723                 : }
                               2724                 : 
 7937 tgl                      2725 ECB             : 
 8955 bruce                    2726                 : /* ----------
                               2727                 :  * pg_get_userbyid      - Get a user name by roleid and
                               2728                 :  *                fallback to 'unknown (OID=n)'
                               2729                 :  * ----------
                               2730                 :  */
 8335 tgl                      2731                 : Datum
 8335 tgl                      2732 CBC         774 : pg_get_userbyid(PG_FUNCTION_ARGS)
                               2733                 : {
 6494                          2734             774 :     Oid         roleid = PG_GETARG_OID(0);
 8335 tgl                      2735 ECB             :     Name        result;
 6494                          2736                 :     HeapTuple   roletup;
                               2737                 :     Form_pg_authid role_rec;
                               2738                 : 
 8053 bruce                    2739 EUB             :     /*
                               2740                 :      * Allocate space for the result
 8955 bruce                    2741 ECB             :      */
 8335 tgl                      2742 GIC         774 :     result = (Name) palloc(NAMEDATALEN);
 8554 bruce                    2743             774 :     memset(NameStr(*result), 0, NAMEDATALEN);
                               2744                 : 
                               2745                 :     /*
                               2746                 :      * Get the pg_authid entry and print the result
                               2747                 :      */
 4802 rhaas                    2748             774 :     roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
 6494 tgl                      2749             774 :     if (HeapTupleIsValid(roletup))
                               2750                 :     {
                               2751             774 :         role_rec = (Form_pg_authid) GETSTRUCT(roletup);
  972 peter                    2752             774 :         *result = role_rec->rolname;
 6494 tgl                      2753 CBC         774 :         ReleaseSysCache(roletup);
                               2754                 :     }
 8955 bruce                    2755 ECB             :     else
 6494 tgl                      2756 LBC           0 :         sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
                               2757                 : 
 8335 tgl                      2758 GIC         774 :     PG_RETURN_NAME(result);
                               2759                 : }
                               2760                 : 
 6862 tgl                      2761 ECB             : 
                               2762                 : /*
                               2763                 :  * pg_get_serial_sequence
                               2764                 :  *      Get the name of the sequence used by an identity or serial column,
                               2765                 :  *      formatted suitably for passing to setval, nextval or currval.
                               2766                 :  *      First parameter is not treated as double-quoted, second parameter
                               2767                 :  *      is --- see documentation for reason.
                               2768                 :  */
                               2769                 : Datum
 6862 tgl                      2770 GIC           6 : pg_get_serial_sequence(PG_FUNCTION_ARGS)
                               2771                 : {
 2219 noah                     2772 CBC           6 :     text       *tablename = PG_GETARG_TEXT_PP(0);
 5493 tgl                      2773 GIC           6 :     text       *columnname = PG_GETARG_TEXT_PP(1);
 6862 tgl                      2774 ECB             :     RangeVar   *tablerv;
                               2775                 :     Oid         tableOid;
 6797 bruce                    2776 EUB             :     char       *column;
                               2777                 :     AttrNumber  attnum;
 6797 bruce                    2778 GIC           6 :     Oid         sequenceId = InvalidOid;
                               2779                 :     Relation    depRel;
                               2780                 :     ScanKeyData key[3];
                               2781                 :     SysScanDesc scan;
 6862 tgl                      2782 ECB             :     HeapTuple   tup;
                               2783                 : 
 3260 bruce                    2784                 :     /* Look up table name.  Can't lock it - we might not have privileges. */
 6526 neilc                    2785 GIC           6 :     tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
 4148 rhaas                    2786               6 :     tableOid = RangeVarGetRelid(tablerv, NoLock, false);
                               2787                 : 
 6862 tgl                      2788 ECB             :     /* Get the number of the column */
 5493 tgl                      2789 GIC           6 :     column = text_to_cstring(columnname);
                               2790                 : 
 6862                          2791               6 :     attnum = get_attnum(tableOid, column);
 6862 tgl                      2792 CBC           6 :     if (attnum == InvalidAttrNumber)
 6862 tgl                      2793 UIC           0 :         ereport(ERROR,
                               2794                 :                 (errcode(ERRCODE_UNDEFINED_COLUMN),
                               2795                 :                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                               2796                 :                         column, tablerv->relname)));
 6862 tgl                      2797 ECB             : 
                               2798                 :     /* Search the dependency table for the dependent sequence */
 1539 andres                   2799 GIC           6 :     depRel = table_open(DependRelationId, AccessShareLock);
 6862 tgl                      2800 ECB             : 
 6862 tgl                      2801 GIC           6 :     ScanKeyInit(&key[0],
 6862 tgl                      2802 ECB             :                 Anum_pg_depend_refclassid,
                               2803                 :                 BTEqualStrategyNumber, F_OIDEQ,
                               2804                 :                 ObjectIdGetDatum(RelationRelationId));
 6862 tgl                      2805 GIC           6 :     ScanKeyInit(&key[1],
                               2806                 :                 Anum_pg_depend_refobjid,
                               2807                 :                 BTEqualStrategyNumber, F_OIDEQ,
                               2808                 :                 ObjectIdGetDatum(tableOid));
 6862 tgl                      2809 CBC           6 :     ScanKeyInit(&key[2],
 6862 tgl                      2810 ECB             :                 Anum_pg_depend_refobjsubid,
                               2811                 :                 BTEqualStrategyNumber, F_INT4EQ,
                               2812                 :                 Int32GetDatum(attnum));
                               2813                 : 
 6569 tgl                      2814 GIC           6 :     scan = systable_beginscan(depRel, DependReferenceIndexId, true,
 3568 rhaas                    2815 ECB             :                               NULL, 3, key);
 6862 tgl                      2816                 : 
 6862 tgl                      2817 GIC          15 :     while (HeapTupleIsValid(tup = systable_getnext(scan)))
                               2818                 :     {
 6797 bruce                    2819              15 :         Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
 6862 tgl                      2820 ECB             : 
                               2821                 :         /*
                               2822                 :          * Look for an auto dependency (serial column) or internal dependency
 2032 peter_e                  2823                 :          * (identity column) of a sequence on a column.  (We need the relkind
                               2824                 :          * test because indexes can also have auto dependencies on columns.)
                               2825                 :          */
 6569 tgl                      2826 GIC          15 :         if (deprec->classid == RelationRelationId &&
 6862 tgl                      2827 CBC           6 :             deprec->objsubid == 0 &&
 2032 peter_e                  2828 GIC           6 :             (deprec->deptype == DEPENDENCY_AUTO ||
 2032 peter_e                  2829 CBC           9 :              deprec->deptype == DEPENDENCY_INTERNAL) &&
 5994 tgl                      2830 GIC           6 :             get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
                               2831                 :         {
 6862 tgl                      2832 GBC           6 :             sequenceId = deprec->objid;
 6862 tgl                      2833 GIC           6 :             break;
                               2834                 :         }
                               2835                 :     }
                               2836                 : 
                               2837               6 :     systable_endscan(scan);
 1539 andres                   2838               6 :     table_close(depRel, AccessShareLock);
                               2839                 : 
 6862 tgl                      2840               6 :     if (OidIsValid(sequenceId))
                               2841                 :     {
                               2842                 :         char       *result;
                               2843                 : 
 2697                          2844               6 :         result = generate_qualified_relation_name(sequenceId);
                               2845                 : 
 6862                          2846               6 :         PG_RETURN_TEXT_P(string_to_text(result));
 6862 tgl                      2847 ECB             :     }
                               2848                 : 
 6862 tgl                      2849 LBC           0 :     PG_RETURN_NULL();
                               2850                 : }
                               2851                 : 
                               2852                 : 
                               2853                 : /*
                               2854                 :  * pg_get_functiondef
                               2855                 :  *      Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
                               2856                 :  *      the specified function.
                               2857                 :  *
                               2858                 :  * Note: if you change the output format of this function, be careful not
                               2859                 :  * to break psql's rules (in \ef and \sf) for identifying the start of the
                               2860                 :  * function body.  To wit: the function body starts on a line that begins with
                               2861                 :  * "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
                               2862                 :  */
 5328 tgl                      2863 ECB             : Datum
 5328 tgl                      2864 GIC          73 : pg_get_functiondef(PG_FUNCTION_ARGS)
                               2865                 : {
 5328 tgl                      2866 CBC          73 :     Oid         funcid = PG_GETARG_OID(0);
 5328 tgl                      2867 ECB             :     StringInfoData buf;
                               2868                 :     StringInfoData dq;
                               2869                 :     HeapTuple   proctup;
                               2870                 :     Form_pg_proc proc;
 1881 peter_e                  2871                 :     bool        isfunction;
                               2872                 :     Datum       tmp;
 5328 tgl                      2873                 :     bool        isnull;
 5328 tgl                      2874 EUB             :     const char *prosrc;
                               2875                 :     const char *name;
                               2876                 :     const char *nsp;
                               2877                 :     float4      procost;
 5328 tgl                      2878 ECB             :     int         oldlen;
                               2879                 : 
 5328 tgl                      2880 GIC          73 :     initStringInfo(&buf);
                               2881                 : 
                               2882                 :     /* Look up the function */
 4802 rhaas                    2883              73 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 5328 tgl                      2884 CBC          73 :     if (!HeapTupleIsValid(proctup))
 2448 rhaas                    2885               3 :         PG_RETURN_NULL();
                               2886                 : 
 5328 tgl                      2887 GIC          70 :     proc = (Form_pg_proc) GETSTRUCT(proctup);
 5328 tgl                      2888 CBC          70 :     name = NameStr(proc->proname);
 5328 tgl                      2889 ECB             : 
 1864 peter_e                  2890 CBC          70 :     if (proc->prokind == PROKIND_AGGREGATE)
 5328 tgl                      2891 UIC           0 :         ereport(ERROR,
 5328 tgl                      2892 ECB             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               2893                 :                  errmsg("\"%s\" is an aggregate function", name)));
                               2894                 : 
 1864 peter_e                  2895 GIC          70 :     isfunction = (proc->prokind != PROKIND_PROCEDURE);
                               2896                 : 
 5328 tgl                      2897 ECB             :     /*
                               2898                 :      * We always qualify the function name, to ensure the right function gets
 5050 bruce                    2899                 :      * replaced.
 5328 tgl                      2900                 :      */
  621 tgl                      2901 GIC          70 :     nsp = get_namespace_name_or_temp(proc->pronamespace);
 1881 peter_e                  2902              70 :     appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
 1881 peter_e                  2903 ECB             :                      isfunction ? "FUNCTION" : "PROCEDURE",
                               2904                 :                      quote_qualified_identifier(nsp, name));
 5239 peter_e                  2905 CBC          70 :     (void) print_function_arguments(&buf, proctup, false, true);
 1881 peter_e                  2906 GBC          70 :     appendStringInfoString(&buf, ")\n");
 1881 peter_e                  2907 CBC          70 :     if (isfunction)
                               2908                 :     {
                               2909              61 :         appendStringInfoString(&buf, " RETURNS ");
                               2910              61 :         print_function_rettype(&buf, proctup);
                               2911              61 :         appendStringInfoChar(&buf, '\n');
 1881 peter_e                  2912 ECB             :     }
 2905                          2913                 : 
 2905 peter_e                  2914 CBC          70 :     print_function_trftypes(&buf, proctup);
 2905 peter_e                  2915 ECB             : 
 1881 peter_e                  2916 CBC          70 :     appendStringInfo(&buf, " LANGUAGE %s\n",
 2118 tgl                      2917 GIC          70 :                      quote_identifier(get_language_name(proc->prolang, false)));
                               2918                 : 
 5328 tgl                      2919 ECB             :     /* Emit some miscellaneous options on one line */
 5328 tgl                      2920 GIC          70 :     oldlen = buf.len;
 5328 tgl                      2921 ECB             : 
 1864 peter_e                  2922 CBC          70 :     if (proc->prokind == PROKIND_WINDOW)
 5212 tgl                      2923 LBC           0 :         appendStringInfoString(&buf, " WINDOW");
 5328 tgl                      2924 GBC          70 :     switch (proc->provolatile)
 5328 tgl                      2925 EUB             :     {
 5328 tgl                      2926 GBC          12 :         case PROVOLATILE_IMMUTABLE:
 5328 tgl                      2927 CBC          12 :             appendStringInfoString(&buf, " IMMUTABLE");
                               2928              12 :             break;
 5328 tgl                      2929 GIC           9 :         case PROVOLATILE_STABLE:
                               2930               9 :             appendStringInfoString(&buf, " STABLE");
 5328 tgl                      2931 CBC           9 :             break;
                               2932              49 :         case PROVOLATILE_VOLATILE:
                               2933              49 :             break;
 5328 tgl                      2934 ECB             :     }
 2539 rhaas                    2935                 : 
 2539 rhaas                    2936 GBC          70 :     switch (proc->proparallel)
                               2937                 :     {
 2539 rhaas                    2938 GIC          19 :         case PROPARALLEL_SAFE:
 2539 rhaas                    2939 CBC          19 :             appendStringInfoString(&buf, " PARALLEL SAFE");
                               2940              19 :             break;
 2539 rhaas                    2941 LBC           0 :         case PROPARALLEL_RESTRICTED:
 2539 rhaas                    2942 UIC           0 :             appendStringInfoString(&buf, " PARALLEL RESTRICTED");
 2539 rhaas                    2943 LBC           0 :             break;
 2539 rhaas                    2944 CBC          51 :         case PROPARALLEL_UNSAFE:
                               2945              51 :             break;
                               2946                 :     }
 2539 rhaas                    2947 ECB             : 
 5328 tgl                      2948 GBC          70 :     if (proc->proisstrict)
 5328 tgl                      2949 GIC          24 :         appendStringInfoString(&buf, " STRICT");
 5328 tgl                      2950 CBC          70 :     if (proc->prosecdef)
 5328 tgl                      2951 GIC           3 :         appendStringInfoString(&buf, " SECURITY DEFINER");
 2873                          2952              70 :     if (proc->proleakproof)
 2873 tgl                      2953 UIC           0 :         appendStringInfoString(&buf, " LEAKPROOF");
                               2954                 : 
                               2955                 :     /* This code for the default cost and rows should match functioncmds.c */
 5328 tgl                      2956 GIC          70 :     if (proc->prolang == INTERNALlanguageId ||
                               2957              70 :         proc->prolang == ClanguageId)
 5328 tgl                      2958 GBC           4 :         procost = 1;
 5328 tgl                      2959 EUB             :     else
 5328 tgl                      2960 GIC          66 :         procost = 100;
                               2961              70 :     if (proc->procost != procost)
                               2962               3 :         appendStringInfo(&buf, " COST %g", proc->procost);
                               2963                 : 
                               2964              70 :     if (proc->prorows > 0 && proc->prorows != 1000)
 5328 tgl                      2965 LBC           0 :         appendStringInfo(&buf, " ROWS %g", proc->prorows);
 5328 tgl                      2966 ECB             : 
 1520 tgl                      2967 GIC          70 :     if (proc->prosupport)
                               2968                 :     {
 1520 tgl                      2969 ECB             :         Oid         argtypes[1];
                               2970                 : 
                               2971                 :         /*
                               2972                 :          * We should qualify the support function's name if it wouldn't be
                               2973                 :          * resolved by lookup in the current search path.
                               2974                 :          */
 1520 tgl                      2975 LBC           0 :         argtypes[0] = INTERNALOID;
                               2976               0 :         appendStringInfo(&buf, " SUPPORT %s",
 1520 tgl                      2977 ECB             :                          generate_function_name(proc->prosupport, 1,
                               2978                 :                                                 NIL, argtypes,
                               2979                 :                                                 false, NULL, EXPR_KIND_NONE));
                               2980                 :     }
                               2981                 : 
 5328 tgl                      2982 GIC          70 :     if (oldlen != buf.len)
 5328 tgl                      2983 CBC          31 :         appendStringInfoChar(&buf, '\n');
                               2984                 : 
                               2985                 :     /* Emit any proconfig options, one per line */
 5328 tgl                      2986 GIC          70 :     tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
                               2987              70 :     if (!isnull)
                               2988                 :     {
 5050 bruce                    2989 CBC           3 :         ArrayType  *a = DatumGetArrayTypeP(tmp);
                               2990                 :         int         i;
 5328 tgl                      2991 ECB             : 
 5328 tgl                      2992 GIC           3 :         Assert(ARR_ELEMTYPE(a) == TEXTOID);
                               2993               3 :         Assert(ARR_NDIM(a) == 1);
 5328 tgl                      2994 CBC           3 :         Assert(ARR_LBOUND(a)[0] == 1);
 5328 tgl                      2995 ECB             : 
 5328 tgl                      2996 GBC          18 :         for (i = 1; i <= ARR_DIMS(a)[0]; i++)
 5328 tgl                      2997 ECB             :         {
                               2998                 :             Datum       d;
                               2999                 : 
 5328 tgl                      3000 GIC          15 :             d = array_ref(a, 1, &i,
                               3001                 :                           -1 /* varlenarray */ ,
                               3002                 :                           -1 /* TEXT's typlen */ ,
                               3003                 :                           false /* TEXT's typbyval */ ,
                               3004                 :                           TYPALIGN_INT /* TEXT's typalign */ ,
                               3005                 :                           &isnull);
                               3006              15 :             if (!isnull)
                               3007                 :             {
                               3008              15 :                 char       *configitem = TextDatumGetCString(d);
                               3009                 :                 char       *pos;
                               3010                 : 
                               3011              15 :                 pos = strchr(configitem, '=');
                               3012              15 :                 if (pos == NULL)
 5328 tgl                      3013 UIC           0 :                     continue;
 5328 tgl                      3014 GIC          15 :                 *pos++ = '\0';
                               3015                 : 
                               3016              15 :                 appendStringInfo(&buf, " SET %s TO ",
                               3017                 :                                  quote_identifier(configitem));
 5328 tgl                      3018 ECB             : 
                               3019                 :                 /*
                               3020                 :                  * Variables that are marked GUC_LIST_QUOTE were already fully
                               3021                 :                  * quoted by flatten_set_variable_args() before they were put
                               3022                 :                  * into the proconfig array.  However, because the quoting
                               3023                 :                  * rules used there aren't exactly like SQL's, we have to
 1713                          3024                 :                  * break the list value apart and then quote the elements as
                               3025                 :                  * string literals.  (The elements may be double-quoted as-is,
                               3026                 :                  * but we can't just feed them to the SQL parser; it would do
 1713 tgl                      3027 EUB             :                  * the wrong thing with elements that are zero-length or
                               3028                 :                  * longer than NAMEDATALEN.)
 1713 tgl                      3029 ECB             :                  *
                               3030                 :                  * Variables that are not so marked should just be emitted as
                               3031                 :                  * simple string literals.  If the variable is not known to
                               3032                 :                  * guc.c, we'll do that; this makes it unsafe to use
                               3033                 :                  * GUC_LIST_QUOTE for extension variables.
 5328                          3034                 :                  */
 1845 tgl                      3035 CBC          15 :                 if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE)
                               3036                 :                 {
                               3037                 :                     List       *namelist;
                               3038                 :                     ListCell   *lc;
 1713 tgl                      3039 ECB             : 
                               3040                 :                     /* Parse string into list of identifiers */
 1713 tgl                      3041 GIC           6 :                     if (!SplitGUCList(pos, ',', &namelist))
                               3042                 :                     {
                               3043                 :                         /* this shouldn't fail really */
 1713 tgl                      3044 UIC           0 :                         elog(ERROR, "invalid list syntax in proconfig item");
                               3045                 :                     }
 1713 tgl                      3046 CBC          21 :                     foreach(lc, namelist)
 1713 tgl                      3047 ECB             :                     {
 1713 tgl                      3048 GIC          15 :                         char       *curname = (char *) lfirst(lc);
 1713 tgl                      3049 ECB             : 
 1713 tgl                      3050 GIC          15 :                         simple_quote_literal(&buf, curname);
 1364                          3051              15 :                         if (lnext(namelist, lc))
 1713                          3052               9 :                             appendStringInfoString(&buf, ", ");
 1713 tgl                      3053 ECB             :                     }
                               3054                 :                 }
 5328                          3055                 :                 else
 5328 tgl                      3056 CBC           9 :                     simple_quote_literal(&buf, pos);
 5328 tgl                      3057 GIC          15 :                 appendStringInfoChar(&buf, '\n');
 5328 tgl                      3058 ECB             :             }
                               3059                 :         }
                               3060                 :     }
                               3061                 : 
                               3062                 :     /* And finally the function definition ... */
  586 tgl                      3063 CBC          70 :     (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
  732 peter                    3064 GIC          70 :     if (proc->prolang == SQLlanguageId && !isnull)
                               3065                 :     {
                               3066              39 :         print_function_sqlbody(&buf, proctup);
                               3067                 :     }
                               3068                 :     else
                               3069                 :     {
  697 tgl                      3070              31 :         appendStringInfoString(&buf, "AS ");
                               3071                 : 
                               3072              31 :         tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
  697 tgl                      3073 CBC          31 :         if (!isnull)
  697 tgl                      3074 ECB             :         {
  697 tgl                      3075 CBC           4 :             simple_quote_literal(&buf, TextDatumGetCString(tmp));
                               3076               4 :             appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
  697 tgl                      3077 EUB             :         }
 5328 tgl                      3078 ECB             : 
   15 dgustafsson              3079 GNC          31 :         tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosrc);
  697 tgl                      3080 CBC          31 :         prosrc = TextDatumGetCString(tmp);
                               3081                 : 
                               3082                 :         /*
  697 tgl                      3083 ECB             :          * We always use dollar quoting.  Figure out a suitable delimiter.
                               3084                 :          *
                               3085                 :          * Since the user is likely to be editing the function body string, we
                               3086                 :          * shouldn't use a short delimiter that he might easily create a
                               3087                 :          * conflict with.  Hence prefer "$function$"/"$procedure$", but extend
                               3088                 :          * if needed.
                               3089                 :          */
  697 tgl                      3090 GIC          31 :         initStringInfo(&dq);
                               3091              31 :         appendStringInfoChar(&dq, '$');
                               3092              31 :         appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
                               3093              31 :         while (strstr(prosrc, dq.data) != NULL)
  697 tgl                      3094 UIC           0 :             appendStringInfoChar(&dq, 'x');
  697 tgl                      3095 GIC          31 :         appendStringInfoChar(&dq, '$');
                               3096                 : 
  697 tgl                      3097 CBC          31 :         appendBinaryStringInfo(&buf, dq.data, dq.len);
  697 tgl                      3098 GIC          31 :         appendStringInfoString(&buf, prosrc);
  697 tgl                      3099 CBC          31 :         appendBinaryStringInfo(&buf, dq.data, dq.len);
                               3100                 :     }
                               3101                 : 
 3447 rhaas                    3102 GIC          70 :     appendStringInfoChar(&buf, '\n');
 5328 tgl                      3103 ECB             : 
 5328 tgl                      3104 CBC          70 :     ReleaseSysCache(proctup);
 5328 tgl                      3105 ECB             : 
 5328 tgl                      3106 GIC          70 :     PG_RETURN_TEXT_P(string_to_text(buf.data));
 5328 tgl                      3107 ECB             : }
                               3108                 : 
 5378                          3109                 : /*
                               3110                 :  * pg_get_function_arguments
                               3111                 :  *      Get a nicely-formatted list of arguments for a function.
                               3112                 :  *      This is everything that would go between the parentheses in
                               3113                 :  *      CREATE FUNCTION.
                               3114                 :  */
                               3115                 : Datum
 5378 tgl                      3116 GIC        2234 : pg_get_function_arguments(PG_FUNCTION_ARGS)
                               3117                 : {
                               3118            2234 :     Oid         funcid = PG_GETARG_OID(0);
                               3119                 :     StringInfoData buf;
                               3120                 :     HeapTuple   proctup;
                               3121                 : 
 4802 rhaas                    3122            2234 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 5378 tgl                      3123 CBC        2234 :     if (!HeapTupleIsValid(proctup))
 2445 rhaas                    3124 GIC           3 :         PG_RETURN_NULL();
 2445 rhaas                    3125 ECB             : 
 2445 rhaas                    3126 GIC        2231 :     initStringInfo(&buf);
                               3127                 : 
 5239 peter_e                  3128            2231 :     (void) print_function_arguments(&buf, proctup, false, true);
 5378 tgl                      3129 ECB             : 
 5378 tgl                      3130 CBC        2231 :     ReleaseSysCache(proctup);
 5378 tgl                      3131 ECB             : 
 5378 tgl                      3132 GIC        2231 :     PG_RETURN_TEXT_P(string_to_text(buf.data));
 5378 tgl                      3133 ECB             : }
                               3134                 : 
 5239 peter_e                  3135                 : /*
                               3136                 :  * pg_get_function_identity_arguments
                               3137                 :  *      Get a formatted list of arguments for a function.
                               3138                 :  *      This is everything that would go between the parentheses in
 5225 tgl                      3139                 :  *      ALTER FUNCTION, etc.  In particular, don't print defaults.
                               3140                 :  */
                               3141                 : Datum
 5239 peter_e                  3142 GIC        1977 : pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
                               3143                 : {
                               3144            1977 :     Oid         funcid = PG_GETARG_OID(0);
                               3145                 :     StringInfoData buf;
                               3146                 :     HeapTuple   proctup;
                               3147                 : 
 4802 rhaas                    3148 CBC        1977 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 5239 peter_e                  3149 GIC        1977 :     if (!HeapTupleIsValid(proctup))
 2445 rhaas                    3150 CBC           3 :         PG_RETURN_NULL();
                               3151                 : 
 2445 rhaas                    3152 GIC        1974 :     initStringInfo(&buf);
                               3153                 : 
 5239 peter_e                  3154 CBC        1974 :     (void) print_function_arguments(&buf, proctup, false, false);
 5239 peter_e                  3155 ECB             : 
 5239 peter_e                  3156 CBC        1974 :     ReleaseSysCache(proctup);
                               3157                 : 
                               3158            1974 :     PG_RETURN_TEXT_P(string_to_text(buf.data));
                               3159                 : }
 5239 peter_e                  3160 ECB             : 
 5378 tgl                      3161                 : /*
                               3162                 :  * pg_get_function_result
                               3163                 :  *      Get a nicely-formatted version of the result type of a function.
                               3164                 :  *      This is what would appear after RETURNS in CREATE FUNCTION.
                               3165                 :  */
                               3166                 : Datum
 5378 tgl                      3167 GIC        1939 : pg_get_function_result(PG_FUNCTION_ARGS)
 5378 tgl                      3168 ECB             : {
 5378 tgl                      3169 GIC        1939 :     Oid         funcid = PG_GETARG_OID(0);
 5378 tgl                      3170 ECB             :     StringInfoData buf;
                               3171                 :     HeapTuple   proctup;
                               3172                 : 
 4802 rhaas                    3173 GIC        1939 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 5378 tgl                      3174            1939 :     if (!HeapTupleIsValid(proctup))
 2445 rhaas                    3175               3 :         PG_RETURN_NULL();
                               3176                 : 
 1864 peter_e                  3177            1936 :     if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE)
 1956 peter_e                  3178 ECB             :     {
 1956 peter_e                  3179 GIC         105 :         ReleaseSysCache(proctup);
 1956 peter_e                  3180 CBC         105 :         PG_RETURN_NULL();
 1956 peter_e                  3181 ECB             :     }
                               3182                 : 
 2445 rhaas                    3183 GIC        1831 :     initStringInfo(&buf);
 5378 tgl                      3184 ECB             : 
 5328 tgl                      3185 GIC        1831 :     print_function_rettype(&buf, proctup);
 5328 tgl                      3186 ECB             : 
 5328 tgl                      3187 GIC        1831 :     ReleaseSysCache(proctup);
                               3188                 : 
 5328 tgl                      3189 CBC        1831 :     PG_RETURN_TEXT_P(string_to_text(buf.data));
 5328 tgl                      3190 ECB             : }
                               3191                 : 
                               3192                 : /*
                               3193                 :  * Guts of pg_get_function_result: append the function's return type
                               3194                 :  * to the specified buffer.
                               3195                 :  */
                               3196                 : static void
 5328 tgl                      3197 CBC        1892 : print_function_rettype(StringInfo buf, HeapTuple proctup)
                               3198                 : {
 5328 tgl                      3199 GIC        1892 :     Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
 5328 tgl                      3200 CBC        1892 :     int         ntabargs = 0;
 5328 tgl                      3201 ECB             :     StringInfoData rbuf;
                               3202                 : 
 5328 tgl                      3203 GIC        1892 :     initStringInfo(&rbuf);
                               3204                 : 
 5328 tgl                      3205 CBC        1892 :     if (proc->proretset)
 5378 tgl                      3206 ECB             :     {
                               3207                 :         /* It might be a table function; try to print the arguments */
 5328 tgl                      3208 GIC         173 :         appendStringInfoString(&rbuf, "TABLE(");
 5225                          3209             173 :         ntabargs = print_function_arguments(&rbuf, proctup, true, false);
 5378                          3210             173 :         if (ntabargs > 0)
 2890 peter_e                  3211              35 :             appendStringInfoChar(&rbuf, ')');
                               3212                 :         else
 5328 tgl                      3213             138 :             resetStringInfo(&rbuf);
                               3214                 :     }
                               3215                 : 
 5378 tgl                      3216 CBC        1892 :     if (ntabargs == 0)
                               3217                 :     {
                               3218                 :         /* Not a table function, so do the normal thing */
 5328                          3219            1857 :         if (proc->proretset)
 5328 tgl                      3220 GIC         138 :             appendStringInfoString(&rbuf, "SETOF ");
                               3221            1857 :         appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
                               3222                 :     }
                               3223                 : 
 1356 drowley                  3224 CBC        1892 :     appendBinaryStringInfo(buf, rbuf.data, rbuf.len);
 5378 tgl                      3225 GIC        1892 : }
                               3226                 : 
                               3227                 : /*
 5378 tgl                      3228 ECB             :  * Common code for pg_get_function_arguments and pg_get_function_result:
                               3229                 :  * append the desired subset of arguments to buf.  We print only TABLE
                               3230                 :  * arguments when print_table_args is true, and all the others when it's false.
                               3231                 :  * We print argument defaults only if print_defaults is true.
                               3232                 :  * Function return value is the number of arguments printed.
                               3233                 :  */
                               3234                 : static int
 5378 tgl                      3235 CBC        4448 : print_function_arguments(StringInfo buf, HeapTuple proctup,
 5225 tgl                      3236 ECB             :                          bool print_table_args, bool print_defaults)
                               3237                 : {
 5225 tgl                      3238 GIC        4448 :     Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
                               3239                 :     int         numargs;
                               3240                 :     Oid        *argtypes;
 5378 tgl                      3241 ECB             :     char      **argnames;
                               3242                 :     char       *argmodes;
 3394 tgl                      3243 GIC        4448 :     int         insertorderbyat = -1;
 5378 tgl                      3244 ECB             :     int         argsprinted;
                               3245                 :     int         inputargno;
                               3246                 :     int         nlackdefaults;
 1364 tgl                      3247 GIC        4448 :     List       *argdefaults = NIL;
 5225 tgl                      3248 CBC        4448 :     ListCell   *nextargdefault = NULL;
 5378 tgl                      3249 ECB             :     int         i;
                               3250                 : 
 5378 tgl                      3251 CBC        4448 :     numargs = get_func_arg_info(proctup,
                               3252                 :                                 &argtypes, &argnames, &argmodes);
 5378 tgl                      3253 ECB             : 
 5225 tgl                      3254 GIC        4448 :     nlackdefaults = numargs;
                               3255            4448 :     if (print_defaults && proc->pronargdefaults > 0)
                               3256                 :     {
                               3257                 :         Datum       proargdefaults;
 5225 tgl                      3258 ECB             :         bool        isnull;
                               3259                 : 
 5225 tgl                      3260 GIC          18 :         proargdefaults = SysCacheGetAttr(PROCOID, proctup,
                               3261                 :                                          Anum_pg_proc_proargdefaults,
                               3262                 :                                          &isnull);
 5225 tgl                      3263 CBC          18 :         if (!isnull)
 5225 tgl                      3264 ECB             :         {
 5050 bruce                    3265 EUB             :             char       *str;
                               3266                 : 
 5225 tgl                      3267 CBC          18 :             str = TextDatumGetCString(proargdefaults);
 2238 peter_e                  3268              18 :             argdefaults = castNode(List, stringToNode(str));
 5225 tgl                      3269              18 :             pfree(str);
                               3270              18 :             nextargdefault = list_head(argdefaults);
                               3271                 :             /* nlackdefaults counts only *input* arguments lacking defaults */
 5225 tgl                      3272 GIC          18 :             nlackdefaults = proc->pronargs - list_length(argdefaults);
 5225 tgl                      3273 ECB             :         }
 5239 peter_e                  3274                 :     }
                               3275                 : 
                               3276                 :     /* Check for special treatment of ordered-set aggregates */
 1864 peter_e                  3277 CBC        4448 :     if (proc->prokind == PROKIND_AGGREGATE)
 3394 tgl                      3278 ECB             :     {
                               3279                 :         HeapTuple   aggtup;
                               3280                 :         Form_pg_aggregate agg;
                               3281                 : 
 1601 andres                   3282 GIC         591 :         aggtup = SearchSysCache1(AGGFNOID, proc->oid);
 3394 tgl                      3283 CBC         591 :         if (!HeapTupleIsValid(aggtup))
 3394 tgl                      3284 UIC           0 :             elog(ERROR, "cache lookup failed for aggregate %u",
 1601 andres                   3285 ECB             :                  proc->oid);
 3394 tgl                      3286 GIC         591 :         agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
                               3287             591 :         if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
                               3288              26 :             insertorderbyat = agg->aggnumdirectargs;
                               3289             591 :         ReleaseSysCache(aggtup);
                               3290                 :     }
 3394 tgl                      3291 ECB             : 
 5378 tgl                      3292 CBC        4448 :     argsprinted = 0;
 5225 tgl                      3293 GIC        4448 :     inputargno = 0;
 5378 tgl                      3294 CBC        9039 :     for (i = 0; i < numargs; i++)
 5378 tgl                      3295 ECB             :     {
 5050 bruce                    3296 CBC        4591 :         Oid         argtype = argtypes[i];
                               3297            4591 :         char       *argname = argnames ? argnames[i] : NULL;
                               3298            4591 :         char        argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
 5378 tgl                      3299 ECB             :         const char *modename;
 5050 bruce                    3300                 :         bool        isinput;
 5378 tgl                      3301                 : 
 5378 tgl                      3302 CBC        4591 :         switch (argmode)
 5378 tgl                      3303 ECB             :         {
 5378 tgl                      3304 CBC        3860 :             case PROARGMODE_IN:
  668 tgl                      3305 ECB             : 
                               3306                 :                 /*
                               3307                 :                  * For procedures, explicitly mark all argument modes, so as
                               3308                 :                  * to avoid ambiguity with the SQL syntax for DROP PROCEDURE.
                               3309                 :                  */
  668 tgl                      3310 CBC        3860 :                 if (proc->prokind == PROKIND_PROCEDURE)
                               3311             263 :                     modename = "IN ";
  668 tgl                      3312 ECB             :                 else
  668 tgl                      3313 GBC        3597 :                     modename = "";
 5225                          3314            3860 :                 isinput = true;
 5378 tgl                      3315 GIC        3860 :                 break;
                               3316              20 :             case PROARGMODE_INOUT:
                               3317              20 :                 modename = "INOUT ";
 5225                          3318              20 :                 isinput = true;
 5378 tgl                      3319 CBC          20 :                 break;
                               3320             472 :             case PROARGMODE_OUT:
 5378 tgl                      3321 GIC         472 :                 modename = "OUT ";
 5225 tgl                      3322 CBC         472 :                 isinput = false;
 5378                          3323             472 :                 break;
 5378 tgl                      3324 GIC          89 :             case PROARGMODE_VARIADIC:
 5378 tgl                      3325 CBC          89 :                 modename = "VARIADIC ";
 5225 tgl                      3326 GIC          89 :                 isinput = true;
 5378 tgl                      3327 CBC          89 :                 break;
                               3328             150 :             case PROARGMODE_TABLE:
                               3329             150 :                 modename = "";
 5225 tgl                      3330 GIC         150 :                 isinput = false;
 5378 tgl                      3331 CBC         150 :                 break;
 5378 tgl                      3332 LBC           0 :             default:
 5378 tgl                      3333 UIC           0 :                 elog(ERROR, "invalid parameter mode '%c'", argmode);
 5050 bruce                    3334 ECB             :                 modename = NULL;    /* keep compiler quiet */
 5225 tgl                      3335                 :                 isinput = false;
 5378                          3336                 :                 break;
                               3337                 :         }
 5225 tgl                      3338 CBC        4591 :         if (isinput)
 5225 tgl                      3339 GIC        3969 :             inputargno++;       /* this is a 1-based counter */
                               3340                 : 
                               3341            4591 :         if (print_table_args != (argmode == PROARGMODE_TABLE))
 5225 tgl                      3342 CBC         364 :             continue;
 5225 tgl                      3343 ECB             : 
 3394 tgl                      3344 CBC        4227 :         if (argsprinted == insertorderbyat)
                               3345                 :         {
                               3346              26 :             if (argsprinted)
 3394 tgl                      3347 GIC          26 :                 appendStringInfoChar(buf, ' ');
                               3348              26 :             appendStringInfoString(buf, "ORDER BY ");
 3394 tgl                      3349 ECB             :         }
 3394 tgl                      3350 GIC        4201 :         else if (argsprinted)
 5378                          3351            1314 :             appendStringInfoString(buf, ", ");
 3394 tgl                      3352 ECB             : 
 5378 tgl                      3353 GIC        4227 :         appendStringInfoString(buf, modename);
 5225 tgl                      3354 CBC        4227 :         if (argname && argname[0])
 5052 tgl                      3355 GIC        1446 :             appendStringInfo(buf, "%s ", quote_identifier(argname));
 5378 tgl                      3356 CBC        4227 :         appendStringInfoString(buf, format_type_be(argtype));
 5225 tgl                      3357 GIC        4227 :         if (print_defaults && isinput && inputargno > nlackdefaults)
                               3358                 :         {
                               3359                 :             Node       *expr;
 5239 peter_e                  3360 ECB             : 
 5225 tgl                      3361 GIC          25 :             Assert(nextargdefault != NULL);
                               3362              25 :             expr = (Node *) lfirst(nextargdefault);
 1364                          3363              25 :             nextargdefault = lnext(argdefaults, nextargdefault);
 5239 peter_e                  3364 ECB             : 
 5225 tgl                      3365 GIC          25 :             appendStringInfo(buf, " DEFAULT %s",
                               3366                 :                              deparse_expression(expr, NIL, false, false));
 5225 tgl                      3367 ECB             :         }
 5378 tgl                      3368 CBC        4227 :         argsprinted++;
 3394 tgl                      3369 ECB             : 
                               3370                 :         /* nasty hack: print the last arg twice for variadic ordered-set agg */
 3394 tgl                      3371 GIC        4227 :         if (argsprinted == insertorderbyat && i == numargs - 1)
                               3372                 :         {
                               3373              13 :             i--;
                               3374                 :             /* aggs shouldn't have defaults anyway, but just to be sure ... */
                               3375              13 :             print_defaults = false;
 3394 tgl                      3376 ECB             :         }
                               3377                 :     }
                               3378                 : 
 5378 tgl                      3379 GIC        4448 :     return argsprinted;
                               3380                 : }
 5378 tgl                      3381 ECB             : 
 3421 peter_e                  3382                 : static bool
 3421 peter_e                  3383 GIC          48 : is_input_argument(int nth, const char *argmodes)
                               3384                 : {
                               3385                 :     return (!argmodes
 3421 peter_e                  3386 CBC          21 :             || argmodes[nth] == PROARGMODE_IN
                               3387               9 :             || argmodes[nth] == PROARGMODE_INOUT
 3421 peter_e                  3388 GIC          69 :             || argmodes[nth] == PROARGMODE_VARIADIC);
 3421 peter_e                  3389 ECB             : }
                               3390                 : 
 2905                          3391                 : /*
                               3392                 :  * Append used transformed types to specified buffer
                               3393                 :  */
                               3394                 : static void
 2905 peter_e                  3395 CBC          70 : print_function_trftypes(StringInfo buf, HeapTuple proctup)
                               3396                 : {
                               3397                 :     Oid        *trftypes;
                               3398                 :     int         ntypes;
                               3399                 : 
 2905 peter_e                  3400 GIC          70 :     ntypes = get_func_trftypes(proctup, &trftypes);
                               3401              70 :     if (ntypes > 0)
                               3402                 :     {
                               3403                 :         int         i;
 2905 peter_e                  3404 ECB             : 
  804 tgl                      3405 GIC           3 :         appendStringInfoString(buf, " TRANSFORM ");
 2905 peter_e                  3406 CBC           8 :         for (i = 0; i < ntypes; i++)
 2905 peter_e                  3407 ECB             :         {
 2905 peter_e                  3408 GIC           5 :             if (i != 0)
                               3409               2 :                 appendStringInfoString(buf, ", ");
 2894 magnus                   3410               5 :             appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
                               3411                 :         }
  804 tgl                      3412               3 :         appendStringInfoChar(buf, '\n');
                               3413                 :     }
 2905 peter_e                  3414              70 : }
                               3415                 : 
                               3416                 : /*
                               3417                 :  * Get textual representation of a function argument's default value.  The
                               3418                 :  * second argument of this function is the argument number among all arguments
                               3419                 :  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
                               3420                 :  * how information_schema.sql uses it.
                               3421                 :  */
                               3422                 : Datum
 3421 peter_e                  3423 CBC          27 : pg_get_function_arg_default(PG_FUNCTION_ARGS)
 3421 peter_e                  3424 ECB             : {
 3421 peter_e                  3425 CBC          27 :     Oid         funcid = PG_GETARG_OID(0);
 3421 peter_e                  3426 GIC          27 :     int32       nth_arg = PG_GETARG_INT32(1);
 3421 peter_e                  3427 ECB             :     HeapTuple   proctup;
                               3428                 :     Form_pg_proc proc;
                               3429                 :     int         numargs;
                               3430                 :     Oid        *argtypes;
                               3431                 :     char      **argnames;
                               3432                 :     char       *argmodes;
                               3433                 :     int         i;
                               3434                 :     List       *argdefaults;
                               3435                 :     Node       *node;
                               3436                 :     char       *str;
                               3437                 :     int         nth_inputarg;
                               3438                 :     Datum       proargdefaults;
                               3439                 :     bool        isnull;
                               3440                 :     int         nth_default;
                               3441                 : 
 3421 peter_e                  3442 CBC          27 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 3421 peter_e                  3443 GIC          27 :     if (!HeapTupleIsValid(proctup))
 2445 rhaas                    3444 GBC           6 :         PG_RETURN_NULL();
 3421 peter_e                  3445 EUB             : 
 3421 peter_e                  3446 GIC          21 :     numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes);
                               3447              21 :     if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes))
 3421 peter_e                  3448 ECB             :     {
 3421 peter_e                  3449 CBC           6 :         ReleaseSysCache(proctup);
                               3450               6 :         PG_RETURN_NULL();
                               3451                 :     }
 3421 peter_e                  3452 ECB             : 
 3421 peter_e                  3453 GIC          15 :     nth_inputarg = 0;
                               3454              42 :     for (i = 0; i < nth_arg; i++)
                               3455              27 :         if (is_input_argument(i, argmodes))
                               3456              24 :             nth_inputarg++;
                               3457                 : 
 3421 peter_e                  3458 CBC          15 :     proargdefaults = SysCacheGetAttr(PROCOID, proctup,
                               3459                 :                                      Anum_pg_proc_proargdefaults,
 3421 peter_e                  3460 ECB             :                                      &isnull);
 3421 peter_e                  3461 GIC          15 :     if (isnull)
 3421 peter_e                  3462 ECB             :     {
 3421 peter_e                  3463 LBC           0 :         ReleaseSysCache(proctup);
 3421 peter_e                  3464 UIC           0 :         PG_RETURN_NULL();
 3421 peter_e                  3465 ECB             :     }
                               3466                 : 
 3421 peter_e                  3467 GIC          15 :     str = TextDatumGetCString(proargdefaults);
 2238 peter_e                  3468 CBC          15 :     argdefaults = castNode(List, stringToNode(str));
 3421 peter_e                  3469 GIC          15 :     pfree(str);
 3421 peter_e                  3470 ECB             : 
 3421 peter_e                  3471 GIC          15 :     proc = (Form_pg_proc) GETSTRUCT(proctup);
                               3472                 : 
                               3473                 :     /*
 3260 bruce                    3474 ECB             :      * Calculate index into proargdefaults: proargdefaults corresponds to the
                               3475                 :      * last N input arguments, where N = pronargdefaults.
                               3476                 :      */
 3421 peter_e                  3477 GIC          15 :     nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults);
                               3478                 : 
                               3479              15 :     if (nth_default < 0 || nth_default >= list_length(argdefaults))
 3421 peter_e                  3480 ECB             :     {
 3421 peter_e                  3481 GIC           3 :         ReleaseSysCache(proctup);
                               3482               3 :         PG_RETURN_NULL();
                               3483                 :     }
 3421 peter_e                  3484 CBC          12 :     node = list_nth(argdefaults, nth_default);
                               3485              12 :     str = deparse_expression(node, NIL, false, false);
                               3486                 : 
                               3487              12 :     ReleaseSysCache(proctup);
 3421 peter_e                  3488 ECB             : 
 3421 peter_e                  3489 GIC          12 :     PG_RETURN_TEXT_P(string_to_text(str));
 3421 peter_e                  3490 ECB             : }
                               3491                 : 
                               3492                 : static void
  732 peter                    3493 CBC          54 : print_function_sqlbody(StringInfo buf, HeapTuple proctup)
                               3494                 : {
                               3495                 :     int         numargs;
                               3496                 :     Oid        *argtypes;
                               3497                 :     char      **argnames;
  732 peter                    3498 ECB             :     char       *argmodes;
  732 peter                    3499 GIC          54 :     deparse_namespace dpns = {0};
  732 peter                    3500 ECB             :     Datum       tmp;
                               3501                 :     Node       *n;
                               3502                 : 
  732 peter                    3503 CBC          54 :     dpns.funcname = pstrdup(NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname));
  732 peter                    3504 GIC          54 :     numargs = get_func_arg_info(proctup,
                               3505                 :                                 &argtypes, &argnames, &argmodes);
  732 peter                    3506 CBC          54 :     dpns.numargs = numargs;
                               3507              54 :     dpns.argnames = argnames;
                               3508                 : 
   15 dgustafsson              3509 GNC          54 :     tmp = SysCacheGetAttrNotNull(PROCOID, proctup, Anum_pg_proc_prosqlbody);
  732 peter                    3510 GIC          54 :     n = stringToNode(TextDatumGetCString(tmp));
                               3511                 : 
  732 peter                    3512 CBC          54 :     if (IsA(n, List))
                               3513                 :     {
                               3514                 :         List       *stmts;
                               3515                 :         ListCell   *lc;
  732 peter                    3516 ECB             : 
  732 peter                    3517 GIC          32 :         stmts = linitial(castNode(List, n));
                               3518                 : 
  732 peter                    3519 CBC          32 :         appendStringInfoString(buf, "BEGIN ATOMIC\n");
  732 peter                    3520 ECB             : 
  732 peter                    3521 GIC          59 :         foreach(lc, stmts)
                               3522                 :         {
  732 peter                    3523 CBC          27 :             Query      *query = lfirst_node(Query, lc);
                               3524                 : 
                               3525                 :             /* It seems advisable to get at least AccessShareLock on rels */
  586 tgl                      3526              27 :             AcquireRewriteLocks(query, false, false);
  323 tgl                      3527 GIC          27 :             get_query_def(query, buf, list_make1(&dpns), NULL, false,
  586 tgl                      3528 ECB             :                           PRETTYFLAG_INDENT, WRAP_COLUMN_DEFAULT, 1);
  732 peter                    3529 GIC          27 :             appendStringInfoChar(buf, ';');
                               3530              27 :             appendStringInfoChar(buf, '\n');
                               3531                 :         }
                               3532                 : 
  732 peter                    3533 CBC          32 :         appendStringInfoString(buf, "END");
                               3534                 :     }
                               3535                 :     else
  732 peter                    3536 ECB             :     {
  586 tgl                      3537 CBC          22 :         Query      *query = castNode(Query, n);
  586 tgl                      3538 EUB             : 
                               3539                 :         /* It seems advisable to get at least AccessShareLock on rels */
  586 tgl                      3540 CBC          22 :         AcquireRewriteLocks(query, false, false);
  323                          3541              22 :         get_query_def(query, buf, list_make1(&dpns), NULL, false,
                               3542                 :                       0, WRAP_COLUMN_DEFAULT, 0);
  732 peter                    3543 ECB             :     }
  732 peter                    3544 CBC          54 : }
                               3545                 : 
                               3546                 : Datum
                               3547            1686 : pg_get_function_sqlbody(PG_FUNCTION_ARGS)
                               3548                 : {
                               3549            1686 :     Oid         funcid = PG_GETARG_OID(0);
                               3550                 :     StringInfoData buf;
  732 peter                    3551 ECB             :     HeapTuple   proctup;
                               3552                 :     bool        isnull;
                               3553                 : 
  732 peter                    3554 GIC        1686 :     initStringInfo(&buf);
                               3555                 : 
                               3556                 :     /* Look up the function */
                               3557            1686 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
                               3558            1686 :     if (!HeapTupleIsValid(proctup))
  732 peter                    3559 UIC           0 :         PG_RETURN_NULL();
                               3560                 : 
  586 tgl                      3561 CBC        1686 :     (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosqlbody, &isnull);
  732 peter                    3562 GIC        1686 :     if (isnull)
                               3563                 :     {
  732 peter                    3564 CBC        1671 :         ReleaseSysCache(proctup);
  732 peter                    3565 GIC        1671 :         PG_RETURN_NULL();
                               3566                 :     }
                               3567                 : 
                               3568              15 :     print_function_sqlbody(&buf, proctup);
                               3569                 : 
                               3570              15 :     ReleaseSysCache(proctup);
                               3571                 : 
  215 drowley                  3572 GNC          15 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(buf.data, buf.len));
                               3573                 : }
                               3574                 : 
                               3575                 : 
                               3576                 : /*
                               3577                 :  * deparse_expression           - General utility for deparsing expressions
                               3578                 :  *
                               3579                 :  * calls deparse_expression_pretty with all prettyPrinting disabled
                               3580                 :  */
                               3581                 : char *
 7193 tgl                      3582 GIC       28781 : deparse_expression(Node *expr, List *dpcontext,
                               3583                 :                    bool forceprefix, bool showimplicit)
                               3584                 : {
 7188 bruce                    3585           28781 :     return deparse_expression_pretty(expr, dpcontext, forceprefix,
                               3586                 :                                      showimplicit, 0, 0);
                               3587                 : }
 7193 tgl                      3588 ECB             : 
                               3589                 : /* ----------
                               3590                 :  * deparse_expression_pretty    - General utility for deparsing expressions
                               3591                 :  *
                               3592                 :  * expr is the node tree to be deparsed.  It must be a transformed expression
                               3593                 :  * tree (ie, not the raw output of gram.y).
                               3594                 :  *
 8089                          3595                 :  * dpcontext is a list of deparse_namespace nodes representing the context
 3260 bruce                    3596                 :  * for interpreting Vars in the node tree.  It can be NIL if no Vars are
 3751 tgl                      3597                 :  * expected.
 8589                          3598                 :  *
 2062 peter_e                  3599                 :  * forceprefix is true to force all Vars to be prefixed with their table names.
 8589 tgl                      3600                 :  *
 2062 peter_e                  3601                 :  * showimplicit is true to force all implicit casts to be shown explicitly.
 7188 bruce                    3602                 :  *
 3751 tgl                      3603                 :  * Tries to pretty up the output according to prettyFlags and startIndent.
 7507                          3604                 :  *
 8589                          3605                 :  * The result is a palloc'd string.
                               3606                 :  * ----------
                               3607                 :  */
                               3608                 : static char *
 7193 tgl                      3609 CBC       34079 : deparse_expression_pretty(Node *expr, List *dpcontext,
                               3610                 :                           bool forceprefix, bool showimplicit,
                               3611                 :                           int prettyFlags, int startIndent)
                               3612                 : {
                               3613                 :     StringInfoData buf;
                               3614                 :     deparse_context context;
                               3615                 : 
 8589 tgl                      3616 GIC       34079 :     initStringInfo(&buf);
                               3617           34079 :     context.buf = &buf;
 8089                          3618           34079 :     context.namespaces = dpcontext;
 5215                          3619           34079 :     context.windowClause = NIL;
                               3620           34079 :     context.windowTList = NIL;
 8089 tgl                      3621 CBC       34079 :     context.varprefix = forceprefix;
 7193 tgl                      3622 GIC       34079 :     context.prettyFlags = prettyFlags;
 3758                          3623           34079 :     context.wrapColumn = WRAP_COLUMN_DEFAULT;
 7193                          3624           34079 :     context.indentLevel = startIndent;
 2885 andres                   3625           34079 :     context.special_exprkind = EXPR_KIND_NONE;
 1215 tgl                      3626 CBC       34079 :     context.appendparents = NULL;
                               3627                 : 
 7507 tgl                      3628 GIC       34079 :     get_rule_expr(expr, &context, showimplicit);
 8589 tgl                      3629 ECB             : 
 8589 tgl                      3630 CBC       34079 :     return buf.data;
 8589 tgl                      3631 ECB             : }
 8955 bruce                    3632                 : 
 8089 tgl                      3633                 : /* ----------
                               3634                 :  * deparse_context_for          - Build deparse context for a single relation
                               3635                 :  *
 7688                          3636                 :  * Given the reference name (alias) and OID of a relation, build deparsing
                               3637                 :  * context for an expression referencing only that relation (as varno 1,
 3260 bruce                    3638                 :  * varlevelsup 0).  This is sufficient for many uses of deparse_expression.
                               3639                 :  * ----------
                               3640                 :  */
 8089 tgl                      3641                 : List *
 7688 tgl                      3642 CBC        9629 : deparse_context_for(const char *aliasname, Oid relid)
 8089 tgl                      3643 ECB             : {
                               3644                 :     deparse_namespace *dpns;
                               3645                 :     RangeTblEntry *rte;
                               3646                 : 
 4653 tgl                      3647 GIC        9629 :     dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
                               3648                 : 
 8089 tgl                      3649 ECB             :     /* Build a minimal RTE for the rel */
 8089 tgl                      3650 GIC        9629 :     rte = makeNode(RangeTblEntry);
 7698                          3651            9629 :     rte->rtekind = RTE_RELATION;
 8089                          3652            9629 :     rte->relid = relid;
 4429                          3653            9629 :     rte->relkind = RELKIND_RELATION; /* no need for exactness here */
 1652                          3654            9629 :     rte->rellockmode = AccessShareLock;
 3852                          3655            9629 :     rte->alias = makeAlias(aliasname, NIL);
                               3656            9629 :     rte->eref = rte->alias;
 3897                          3657            9629 :     rte->lateral = false;
 8089                          3658            9629 :     rte->inh = false;
                               3659            9629 :     rte->inFromCl = true;
                               3660                 : 
                               3661                 :     /* Build one-element rtable */
 6888 neilc                    3662            9629 :     dpns->rtable = list_make1(rte);
 1215 tgl                      3663            9629 :     dpns->subplans = NIL;
 5298                          3664            9629 :     dpns->ctes = NIL;
 1215                          3665            9629 :     dpns->appendrels = NULL;
 3852 tgl                      3666 CBC        9629 :     set_rtable_names(dpns, NIL, NULL);
 3751 tgl                      3667 GIC        9629 :     set_simple_column_names(dpns);
                               3668                 : 
                               3669                 :     /* Return a one-deep namespace stack */
 6888 neilc                    3670 CBC        9629 :     return list_make1(dpns);
                               3671                 : }
                               3672                 : 
 7698 tgl                      3673 ECB             : /*
 1215                          3674                 :  * deparse_context_for_plan_tree - Build deparse context for a Plan tree
 3006                          3675                 :  *
                               3676                 :  * When deparsing an expression in a Plan tree, we use the plan's rangetable
                               3677                 :  * to resolve names of simple Vars.  The initialization of column names for
                               3678                 :  * this is rather expensive if the rangetable is large, and it'll be the same
                               3679                 :  * for every expression in the Plan tree; so we do it just once and re-use
                               3680                 :  * the result of this function for each expression.  (Note that the result
                               3681                 :  * is not usable until set_deparse_context_plan() is applied to it.)
                               3682                 :  *
 1215                          3683                 :  * In addition to the PlannedStmt, pass the per-RTE alias names
 3006                          3684                 :  * assigned by a previous call to select_rtable_names_for_explain.
                               3685                 :  */
                               3686                 : List *
 1215 tgl                      3687 CBC        9874 : deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names)
 3006 tgl                      3688 ECB             : {
                               3689                 :     deparse_namespace *dpns;
                               3690                 : 
 3006 tgl                      3691 CBC        9874 :     dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
 3006 tgl                      3692 ECB             : 
                               3693                 :     /* Initialize fields that stay the same across the whole plan tree */
 1215 tgl                      3694 GIC        9874 :     dpns->rtable = pstmt->rtable;
 3006                          3695            9874 :     dpns->rtable_names = rtable_names;
 1215 tgl                      3696 CBC        9874 :     dpns->subplans = pstmt->subplans;
 3006 tgl                      3697 GIC        9874 :     dpns->ctes = NIL;
 1215                          3698            9874 :     if (pstmt->appendRelations)
                               3699                 :     {
                               3700                 :         /* Set up the array, indexed by child relid */
                               3701            1637 :         int         ntables = list_length(dpns->rtable);
                               3702                 :         ListCell   *lc;
 1215 tgl                      3703 ECB             : 
 1215 tgl                      3704 GIC        1637 :         dpns->appendrels = (AppendRelInfo **)
                               3705            1637 :             palloc0((ntables + 1) * sizeof(AppendRelInfo *));
 1215 tgl                      3706 CBC        9266 :         foreach(lc, pstmt->appendRelations)
                               3707                 :         {
 1215 tgl                      3708 GIC        7629 :             AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
                               3709            7629 :             Index       crelid = appinfo->child_relid;
                               3710                 : 
                               3711            7629 :             Assert(crelid > 0 && crelid <= ntables);
                               3712            7629 :             Assert(dpns->appendrels[crelid] == NULL);
                               3713            7629 :             dpns->appendrels[crelid] = appinfo;
                               3714                 :         }
                               3715                 :     }
                               3716                 :     else
                               3717            8237 :         dpns->appendrels = NULL; /* don't need it */
                               3718                 : 
                               3719                 :     /*
                               3720                 :      * Set up column name aliases.  We will get rather bogus results for join
                               3721                 :      * RTEs, but that doesn't matter because plan trees don't contain any join
                               3722                 :      * alias Vars.
                               3723                 :      */
 3006                          3724            9874 :     set_simple_column_names(dpns);
                               3725                 : 
                               3726                 :     /* Return a one-deep namespace stack */
                               3727            9874 :     return list_make1(dpns);
                               3728                 : }
                               3729                 : 
                               3730                 : /*
                               3731                 :  * set_deparse_context_plan - Specify Plan node containing expression
                               3732                 :  *
                               3733                 :  * When deparsing an expression in a Plan tree, we might have to resolve
                               3734                 :  * OUTER_VAR, INNER_VAR, or INDEX_VAR references.  To do this, the caller must
 1215 tgl                      3735 ECB             :  * provide the parent Plan node.  Then OUTER_VAR and INNER_VAR references
                               3736                 :  * can be resolved by drilling down into the left and right child plans.
                               3737                 :  * Similarly, INDEX_VAR references can be resolved by reference to the
                               3738                 :  * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in
                               3739                 :  * ForeignScan and CustomScan nodes.  (Note that we don't currently support
 2891                          3740                 :  * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes;
                               3741                 :  * for those, we can only deparse the indexqualorig fields, which won't
                               3742                 :  * contain INDEX_VAR Vars.)
                               3743                 :  *
 1215                          3744                 :  * The ancestors list is a list of the Plan's parent Plan and SubPlan nodes,
                               3745                 :  * the most-closely-nested first.  This is needed to resolve PARAM_EXEC
                               3746                 :  * Params.  Note we assume that all the Plan nodes share the same rtable.
 7605                          3747                 :  *
                               3748                 :  * Once this function has been called, deparse_expression() can be called on
                               3749                 :  * subsidiary expression(s) of the specified Plan node.  To deparse
                               3750                 :  * expressions of a different Plan node in the same Plan tree, re-call this
                               3751                 :  * function to identify the new parent Plan node.
                               3752                 :  *
                               3753                 :  * The result is the same List passed in; this is a notational convenience.
                               3754                 :  */
                               3755                 : List *
 1215 tgl                      3756 GIC       21439 : set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors)
                               3757                 : {
 7698 tgl                      3758 ECB             :     deparse_namespace *dpns;
                               3759                 : 
                               3760                 :     /* Should always have one-entry namespace list for Plan deparsing */
 3006 tgl                      3761 GIC       21439 :     Assert(list_length(dpcontext) == 1);
 3006 tgl                      3762 CBC       21439 :     dpns = (deparse_namespace *) linitial(dpcontext);
 3751 tgl                      3763 ECB             : 
 4653                          3764                 :     /* Set our attention on the specific plan node passed in */
 4653 tgl                      3765 CBC       21439 :     dpns->ancestors = ancestors;
  545                          3766           21439 :     set_deparse_plan(dpns, plan);
 4653 tgl                      3767 ECB             : 
 3006 tgl                      3768 GIC       21439 :     return dpcontext;
                               3769                 : }
 4653 tgl                      3770 ECB             : 
                               3771                 : /*
                               3772                 :  * select_rtable_names_for_explain  - Select RTE aliases for EXPLAIN
                               3773                 :  *
                               3774                 :  * Determine the relation aliases we'll use during an EXPLAIN operation.
                               3775                 :  * This is just a frontend to set_rtable_names.  We have to expose the aliases
                               3776                 :  * to EXPLAIN because EXPLAIN needs to know the right alias names to print.
                               3777                 :  */
                               3778                 : List *
 3852 tgl                      3779 GIC        9874 : select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used)
                               3780                 : {
                               3781                 :     deparse_namespace dpns;
                               3782                 : 
                               3783            9874 :     memset(&dpns, 0, sizeof(dpns));
                               3784            9874 :     dpns.rtable = rtable;
 1215                          3785            9874 :     dpns.subplans = NIL;
 3852                          3786            9874 :     dpns.ctes = NIL;
 1215 tgl                      3787 CBC        9874 :     dpns.appendrels = NULL;
 3852 tgl                      3788 GIC        9874 :     set_rtable_names(&dpns, NIL, rels_used);
                               3789                 :     /* We needn't bother computing column aliases yet */
                               3790                 : 
                               3791            9874 :     return dpns.rtable_names;
                               3792                 : }
                               3793                 : 
                               3794                 : /*
                               3795                 :  * set_rtable_names: select RTE aliases to be used in printing a query
                               3796                 :  *
 3852 tgl                      3797 ECB             :  * We fill in dpns->rtable_names with a list of names that is one-for-one with
                               3798                 :  * the already-filled dpns->rtable list.  Each RTE name is unique among those
                               3799                 :  * in the new namespace plus any ancestor namespaces listed in
                               3800                 :  * parent_namespaces.
                               3801                 :  *
                               3802                 :  * If rels_used isn't NULL, only RTE indexes listed in it are given aliases.
                               3803                 :  *
                               3804                 :  * Note that this function is only concerned with relation names, not column
                               3805                 :  * names.
                               3806                 :  */
                               3807                 : static void
 3852 tgl                      3808 CBC       21939 : set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
 3852 tgl                      3809 ECB             :                  Bitmapset *rels_used)
                               3810                 : {
                               3811                 :     HASHCTL     hash_ctl;
                               3812                 :     HTAB       *names_hash;
                               3813                 :     NameHashEntry *hentry;
                               3814                 :     bool        found;
 2701                          3815                 :     int         rtindex;
                               3816                 :     ListCell   *lc;
 3852                          3817                 : 
 3852 tgl                      3818 GIC       21939 :     dpns->rtable_names = NIL;
                               3819                 :     /* nothing more to do if empty rtable */
 2701 tgl                      3820 CBC       21939 :     if (dpns->rtable == NIL)
 2701 tgl                      3821 GIC         232 :         return;
 2701 tgl                      3822 ECB             : 
                               3823                 :     /*
                               3824                 :      * We use a hash table to hold known names, so that this process is O(N)
                               3825                 :      * not O(N^2) for N names.
                               3826                 :      */
 2701 tgl                      3827 GIC       21707 :     hash_ctl.keysize = NAMEDATALEN;
                               3828           21707 :     hash_ctl.entrysize = sizeof(NameHashEntry);
                               3829           21707 :     hash_ctl.hcxt = CurrentMemoryContext;
                               3830           21707 :     names_hash = hash_create("set_rtable_names names",
 2701 tgl                      3831 CBC       21707 :                              list_length(dpns->rtable),
                               3832                 :                              &hash_ctl,
                               3833                 :                              HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
                               3834                 : 
                               3835                 :     /* Preload the hash table with names appearing in parent_namespaces */
                               3836           22365 :     foreach(lc, parent_namespaces)
 2701 tgl                      3837 ECB             :     {
 2701 tgl                      3838 GIC         658 :         deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc);
 2701 tgl                      3839 ECB             :         ListCell   *lc2;
                               3840                 : 
 2701 tgl                      3841 GIC        2189 :         foreach(lc2, olddpns->rtable_names)
                               3842                 :         {
 2701 tgl                      3843 CBC        1531 :             char       *oldname = (char *) lfirst(lc2);
                               3844                 : 
                               3845            1531 :             if (oldname == NULL)
 2701 tgl                      3846 GIC         114 :                 continue;
                               3847            1417 :             hentry = (NameHashEntry *) hash_search(names_hash,
 2701 tgl                      3848 ECB             :                                                    oldname,
                               3849                 :                                                    HASH_ENTER,
                               3850                 :                                                    &found);
                               3851                 :             /* we do not complain about duplicate names in parent namespaces */
 2701 tgl                      3852 GIC        1417 :             hentry->counter = 0;
 2701 tgl                      3853 ECB             :         }
                               3854                 :     }
                               3855                 : 
                               3856                 :     /* Now we can scan the rtable */
 2701 tgl                      3857 GIC       21707 :     rtindex = 1;
 3852 tgl                      3858 CBC       60652 :     foreach(lc, dpns->rtable)
                               3859                 :     {
                               3860           38945 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
                               3861                 :         char       *refname;
                               3862                 : 
 2701 tgl                      3863 ECB             :         /* Just in case this takes an unreasonable amount of time ... */
 2701 tgl                      3864 GIC       38945 :         CHECK_FOR_INTERRUPTS();
                               3865                 : 
 3852                          3866           38945 :         if (rels_used && !bms_is_member(rtindex, rels_used))
                               3867                 :         {
 3852 tgl                      3868 ECB             :             /* Ignore unreferenced RTE */
 3852 tgl                      3869 GIC        5831 :             refname = NULL;
                               3870                 :         }
                               3871           33114 :         else if (rte->alias)
                               3872                 :         {
                               3873                 :             /* If RTE has a user-defined alias, prefer that */
                               3874           21727 :             refname = rte->alias->aliasname;
                               3875                 :         }
                               3876           11387 :         else if (rte->rtekind == RTE_RELATION)
 3852 tgl                      3877 ECB             :         {
                               3878                 :             /* Use the current actual name of the relation */
 3852 tgl                      3879 CBC        9798 :             refname = get_rel_name(rte->relid);
                               3880                 :         }
 3852 tgl                      3881 GIC        1589 :         else if (rte->rtekind == RTE_JOIN)
                               3882                 :         {
 3852 tgl                      3883 ECB             :             /* Unnamed join has no refname */
 3852 tgl                      3884 GIC         630 :             refname = NULL;
                               3885                 :         }
 3852 tgl                      3886 ECB             :         else
                               3887                 :         {
                               3888                 :             /* Otherwise use whatever the parser assigned */
 3852 tgl                      3889 GIC         959 :             refname = rte->eref->aliasname;
                               3890                 :         }
                               3891                 : 
 3852 tgl                      3892 ECB             :         /*
                               3893                 :          * If the selected name isn't unique, append digits to make it so, and
                               3894                 :          * make a new hash entry for it once we've got a unique name.  For a
 2701                          3895                 :          * very long input name, we might have to truncate to stay within
                               3896                 :          * NAMEDATALEN.
 3852                          3897                 :          */
 2701 tgl                      3898 CBC       38945 :         if (refname)
                               3899                 :         {
                               3900           32484 :             hentry = (NameHashEntry *) hash_search(names_hash,
                               3901                 :                                                    refname,
                               3902                 :                                                    HASH_ENTER,
 2701 tgl                      3903 ECB             :                                                    &found);
 2701 tgl                      3904 GIC       32484 :             if (found)
                               3905                 :             {
                               3906                 :                 /* Name already in use, must choose a new one */
 2701 tgl                      3907 CBC        6241 :                 int         refnamelen = strlen(refname);
                               3908            6241 :                 char       *modname = (char *) palloc(refnamelen + 16);
 2701 tgl                      3909 ECB             :                 NameHashEntry *hentry2;
                               3910                 : 
                               3911                 :                 do
                               3912                 :                 {
 2701 tgl                      3913 GIC        6244 :                     hentry->counter++;
 2701 tgl                      3914 ECB             :                     for (;;)
                               3915                 :                     {
 2701 tgl                      3916 GIC        6250 :                         memcpy(modname, refname, refnamelen);
                               3917            6250 :                         sprintf(modname + refnamelen, "_%d", hentry->counter);
 2701 tgl                      3918 CBC        6250 :                         if (strlen(modname) < NAMEDATALEN)
                               3919            6244 :                             break;
                               3920                 :                         /* drop chars from refname to keep all the digits */
 2701 tgl                      3921 GIC           6 :                         refnamelen = pg_mbcliplen(refname, refnamelen,
 2701 tgl                      3922 ECB             :                                                   refnamelen - 1);
                               3923                 :                     }
 2701 tgl                      3924 GIC        6244 :                     hentry2 = (NameHashEntry *) hash_search(names_hash,
                               3925                 :                                                             modname,
                               3926                 :                                                             HASH_ENTER,
                               3927                 :                                                             &found);
                               3928            6244 :                 } while (found);
                               3929            6241 :                 hentry2->counter = 0;    /* init new hash entry */
                               3930            6241 :                 refname = modname;
                               3931                 :             }
 2701 tgl                      3932 ECB             :             else
                               3933                 :             {
                               3934                 :                 /* Name not previously used, need only initialize hentry */
 2701 tgl                      3935 GIC       26243 :                 hentry->counter = 0;
                               3936                 :             }
                               3937                 :         }
                               3938                 : 
 3852 tgl                      3939 CBC       38945 :         dpns->rtable_names = lappend(dpns->rtable_names, refname);
                               3940           38945 :         rtindex++;
 3852 tgl                      3941 ECB             :     }
                               3942                 : 
 2701 tgl                      3943 CBC       21707 :     hash_destroy(names_hash);
                               3944                 : }
                               3945                 : 
 3751 tgl                      3946 ECB             : /*
                               3947                 :  * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree
                               3948                 :  *
                               3949                 :  * For convenience, this is defined to initialize the deparse_namespace struct
                               3950                 :  * from scratch.
                               3951                 :  */
                               3952                 : static void
 3751 tgl                      3953 GIC        2364 : set_deparse_for_query(deparse_namespace *dpns, Query *query,
                               3954                 :                       List *parent_namespaces)
 3751 tgl                      3955 ECB             : {
                               3956                 :     ListCell   *lc;
                               3957                 :     ListCell   *lc2;
                               3958                 : 
                               3959                 :     /* Initialize *dpns and fill rtable/ctes links */
 3751 tgl                      3960 GIC        2364 :     memset(dpns, 0, sizeof(deparse_namespace));
                               3961            2364 :     dpns->rtable = query->rtable;
 1215                          3962            2364 :     dpns->subplans = NIL;
 3751                          3963            2364 :     dpns->ctes = query->cteList;
 1215                          3964            2364 :     dpns->appendrels = NULL;
 3751 tgl                      3965 ECB             : 
                               3966                 :     /* Assign a unique relation alias to each RTE */
 3751 tgl                      3967 GIC        2364 :     set_rtable_names(dpns, parent_namespaces, NULL);
                               3968                 : 
                               3969                 :     /* Initialize dpns->rtable_columns to contain zeroed structs */
                               3970            2364 :     dpns->rtable_columns = NIL;
                               3971            6395 :     while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
                               3972            4031 :         dpns->rtable_columns = lappend(dpns->rtable_columns,
                               3973                 :                                        palloc0(sizeof(deparse_columns)));
                               3974                 : 
                               3975                 :     /* If it's a utility query, it won't have a jointree */
 3615 tgl                      3976 CBC        2364 :     if (query->jointree)
                               3977                 :     {
 3615 tgl                      3978 ECB             :         /* Detect whether global uniqueness of USING names is needed */
 3615 tgl                      3979 CBC        2356 :         dpns->unique_using =
 3547 tgl                      3980 GIC        2356 :             has_dangerous_join_using(dpns, (Node *) query->jointree);
 3751 tgl                      3981 ECB             : 
 3615                          3982                 :         /*
                               3983                 :          * Select names for columns merged by USING, via a recursive pass over
                               3984                 :          * the query jointree.
                               3985                 :          */
 3265 tgl                      3986 CBC        2356 :         set_using_names(dpns, (Node *) query->jointree, NIL);
                               3987                 :     }
                               3988                 : 
                               3989                 :     /*
                               3990                 :      * Now assign remaining column aliases for each RTE.  We do this in a
                               3991                 :      * linear scan of the rtable, so as to process RTEs whether or not they
                               3992                 :      * are in the jointree (we mustn't miss NEW.*, INSERT target relations,
                               3993                 :      * etc).  JOIN RTEs must be processed after their children, but this is
                               3994                 :      * okay because they appear later in the rtable list than their children
                               3995                 :      * (cf Asserts in identify_join_columns()).
                               3996                 :      */
 3751                          3997            6395 :     forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
                               3998                 :     {
 3751 tgl                      3999 GIC        4031 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
                               4000            4031 :         deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
                               4001                 : 
                               4002            4031 :         if (rte->rtekind == RTE_JOIN)
 3751 tgl                      4003 CBC         500 :             set_join_column_names(dpns, rte, colinfo);
 3751 tgl                      4004 ECB             :         else
 3751 tgl                      4005 CBC        3531 :             set_relation_column_names(dpns, rte, colinfo);
                               4006                 :     }
 3751 tgl                      4007 GIC        2364 : }
                               4008                 : 
 3751 tgl                      4009 ECB             : /*
                               4010                 :  * set_simple_column_names: fill in column aliases for non-query situations
                               4011                 :  *
                               4012                 :  * This handles EXPLAIN and cases where we only have relation RTEs.  Without
                               4013                 :  * a join tree, we can't do anything smart about join RTEs, but we don't
                               4014                 :  * need to (note that EXPLAIN should never see join alias Vars anyway).
                               4015                 :  * If we do hit a join RTE we'll just process it like a non-table base RTE.
                               4016                 :  */
                               4017                 : static void
 3751 tgl                      4018 GIC       19575 : set_simple_column_names(deparse_namespace *dpns)
                               4019                 : {
                               4020                 :     ListCell   *lc;
                               4021                 :     ListCell   *lc2;
                               4022                 : 
                               4023                 :     /* Initialize dpns->rtable_columns to contain zeroed structs */
                               4024           19575 :     dpns->rtable_columns = NIL;
                               4025           54489 :     while (list_length(dpns->rtable_columns) < list_length(dpns->rtable))
                               4026           34914 :         dpns->rtable_columns = lappend(dpns->rtable_columns,
                               4027                 :                                        palloc0(sizeof(deparse_columns)));
                               4028                 : 
                               4029                 :     /* Assign unique column aliases within each RTE */
                               4030           54489 :     forboth(lc, dpns->rtable, lc2, dpns->rtable_columns)
                               4031                 :     {
                               4032           34914 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
                               4033           34914 :         deparse_columns *colinfo = (deparse_columns *) lfirst(lc2);
                               4034                 : 
                               4035           34914 :         set_relation_column_names(dpns, rte, colinfo);
                               4036                 :     }
                               4037           19575 : }
 3751 tgl                      4038 ECB             : 
                               4039                 : /*
 3547                          4040                 :  * has_dangerous_join_using: search jointree for unnamed JOIN USING
                               4041                 :  *
                               4042                 :  * Merged columns of a JOIN USING may act differently from either of the input
                               4043                 :  * columns, either because they are merged with COALESCE (in a FULL JOIN) or
                               4044                 :  * because an implicit coercion of the underlying input column is required.
                               4045                 :  * In such a case the column must be referenced as a column of the JOIN not as
                               4046                 :  * a column of either input.  And this is problematic if the join is unnamed
                               4047                 :  * (alias-less): we cannot qualify the column's name with an RTE name, since
                               4048                 :  * there is none.  (Forcibly assigning an alias to the join is not a solution,
                               4049                 :  * since that will prevent legal references to tables below the join.)
                               4050                 :  * To ensure that every column in the query is unambiguously referenceable,
                               4051                 :  * we must assign such merged columns names that are globally unique across
                               4052                 :  * the whole query, aliasing other columns out of the way as necessary.
                               4053                 :  *
                               4054                 :  * Because the ensuing re-aliasing is fairly damaging to the readability of
 3751                          4055                 :  * the query, we don't do this unless we have to.  So, we must pre-scan
                               4056                 :  * the join tree to see if we have to, before starting set_using_names().
                               4057                 :  */
                               4058                 : static bool
 3547 tgl                      4059 GIC        5335 : has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode)
 3751 tgl                      4060 ECB             : {
 3751 tgl                      4061 GIC        5335 :     if (IsA(jtnode, RangeTblRef))
                               4062                 :     {
                               4063                 :         /* nothing to do here */
                               4064                 :     }
                               4065            2823 :     else if (IsA(jtnode, FromExpr))
                               4066                 :     {
 3751 tgl                      4067 CBC        2356 :         FromExpr   *f = (FromExpr *) jtnode;
                               4068                 :         ListCell   *lc;
                               4069                 : 
                               4070            4437 :         foreach(lc, f->fromlist)
                               4071                 :         {
 3547                          4072            2117 :             if (has_dangerous_join_using(dpns, (Node *) lfirst(lc)))
 3751 tgl                      4073 GIC          36 :                 return true;
 3751 tgl                      4074 ECB             :         }
                               4075                 :     }
 3751 tgl                      4076 GIC         467 :     else if (IsA(jtnode, JoinExpr))
                               4077                 :     {
                               4078             467 :         JoinExpr   *j = (JoinExpr *) jtnode;
                               4079                 : 
 3547 tgl                      4080 ECB             :         /* Is it an unnamed JOIN with USING? */
 3547 tgl                      4081 GBC         467 :         if (j->alias == NULL && j->usingClause)
 3547 tgl                      4082 ECB             :         {
 3547 tgl                      4083 EUB             :             /*
                               4084                 :              * Yes, so check each join alias var to see if any of them are not
                               4085                 :              * simple references to underlying columns.  If so, we have a
                               4086                 :              * dangerous situation and must pick unique aliases.
                               4087                 :              */
 3547 tgl                      4088 CBC         143 :             RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable);
                               4089                 : 
                               4090                 :             /* We need only examine the merged columns */
 1186 tgl                      4091 GIC         298 :             for (int i = 0; i < jrte->joinmergedcols; i++)
                               4092                 :             {
                               4093             191 :                 Node       *aliasvar = list_nth(jrte->joinaliasvars, i);
                               4094                 : 
                               4095             191 :                 if (!IsA(aliasvar, Var))
 3547                          4096              36 :                     return true;
                               4097                 :             }
                               4098                 :         }
                               4099                 : 
                               4100                 :         /* Nope, but inspect children */
                               4101             431 :         if (has_dangerous_join_using(dpns, j->larg))
 3751 tgl                      4102 UIC           0 :             return true;
 3547 tgl                      4103 GIC         431 :         if (has_dangerous_join_using(dpns, j->rarg))
 3751 tgl                      4104 LBC           0 :             return true;
                               4105                 :     }
 3751 tgl                      4106 ECB             :     else
 3751 tgl                      4107 UIC           0 :         elog(ERROR, "unrecognized node type: %d",
                               4108                 :              (int) nodeTag(jtnode));
 3751 tgl                      4109 GIC        5263 :     return false;
 3751 tgl                      4110 ECB             : }
                               4111                 : 
                               4112                 : /*
                               4113                 :  * set_using_names: select column aliases to be used for merged USING columns
                               4114                 :  *
                               4115                 :  * We do this during a recursive descent of the query jointree.
                               4116                 :  * dpns->unique_using must already be set to determine the global strategy.
                               4117                 :  *
                               4118                 :  * Column alias info is saved in the dpns->rtable_columns list, which is
                               4119                 :  * assumed to be filled with pre-zeroed deparse_columns structs.
 3265                          4120                 :  *
                               4121                 :  * parentUsing is a list of all USING aliases assigned in parent joins of
                               4122                 :  * the current jointree node.  (The passed-in list must not be modified.)
                               4123                 :  */
                               4124                 : static void
 3265 tgl                      4125 GIC        5494 : set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing)
                               4126                 : {
 3751                          4127            5494 :     if (IsA(jtnode, RangeTblRef))
                               4128                 :     {
                               4129                 :         /* nothing to do now */
                               4130                 :     }
 3751 tgl                      4131 CBC        2856 :     else if (IsA(jtnode, FromExpr))
 3751 tgl                      4132 ECB             :     {
 3751 tgl                      4133 CBC        2356 :         FromExpr   *f = (FromExpr *) jtnode;
                               4134                 :         ListCell   *lc;
                               4135                 : 
                               4136            4494 :         foreach(lc, f->fromlist)
 3265                          4137            2138 :             set_using_names(dpns, (Node *) lfirst(lc), parentUsing);
                               4138                 :     }
 3751 tgl                      4139 GIC         500 :     else if (IsA(jtnode, JoinExpr))
                               4140                 :     {
                               4141             500 :         JoinExpr   *j = (JoinExpr *) jtnode;
                               4142             500 :         RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable);
                               4143             500 :         deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
 3751 tgl                      4144 ECB             :         int        *leftattnos;
                               4145                 :         int        *rightattnos;
                               4146                 :         deparse_columns *leftcolinfo;
                               4147                 :         deparse_columns *rightcolinfo;
                               4148                 :         int         i;
                               4149                 :         ListCell   *lc;
                               4150                 : 
                               4151                 :         /* Get info about the shape of the join */
 3751 tgl                      4152 GIC         500 :         identify_join_columns(j, rte, colinfo);
                               4153             500 :         leftattnos = colinfo->leftattnos;
 3751 tgl                      4154 CBC         500 :         rightattnos = colinfo->rightattnos;
                               4155                 : 
 3751 tgl                      4156 ECB             :         /* Look up the not-yet-filled-in child deparse_columns structs */
 3751 tgl                      4157 CBC         500 :         leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
 3751 tgl                      4158 GIC         500 :         rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
                               4159                 : 
                               4160                 :         /*
 3751 tgl                      4161 ECB             :          * If this join is unnamed, then we cannot substitute new aliases at
                               4162                 :          * this level, so any name requirements pushed down to here must be
                               4163                 :          * pushed down again to the children.
                               4164                 :          */
 3751 tgl                      4165 GIC         500 :         if (rte->alias == NULL)
                               4166                 :         {
                               4167             515 :             for (i = 0; i < colinfo->num_cols; i++)
                               4168                 :             {
                               4169              69 :                 char       *colname = colinfo->colnames[i];
                               4170                 : 
                               4171              69 :                 if (colname == NULL)
                               4172              12 :                     continue;
                               4173                 : 
                               4174                 :                 /* Push down to left column, unless it's a system column */
                               4175              57 :                 if (leftattnos[i] > 0)
                               4176                 :                 {
                               4177              51 :                     expand_colnames_array_to(leftcolinfo, leftattnos[i]);
                               4178              51 :                     leftcolinfo->colnames[leftattnos[i] - 1] = colname;
                               4179                 :                 }
                               4180                 : 
                               4181                 :                 /* Same on the righthand side */
                               4182              57 :                 if (rightattnos[i] > 0)
                               4183                 :                 {
                               4184              57 :                     expand_colnames_array_to(rightcolinfo, rightattnos[i]);
                               4185              57 :                     rightcolinfo->colnames[rightattnos[i] - 1] = colname;
                               4186                 :                 }
                               4187                 :             }
                               4188                 :         }
                               4189                 : 
                               4190                 :         /*
                               4191                 :          * If there's a USING clause, select the USING column names and push
                               4192                 :          * those names down to the children.  We have two strategies:
                               4193                 :          *
 2062 peter_e                  4194 ECB             :          * If dpns->unique_using is true, we force all USING names to be
                               4195                 :          * unique across the whole query level.  In principle we'd only need
                               4196                 :          * the names of dangerous USING columns to be globally unique, but to
 3547 tgl                      4197                 :          * safely assign all USING names in a single pass, we have to enforce
                               4198                 :          * the same uniqueness rule for all of them.  However, if a USING
                               4199                 :          * column's name has been pushed down from the parent, we should use
                               4200                 :          * it as-is rather than making a uniqueness adjustment.  This is
                               4201                 :          * necessary when we're at an unnamed join, and it creates no risk of
                               4202                 :          * ambiguity.  Also, if there's a user-written output alias for a
                               4203                 :          * merged column, we prefer to use that rather than the input name;
                               4204                 :          * this simplifies the logic and seems likely to lead to less aliasing
                               4205                 :          * overall.
                               4206                 :          *
 2062 peter_e                  4207                 :          * If dpns->unique_using is false, we only need USING names to be
                               4208                 :          * unique within their own join RTE.  We still need to honor
                               4209                 :          * pushed-down names, though.
 3751 tgl                      4210                 :          *
                               4211                 :          * Though significantly different in results, these two strategies are
                               4212                 :          * implemented by the same code, with only the difference of whether
                               4213                 :          * to put assigned names into dpns->using_names.
                               4214                 :          */
 3751 tgl                      4215 CBC         500 :         if (j->usingClause)
 3751 tgl                      4216 EUB             :         {
                               4217                 :             /* Copy the input parentUsing list so we don't modify it */
 3265 tgl                      4218 CBC         212 :             parentUsing = list_copy(parentUsing);
 3265 tgl                      4219 ECB             : 
 3751                          4220                 :             /* USING names must correspond to the first join output columns */
 3751 tgl                      4221 GIC         212 :             expand_colnames_array_to(colinfo, list_length(j->usingClause));
                               4222             212 :             i = 0;
 3751 tgl                      4223 CBC         502 :             foreach(lc, j->usingClause)
                               4224                 :             {
 3751 tgl                      4225 GIC         290 :                 char       *colname = strVal(lfirst(lc));
                               4226                 : 
 3751 tgl                      4227 ECB             :                 /* Assert it's a merged column */
 3751 tgl                      4228 CBC         290 :                 Assert(leftattnos[i] != 0 && rightattnos[i] != 0);
                               4229                 : 
                               4230                 :                 /* Adopt passed-down name if any, else select unique name */
                               4231             290 :                 if (colinfo->colnames[i] != NULL)
 3751 tgl                      4232 GIC          51 :                     colname = colinfo->colnames[i];
 3751 tgl                      4233 ECB             :                 else
                               4234                 :                 {
                               4235                 :                     /* Prefer user-written output alias if any */
 3751 tgl                      4236 GIC         239 :                     if (rte->alias && i < list_length(rte->alias->colnames))
 3751 tgl                      4237 UIC           0 :                         colname = strVal(list_nth(rte->alias->colnames, i));
 3751 tgl                      4238 ECB             :                     /* Make it appropriately unique */
 3751 tgl                      4239 GIC         239 :                     colname = make_colname_unique(colname, dpns, colinfo);
 3751 tgl                      4240 CBC         239 :                     if (dpns->unique_using)
                               4241              63 :                         dpns->using_names = lappend(dpns->using_names,
                               4242                 :                                                     colname);
                               4243                 :                     /* Save it as output column name, too */
                               4244             239 :                     colinfo->colnames[i] = colname;
                               4245                 :                 }
                               4246                 : 
                               4247                 :                 /* Remember selected names for use later */
 3751 tgl                      4248 GIC         290 :                 colinfo->usingNames = lappend(colinfo->usingNames, colname);
 3265 tgl                      4249 CBC         290 :                 parentUsing = lappend(parentUsing, colname);
 3751 tgl                      4250 ECB             : 
                               4251                 :                 /* Push down to left column, unless it's a system column */
 3751 tgl                      4252 GIC         290 :                 if (leftattnos[i] > 0)
 3751 tgl                      4253 ECB             :                 {
 3751 tgl                      4254 CBC         290 :                     expand_colnames_array_to(leftcolinfo, leftattnos[i]);
 3751 tgl                      4255 GIC         290 :                     leftcolinfo->colnames[leftattnos[i] - 1] = colname;
                               4256                 :                 }
 3751 tgl                      4257 EUB             : 
                               4258                 :                 /* Same on the righthand side */
 3751 tgl                      4259 CBC         290 :                 if (rightattnos[i] > 0)
                               4260                 :                 {
 3751 tgl                      4261 GIC         290 :                     expand_colnames_array_to(rightcolinfo, rightattnos[i]);
                               4262             290 :                     rightcolinfo->colnames[rightattnos[i] - 1] = colname;
                               4263                 :                 }
                               4264                 : 
                               4265             290 :                 i++;
                               4266                 :             }
                               4267                 :         }
                               4268                 : 
 3265 tgl                      4269 ECB             :         /* Mark child deparse_columns structs with correct parentUsing info */
 3265 tgl                      4270 GIC         500 :         leftcolinfo->parentUsing = parentUsing;
                               4271             500 :         rightcolinfo->parentUsing = parentUsing;
                               4272                 : 
                               4273                 :         /* Now recursively assign USING column names in children */
                               4274             500 :         set_using_names(dpns, j->larg, parentUsing);
                               4275             500 :         set_using_names(dpns, j->rarg, parentUsing);
                               4276                 :     }
                               4277                 :     else
 3751 tgl                      4278 UIC           0 :         elog(ERROR, "unrecognized node type: %d",
                               4279                 :              (int) nodeTag(jtnode));
 3751 tgl                      4280 GIC        5494 : }
                               4281                 : 
                               4282                 : /*
                               4283                 :  * set_relation_column_names: select column aliases for a non-join RTE
 3751 tgl                      4284 ECB             :  *
                               4285                 :  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
                               4286                 :  * If any colnames entries are already filled in, those override local
                               4287                 :  * choices.
                               4288                 :  */
                               4289                 : static void
 3751 tgl                      4290 CBC       38445 : set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
 3751 tgl                      4291 ECB             :                           deparse_columns *colinfo)
                               4292                 : {
                               4293                 :     int         ncolumns;
                               4294                 :     char      **real_colnames;
                               4295                 :     bool        changed_any;
                               4296                 :     int         noldcolumns;
                               4297                 :     int         i;
                               4298                 :     int         j;
                               4299                 : 
                               4300                 :     /*
  262                          4301                 :      * Construct an array of the current "real" column names of the RTE.
                               4302                 :      * real_colnames[] will be indexed by physical column number, with NULL
                               4303                 :      * entries for dropped columns.
                               4304                 :      */
 3751 tgl                      4305 CBC       38445 :     if (rte->rtekind == RTE_RELATION)
                               4306                 :     {
                               4307                 :         /* Relation --- look to the system catalogs for up-to-date info */
                               4308                 :         Relation    rel;
                               4309                 :         TupleDesc   tupdesc;
                               4310                 : 
 3751 tgl                      4311 GIC       32179 :         rel = relation_open(rte->relid, AccessShareLock);
                               4312           32179 :         tupdesc = RelationGetDescr(rel);
                               4313                 : 
                               4314           32179 :         ncolumns = tupdesc->natts;
                               4315           32179 :         real_colnames = (char **) palloc(ncolumns * sizeof(char *));
                               4316                 : 
                               4317          207091 :         for (i = 0; i < ncolumns; i++)
                               4318                 :         {
 2058 andres                   4319          174912 :             Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
                               4320                 : 
                               4321          174912 :             if (attr->attisdropped)
 3751 tgl                      4322            1498 :                 real_colnames[i] = NULL;
                               4323                 :             else
 2058 andres                   4324          173414 :                 real_colnames[i] = pstrdup(NameStr(attr->attname));
                               4325                 :         }
 3751 tgl                      4326           32179 :         relation_close(rel, AccessShareLock);
                               4327                 :     }
 3751 tgl                      4328 ECB             :     else
                               4329                 :     {
                               4330                 :         /* Otherwise get the column names from eref or expandRTE() */
  262                          4331                 :         List       *colnames;
                               4332                 :         ListCell   *lc;
                               4333                 : 
                               4334                 :         /*
                               4335                 :          * Functions returning composites have the annoying property that some
                               4336                 :          * of the composite type's columns might have been dropped since the
                               4337                 :          * query was parsed.  If possible, use expandRTE() to handle that
                               4338                 :          * case, since it has the tedious logic needed to find out about
                               4339                 :          * dropped columns.  However, if we're explaining a plan, then we
                               4340                 :          * don't have rte->functions because the planner thinks that won't be
                               4341                 :          * needed later, and that breaks expandRTE().  So in that case we have
                               4342                 :          * to rely on rte->eref, which may lead us to report a dropped
                               4343                 :          * column's old name; that seems close enough for EXPLAIN's purposes.
                               4344                 :          *
                               4345                 :          * For non-RELATION, non-FUNCTION RTEs, we can just look at rte->eref,
                               4346                 :          * which should be sufficiently up-to-date: no other RTE types can
                               4347                 :          * have columns get dropped from under them after parsing.
                               4348                 :          */
  262 tgl                      4349 CBC        6266 :         if (rte->rtekind == RTE_FUNCTION && rte->functions != NIL)
  262 tgl                      4350 ECB             :         {
                               4351                 :             /* Since we're not creating Vars, rtindex etc. don't matter */
  262 tgl                      4352 CBC         267 :             expandRTE(rte, 1, 0, -1, true /* include dropped */ ,
                               4353                 :                       &colnames, NULL);
                               4354                 :         }
                               4355                 :         else
  262 tgl                      4356 GIC        5999 :             colnames = rte->eref->colnames;
                               4357                 : 
                               4358            6266 :         ncolumns = list_length(colnames);
 3751                          4359            6266 :         real_colnames = (char **) palloc(ncolumns * sizeof(char *));
                               4360                 : 
                               4361            6266 :         i = 0;
  262                          4362           33471 :         foreach(lc, colnames)
                               4363                 :         {
 3186 tgl                      4364 ECB             :             /*
  262                          4365                 :              * If the column name we find here is an empty string, then it's a
                               4366                 :              * dropped column, so change to NULL.
                               4367                 :              */
 3186 tgl                      4368 GIC       27205 :             char       *cname = strVal(lfirst(lc));
                               4369                 : 
                               4370           27205 :             if (cname[0] == '\0')
                               4371              27 :                 cname = NULL;
                               4372           27205 :             real_colnames[i] = cname;
 3751                          4373           27205 :             i++;
 3751 tgl                      4374 ECB             :         }
                               4375                 :     }
                               4376                 : 
                               4377                 :     /*
                               4378                 :      * Ensure colinfo->colnames has a slot for each column.  (It could be long
                               4379                 :      * enough already, if we pushed down a name for the last column.)  Note:
                               4380                 :      * it's possible that there are now more columns than there were when the
                               4381                 :      * query was parsed, ie colnames could be longer than rte->eref->colnames.
                               4382                 :      * We must assign unique aliases to the new columns too, else there could
                               4383                 :      * be unresolved conflicts when the view/rule is reloaded.
                               4384                 :      */
 3751 tgl                      4385 CBC       38445 :     expand_colnames_array_to(colinfo, ncolumns);
                               4386           38445 :     Assert(colinfo->num_cols == ncolumns);
 3751 tgl                      4387 ECB             : 
                               4388                 :     /*
                               4389                 :      * Make sufficiently large new_colnames and is_new_col arrays, too.
                               4390                 :      *
                               4391                 :      * Note: because we leave colinfo->num_new_cols zero until after the loop,
                               4392                 :      * colname_is_unique will not consult that array, which is fine because it
                               4393                 :      * would only be duplicate effort.
                               4394                 :      */
 3751 tgl                      4395 CBC       38445 :     colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *));
                               4396           38445 :     colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool));
                               4397                 : 
                               4398                 :     /*
                               4399                 :      * Scan the columns, select a unique alias for each one, and store it in
 3751 tgl                      4400 ECB             :      * colinfo->colnames and colinfo->new_colnames.  The former array has NULL
                               4401                 :      * entries for dropped columns, the latter omits them.  Also mark
                               4402                 :      * new_colnames entries as to whether they are new since parse time; this
                               4403                 :      * is the case for entries beyond the length of rte->eref->colnames.
                               4404                 :      */
 3751 tgl                      4405 GIC       38445 :     noldcolumns = list_length(rte->eref->colnames);
 3751 tgl                      4406 CBC       38445 :     changed_any = false;
 3751 tgl                      4407 GIC       38445 :     j = 0;
                               4408          240562 :     for (i = 0; i < ncolumns; i++)
 3751 tgl                      4409 ECB             :     {
 3751 tgl                      4410 GIC      202117 :         char       *real_colname = real_colnames[i];
 3751 tgl                      4411 CBC      202117 :         char       *colname = colinfo->colnames[i];
                               4412                 : 
                               4413                 :         /* Skip dropped columns */
 3751 tgl                      4414 GIC      202117 :         if (real_colname == NULL)
 3751 tgl                      4415 ECB             :         {
 3751 tgl                      4416 GIC        1525 :             Assert(colname == NULL);    /* colnames[i] is already NULL */
 3751 tgl                      4417 CBC        1525 :             continue;
 3751 tgl                      4418 ECB             :         }
                               4419                 : 
                               4420                 :         /* If alias already assigned, that's what to use */
 3751 tgl                      4421 CBC      200592 :         if (colname == NULL)
 3751 tgl                      4422 ECB             :         {
                               4423                 :             /* If user wrote an alias, prefer that over real column name */
 3751 tgl                      4424 GIC      200063 :             if (rte->alias && i < list_length(rte->alias->colnames))
                               4425           19190 :                 colname = strVal(list_nth(rte->alias->colnames, i));
                               4426                 :             else
                               4427          180873 :                 colname = real_colname;
                               4428                 : 
                               4429                 :             /* Unique-ify and insert into colinfo */
                               4430          200063 :             colname = make_colname_unique(colname, dpns, colinfo);
 3751 tgl                      4431 ECB             : 
 3751 tgl                      4432 GIC      200063 :             colinfo->colnames[i] = colname;
                               4433                 :         }
                               4434                 : 
                               4435                 :         /* Put names of non-dropped columns in new_colnames[] too */
                               4436          200592 :         colinfo->new_colnames[j] = colname;
                               4437                 :         /* And mark them as new or not */
                               4438          200592 :         colinfo->is_new_col[j] = (i >= noldcolumns);
                               4439          200592 :         j++;
                               4440                 : 
                               4441                 :         /* Remember if any assigned aliases differ from "real" name */
                               4442          200592 :         if (!changed_any && strcmp(colname, real_colname) != 0)
 3751 tgl                      4443 CBC        1641 :             changed_any = true;
 3751 tgl                      4444 ECB             :     }
                               4445                 : 
                               4446                 :     /*
                               4447                 :      * Set correct length for new_colnames[] array.  (Note: if columns have
                               4448                 :      * been added, colinfo->num_cols includes them, which is not really quite
                               4449                 :      * right but is harmless, since any new columns must be at the end where
                               4450                 :      * they won't affect varattnos of pre-existing columns.)
                               4451                 :      */
 3751 tgl                      4452 CBC       38445 :     colinfo->num_new_cols = j;
 3751 tgl                      4453 ECB             : 
                               4454                 :     /*
                               4455                 :      * For a relation RTE, we need only print the alias column names if any
                               4456                 :      * are different from the underlying "real" names.  For a function RTE,
                               4457                 :      * always emit a complete column alias list; this is to protect against
                               4458                 :      * possible instability of the default column names (eg, from altering
                               4459                 :      * parameter names).  For tablefunc RTEs, we never print aliases, because
                               4460                 :      * the column names are part of the clause itself.  For other RTE types,
                               4461                 :      * print if we changed anything OR if there were user-written column
                               4462                 :      * aliases (since the latter would be part of the underlying "reality").
                               4463                 :      */
 3751 tgl                      4464 GIC       38445 :     if (rte->rtekind == RTE_RELATION)
 3751 tgl                      4465 CBC       32179 :         colinfo->printaliases = changed_any;
 3751 tgl                      4466 GIC        6266 :     else if (rte->rtekind == RTE_FUNCTION)
                               4467             453 :         colinfo->printaliases = true;
 2223 alvherre                 4468            5813 :     else if (rte->rtekind == RTE_TABLEFUNC)
                               4469              28 :         colinfo->printaliases = false;
 3751 tgl                      4470            5785 :     else if (rte->alias && rte->alias->colnames != NIL)
                               4471             336 :         colinfo->printaliases = true;
                               4472                 :     else
 3751 tgl                      4473 CBC        5449 :         colinfo->printaliases = changed_any;
                               4474           38445 : }
                               4475                 : 
                               4476                 : /*
                               4477                 :  * set_join_column_names: select column aliases for a join RTE
                               4478                 :  *
                               4479                 :  * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed.
                               4480                 :  * If any colnames entries are already filled in, those override local
 3751 tgl                      4481 ECB             :  * choices.  Also, names for USING columns were already chosen by
                               4482                 :  * set_using_names().  We further expect that column alias selection has been
                               4483                 :  * completed for both input RTEs.
                               4484                 :  */
                               4485                 : static void
 3751 tgl                      4486 GIC         500 : set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
                               4487                 :                       deparse_columns *colinfo)
                               4488                 : {
                               4489                 :     deparse_columns *leftcolinfo;
                               4490                 :     deparse_columns *rightcolinfo;
 3751 tgl                      4491 ECB             :     bool        changed_any;
                               4492                 :     int         noldcolumns;
                               4493                 :     int         nnewcolumns;
 3751 tgl                      4494 GIC         500 :     Bitmapset  *leftmerged = NULL;
                               4495             500 :     Bitmapset  *rightmerged = NULL;
                               4496                 :     int         i;
                               4497                 :     int         j;
                               4498                 :     int         ic;
                               4499                 :     int         jc;
                               4500                 : 
 3751 tgl                      4501 ECB             :     /* Look up the previously-filled-in child deparse_columns structs */
 3751 tgl                      4502 CBC         500 :     leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns);
 3751 tgl                      4503 GIC         500 :     rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns);
 3751 tgl                      4504 ECB             : 
                               4505                 :     /*
                               4506                 :      * Ensure colinfo->colnames has a slot for each column.  (It could be long
                               4507                 :      * enough already, if we pushed down a name for the last column.)  Note:
                               4508                 :      * it's possible that one or both inputs now have more columns than there
                               4509                 :      * were when the query was parsed, but we'll deal with that below.  We
                               4510                 :      * only need entries in colnames for pre-existing columns.
                               4511                 :      */
 3751 tgl                      4512 CBC         500 :     noldcolumns = list_length(rte->eref->colnames);
                               4513             500 :     expand_colnames_array_to(colinfo, noldcolumns);
                               4514             500 :     Assert(colinfo->num_cols == noldcolumns);
                               4515                 : 
                               4516                 :     /*
                               4517                 :      * Scan the join output columns, select an alias for each one, and store
 3751 tgl                      4518 EUB             :      * it in colinfo->colnames.  If there are USING columns, set_using_names()
                               4519                 :      * already selected their names, so we can start the loop at the first
                               4520                 :      * non-merged column.
                               4521                 :      */
 3751 tgl                      4522 CBC         500 :     changed_any = false;
 3751 tgl                      4523 GIC       12818 :     for (i = list_length(colinfo->usingNames); i < noldcolumns; i++)
 3751 tgl                      4524 ECB             :     {
 3751 tgl                      4525 CBC       12318 :         char       *colname = colinfo->colnames[i];
                               4526                 :         char       *real_colname;
                               4527                 : 
                               4528                 :         /* Join column must refer to at least one input column */
 1186                          4529           12318 :         Assert(colinfo->leftattnos[i] != 0 || colinfo->rightattnos[i] != 0);
                               4530                 : 
 3751 tgl                      4531 ECB             :         /* Get the child column name */
 3751 tgl                      4532 CBC       12318 :         if (colinfo->leftattnos[i] > 0)
 3751 tgl                      4533 GIC        8558 :             real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
                               4534            3760 :         else if (colinfo->rightattnos[i] > 0)
                               4535            3760 :             real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1];
 3751 tgl                      4536 ECB             :         else
                               4537                 :         {
                               4538                 :             /* We're joining system columns --- use eref name */
 3547 tgl                      4539 LBC           0 :             real_colname = strVal(list_nth(rte->eref->colnames, i));
 3751 tgl                      4540 ECB             :         }
                               4541                 : 
 1186                          4542                 :         /* If child col has been dropped, no need to assign a join colname */
 1186 tgl                      4543 GIC       12318 :         if (real_colname == NULL)
                               4544                 :         {
 1186 tgl                      4545 CBC           3 :             colinfo->colnames[i] = NULL;
 1186 tgl                      4546 GIC           3 :             continue;
 1186 tgl                      4547 ECB             :         }
                               4548                 : 
                               4549                 :         /* In an unnamed join, just report child column names as-is */
 3751 tgl                      4550 GIC       12315 :         if (rte->alias == NULL)
 3751 tgl                      4551 ECB             :         {
 3751 tgl                      4552 CBC       12126 :             colinfo->colnames[i] = real_colname;
 3751 tgl                      4553 GIC       12126 :             continue;
                               4554                 :         }
                               4555                 : 
                               4556                 :         /* If alias already assigned, that's what to use */
                               4557             189 :         if (colname == NULL)
                               4558                 :         {
                               4559                 :             /* If user wrote an alias, prefer that over real column name */
                               4560             189 :             if (rte->alias && i < list_length(rte->alias->colnames))
                               4561              48 :                 colname = strVal(list_nth(rte->alias->colnames, i));
 3751 tgl                      4562 ECB             :             else
 3751 tgl                      4563 CBC         141 :                 colname = real_colname;
 3751 tgl                      4564 ECB             : 
                               4565                 :             /* Unique-ify and insert into colinfo */
 3751 tgl                      4566 CBC         189 :             colname = make_colname_unique(colname, dpns, colinfo);
                               4567                 : 
 3751 tgl                      4568 GIC         189 :             colinfo->colnames[i] = colname;
                               4569                 :         }
                               4570                 : 
                               4571                 :         /* Remember if any assigned aliases differ from "real" name */
                               4572             189 :         if (!changed_any && strcmp(colname, real_colname) != 0)
                               4573              12 :             changed_any = true;
                               4574                 :     }
                               4575                 : 
                               4576                 :     /*
                               4577                 :      * Calculate number of columns the join would have if it were re-parsed
                               4578                 :      * now, and create storage for the new_colnames and is_new_col arrays.
                               4579                 :      *
                               4580                 :      * Note: colname_is_unique will be consulting new_colnames[] during the
                               4581                 :      * loops below, so its not-yet-filled entries must be zeroes.
                               4582                 :      */
                               4583            1000 :     nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols -
                               4584             500 :         list_length(colinfo->usingNames);
 3751 tgl                      4585 CBC         500 :     colinfo->num_new_cols = nnewcolumns;
                               4586             500 :     colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *));
                               4587             500 :     colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool));
 3751 tgl                      4588 ECB             : 
                               4589                 :     /*
                               4590                 :      * Generating the new_colnames array is a bit tricky since any new columns
                               4591                 :      * added since parse time must be inserted in the right places.  This code
                               4592                 :      * must match the parser, which will order a join's columns as merged
                               4593                 :      * columns first (in USING-clause order), then non-merged columns from the
                               4594                 :      * left input (in attnum order), then non-merged columns from the right
                               4595                 :      * input (ditto).  If one of the inputs is itself a join, its columns will
                               4596                 :      * be ordered according to the same rule, which means newly-added columns
                               4597                 :      * might not be at the end.  We can figure out what's what by consulting
                               4598                 :      * the leftattnos and rightattnos arrays plus the input is_new_col arrays.
                               4599                 :      *
                               4600                 :      * In these loops, i indexes leftattnos/rightattnos (so it's join varattno
                               4601                 :      * less one), j indexes new_colnames/is_new_col, and ic/jc have similar
                               4602                 :      * meanings for the current child RTE.
                               4603                 :      */
                               4604                 : 
                               4605                 :     /* Handle merged columns; they are first and can't be new */
 3751 tgl                      4606 GIC         500 :     i = j = 0;
 3751 tgl                      4607 CBC         500 :     while (i < noldcolumns &&
 3751 tgl                      4608 GIC         790 :            colinfo->leftattnos[i] != 0 &&
 3751 tgl                      4609 CBC         790 :            colinfo->rightattnos[i] != 0)
                               4610                 :     {
                               4611                 :         /* column name is already determined and known unique */
                               4612             290 :         colinfo->new_colnames[j] = colinfo->colnames[i];
                               4613             290 :         colinfo->is_new_col[j] = false;
 3751 tgl                      4614 ECB             : 
                               4615                 :         /* build bitmapsets of child attnums of merged columns */
 3751 tgl                      4616 CBC         290 :         if (colinfo->leftattnos[i] > 0)
 3751 tgl                      4617 GIC         290 :             leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]);
 3751 tgl                      4618 CBC         290 :         if (colinfo->rightattnos[i] > 0)
                               4619             290 :             rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]);
                               4620                 : 
                               4621             290 :         i++, j++;
 3751 tgl                      4622 ECB             :     }
                               4623                 : 
                               4624                 :     /* Handle non-merged left-child columns */
 3751 tgl                      4625 CBC         500 :     ic = 0;
 3751 tgl                      4626 GIC        9591 :     for (jc = 0; jc < leftcolinfo->num_new_cols; jc++)
 3751 tgl                      4627 ECB             :     {
 3751 tgl                      4628 CBC        9091 :         char       *child_colname = leftcolinfo->new_colnames[jc];
                               4629                 : 
 3751 tgl                      4630 GIC        9091 :         if (!leftcolinfo->is_new_col[jc])
                               4631                 :         {
                               4632                 :             /* Advance ic to next non-dropped old column of left child */
                               4633            8887 :             while (ic < leftcolinfo->num_cols &&
                               4634            8887 :                    leftcolinfo->colnames[ic] == NULL)
                               4635              42 :                 ic++;
 3751 tgl                      4636 CBC        8845 :             Assert(ic < leftcolinfo->num_cols);
 3751 tgl                      4637 GIC        8845 :             ic++;
 3751 tgl                      4638 ECB             :             /* If it is a merged column, we already processed it */
 3751 tgl                      4639 CBC        8845 :             if (bms_is_member(ic, leftmerged))
                               4640             290 :                 continue;
 3751 tgl                      4641 ECB             :             /* Else, advance i to the corresponding existing join column */
 3751 tgl                      4642 CBC        8558 :             while (i < colinfo->num_cols &&
 3751 tgl                      4643 GIC        8558 :                    colinfo->colnames[i] == NULL)
                               4644               3 :                 i++;
 3751 tgl                      4645 CBC        8555 :             Assert(i < colinfo->num_cols);
 3751 tgl                      4646 GIC        8555 :             Assert(ic == colinfo->leftattnos[i]);
                               4647                 :             /* Use the already-assigned name of this column */
 3751 tgl                      4648 CBC        8555 :             colinfo->new_colnames[j] = colinfo->colnames[i];
                               4649            8555 :             i++;
                               4650                 :         }
                               4651                 :         else
                               4652                 :         {
 3751 tgl                      4653 ECB             :             /*
                               4654                 :              * Unique-ify the new child column name and assign, unless we're
                               4655                 :              * in an unnamed join, in which case just copy
                               4656                 :              */
 3751 tgl                      4657 GIC         246 :             if (rte->alias != NULL)
 3751 tgl                      4658 ECB             :             {
 3751 tgl                      4659 GIC         132 :                 colinfo->new_colnames[j] =
                               4660              66 :                     make_colname_unique(child_colname, dpns, colinfo);
 3751 tgl                      4661 CBC          66 :                 if (!changed_any &&
                               4662              54 :                     strcmp(colinfo->new_colnames[j], child_colname) != 0)
 3751 tgl                      4663 GBC           6 :                     changed_any = true;
 3751 tgl                      4664 ECB             :             }
                               4665                 :             else
 3751 tgl                      4666 GIC         180 :                 colinfo->new_colnames[j] = child_colname;
 3751 tgl                      4667 ECB             :         }
                               4668                 : 
 3751 tgl                      4669 GIC        8801 :         colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
 3751 tgl                      4670 CBC        8801 :         j++;
 3751 tgl                      4671 ECB             :     }
 3751 tgl                      4672 EUB             : 
 3751 tgl                      4673 ECB             :     /* Handle non-merged right-child columns in exactly the same way */
 3751 tgl                      4674 CBC         500 :     ic = 0;
 3751 tgl                      4675 GIC        4634 :     for (jc = 0; jc < rightcolinfo->num_new_cols; jc++)
 3751 tgl                      4676 ECB             :     {
 3751 tgl                      4677 CBC        4134 :         char       *child_colname = rightcolinfo->new_colnames[jc];
                               4678                 : 
 3751 tgl                      4679 GIC        4134 :         if (!rightcolinfo->is_new_col[jc])
                               4680                 :         {
                               4681                 :             /* Advance ic to next non-dropped old column of right child */
                               4682            4050 :             while (ic < rightcolinfo->num_cols &&
                               4683            4050 :                    rightcolinfo->colnames[ic] == NULL)
 3751 tgl                      4684 UIC           0 :                 ic++;
 3751 tgl                      4685 CBC        4050 :             Assert(ic < rightcolinfo->num_cols);
 3751 tgl                      4686 GIC        4050 :             ic++;
 3751 tgl                      4687 ECB             :             /* If it is a merged column, we already processed it */
 3751 tgl                      4688 CBC        4050 :             if (bms_is_member(ic, rightmerged))
                               4689             290 :                 continue;
 3751 tgl                      4690 ECB             :             /* Else, advance i to the corresponding existing join column */
 3751 tgl                      4691 CBC        3760 :             while (i < colinfo->num_cols &&
 3751 tgl                      4692 GIC        3760 :                    colinfo->colnames[i] == NULL)
 3751 tgl                      4693 UIC           0 :                 i++;
 3751 tgl                      4694 CBC        3760 :             Assert(i < colinfo->num_cols);
 3751 tgl                      4695 GIC        3760 :             Assert(ic == colinfo->rightattnos[i]);
                               4696                 :             /* Use the already-assigned name of this column */
 3751 tgl                      4697 CBC        3760 :             colinfo->new_colnames[j] = colinfo->colnames[i];
                               4698            3760 :             i++;
                               4699                 :         }
                               4700                 :         else
                               4701                 :         {
                               4702                 :             /*
 3751 tgl                      4703 ECB             :              * Unique-ify the new child column name and assign, unless we're
 3751 tgl                      4704 EUB             :              * in an unnamed join, in which case just copy
 3751 tgl                      4705 ECB             :              */
 3751 tgl                      4706 CBC          84 :             if (rte->alias != NULL)
                               4707                 :             {
 3751 tgl                      4708 GIC          24 :                 colinfo->new_colnames[j] =
                               4709              12 :                     make_colname_unique(child_colname, dpns, colinfo);
                               4710              12 :                 if (!changed_any &&
                               4711              12 :                     strcmp(colinfo->new_colnames[j], child_colname) != 0)
                               4712               6 :                     changed_any = true;
 3751 tgl                      4713 ECB             :             }
                               4714                 :             else
 3751 tgl                      4715 GIC          72 :                 colinfo->new_colnames[j] = child_colname;
 3751 tgl                      4716 ECB             :         }
                               4717                 : 
 3751 tgl                      4718 GIC        3844 :         colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
                               4719            3844 :         j++;
                               4720                 :     }
                               4721                 : 
                               4722                 :     /* Assert we processed the right number of columns */
                               4723                 : #ifdef USE_ASSERT_CHECKING
                               4724             500 :     while (i < colinfo->num_cols && colinfo->colnames[i] == NULL)
 3751 tgl                      4725 LBC           0 :         i++;
 3751 tgl                      4726 GIC         500 :     Assert(i == colinfo->num_cols);
                               4727             500 :     Assert(j == nnewcolumns);
                               4728                 : #endif
                               4729                 : 
                               4730                 :     /*
                               4731                 :      * For a named join, print column aliases if we changed any from the child
 3751 tgl                      4732 ECB             :      * names.  Unnamed joins cannot print aliases.
                               4733                 :      */
 3751 tgl                      4734 CBC         500 :     if (rte->alias != NULL)
 3751 tgl                      4735 GIC          54 :         colinfo->printaliases = changed_any;
 3751 tgl                      4736 ECB             :     else
 3751 tgl                      4737 CBC         446 :         colinfo->printaliases = false;
 3751 tgl                      4738 GIC         500 : }
                               4739                 : 
                               4740                 : /*
                               4741                 :  * colname_is_unique: is colname distinct from already-chosen column names?
                               4742                 :  *
                               4743                 :  * dpns is query-wide info, colinfo is for the column's RTE
 3751 tgl                      4744 ECB             :  */
                               4745                 : static bool
 1986 peter_e                  4746 CBC      209077 : colname_is_unique(const char *colname, deparse_namespace *dpns,
                               4747                 :                   deparse_columns *colinfo)
 3751 tgl                      4748 ECB             : {
                               4749                 :     int         i;
                               4750                 :     ListCell   *lc;
                               4751                 : 
                               4752                 :     /* Check against already-assigned column aliases within RTE */
 3751 tgl                      4753 CBC     3170987 :     for (i = 0; i < colinfo->num_cols; i++)
                               4754                 :     {
                               4755         2970382 :         char       *oldname = colinfo->colnames[i];
                               4756                 : 
                               4757         2970382 :         if (oldname && strcmp(oldname, colname) == 0)
                               4758            8472 :             return false;
                               4759                 :     }
                               4760                 : 
                               4761                 :     /*
 3751 tgl                      4762 ECB             :      * If we're building a new_colnames array, check that too (this will be
                               4763                 :      * partially but not completely redundant with the previous checks)
                               4764                 :      */
 3751 tgl                      4765 GIC      201241 :     for (i = 0; i < colinfo->num_new_cols; i++)
 3751 tgl                      4766 ECB             :     {
 3751 tgl                      4767 CBC         648 :         char       *oldname = colinfo->new_colnames[i];
                               4768                 : 
 3751 tgl                      4769 GIC         648 :         if (oldname && strcmp(oldname, colname) == 0)
 3751 tgl                      4770 CBC          12 :             return false;
                               4771                 :     }
                               4772                 : 
                               4773                 :     /* Also check against USING-column names that must be globally unique */
 3751 tgl                      4774 GIC      201013 :     foreach(lc, dpns->using_names)
                               4775                 :     {
                               4776             441 :         char       *oldname = (char *) lfirst(lc);
                               4777                 : 
                               4778             441 :         if (strcmp(oldname, colname) == 0)
 3751 tgl                      4779 CBC          21 :             return false;
                               4780                 :     }
                               4781                 : 
                               4782                 :     /* Also check against names already assigned for parent-join USING cols */
 3265 tgl                      4783 GIC      201868 :     foreach(lc, colinfo->parentUsing)
                               4784                 :     {
                               4785            1299 :         char       *oldname = (char *) lfirst(lc);
                               4786                 : 
 3265 tgl                      4787 CBC        1299 :         if (strcmp(oldname, colname) == 0)
 3265 tgl                      4788 GIC           3 :             return false;
 3265 tgl                      4789 ECB             :     }
                               4790                 : 
 3751 tgl                      4791 CBC      200569 :     return true;
                               4792                 : }
                               4793                 : 
                               4794                 : /*
 3751 tgl                      4795 ECB             :  * make_colname_unique: modify colname if necessary to make it unique
                               4796                 :  *
                               4797                 :  * dpns is query-wide info, colinfo is for the column's RTE
                               4798                 :  */
                               4799                 : static char *
 3751 tgl                      4800 CBC      200569 : make_colname_unique(char *colname, deparse_namespace *dpns,
 3751 tgl                      4801 ECB             :                     deparse_columns *colinfo)
                               4802                 : {
 3751 tgl                      4803 EUB             :     /*
                               4804                 :      * If the selected name isn't unique, append digits to make it so.  For a
                               4805                 :      * very long input name, we might have to truncate to stay within
 2701 tgl                      4806 ECB             :      * NAMEDATALEN.
 3751                          4807                 :      */
 3751 tgl                      4808 GIC      200569 :     if (!colname_is_unique(colname, dpns, colinfo))
 3751 tgl                      4809 ECB             :     {
 2701 tgl                      4810 GIC        7412 :         int         colnamelen = strlen(colname);
                               4811            7412 :         char       *modname = (char *) palloc(colnamelen + 16);
 3751                          4812            7412 :         int         i = 0;
                               4813                 : 
                               4814                 :         do
                               4815                 :         {
 2701                          4816            8508 :             i++;
                               4817                 :             for (;;)
 2701 tgl                      4818 ECB             :             {
 2701 tgl                      4819 GIC        8508 :                 memcpy(modname, colname, colnamelen);
 2701 tgl                      4820 CBC        8508 :                 sprintf(modname + colnamelen, "_%d", i);
 2701 tgl                      4821 GIC        8508 :                 if (strlen(modname) < NAMEDATALEN)
 2701 tgl                      4822 CBC        8508 :                     break;
 2701 tgl                      4823 ECB             :                 /* drop chars from colname to keep all the digits */
 2701 tgl                      4824 UIC           0 :                 colnamelen = pg_mbcliplen(colname, colnamelen,
 2701 tgl                      4825 ECB             :                                           colnamelen - 1);
                               4826                 :             }
 3751 tgl                      4827 GIC        8508 :         } while (!colname_is_unique(modname, dpns, colinfo));
 3751 tgl                      4828 CBC        7412 :         colname = modname;
                               4829                 :     }
 3751 tgl                      4830 GIC      200569 :     return colname;
                               4831                 : }
                               4832                 : 
                               4833                 : /*
                               4834                 :  * expand_colnames_array_to: make colinfo->colnames at least n items long
                               4835                 :  *
                               4836                 :  * Any added array entries are initialized to zero.
 3751 tgl                      4837 ECB             :  */
                               4838                 : static void
 3751 tgl                      4839 GIC       39845 : expand_colnames_array_to(deparse_columns *colinfo, int n)
                               4840                 : {
                               4841           39845 :     if (n > colinfo->num_cols)
                               4842                 :     {
                               4843           38860 :         if (colinfo->colnames == NULL)
  148 peter                    4844 GNC       38152 :             colinfo->colnames = palloc0_array(char *, n);
                               4845                 :         else
                               4846             708 :             colinfo->colnames = repalloc0_array(colinfo->colnames, char *, colinfo->num_cols, n);
 3751 tgl                      4847 GIC       38860 :         colinfo->num_cols = n;
 3751 tgl                      4848 ECB             :     }
 3751 tgl                      4849 CBC       39845 : }
 3751 tgl                      4850 EUB             : 
                               4851                 : /*
                               4852                 :  * identify_join_columns: figure out where columns of a join come from
                               4853                 :  *
                               4854                 :  * Fills the join-specific fields of the colinfo struct, except for
                               4855                 :  * usingNames which is filled later.
                               4856                 :  */
 3751 tgl                      4857 ECB             : static void
 3751 tgl                      4858 CBC         500 : identify_join_columns(JoinExpr *j, RangeTblEntry *jrte,
                               4859                 :                       deparse_columns *colinfo)
                               4860                 : {
 3751 tgl                      4861 ECB             :     int         numjoincols;
 1186                          4862                 :     int         jcolno;
                               4863                 :     int         rcolno;
 3751                          4864                 :     ListCell   *lc;
                               4865                 : 
                               4866                 :     /* Extract left/right child RT indexes */
 3751 tgl                      4867 GIC         500 :     if (IsA(j->larg, RangeTblRef))
                               4868             335 :         colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex;
                               4869             165 :     else if (IsA(j->larg, JoinExpr))
                               4870             165 :         colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex;
                               4871                 :     else
 3751 tgl                      4872 UIC           0 :         elog(ERROR, "unrecognized node type in jointree: %d",
 3751 tgl                      4873 ECB             :              (int) nodeTag(j->larg));
 3751 tgl                      4874 CBC         500 :     if (IsA(j->rarg, RangeTblRef))
 3751 tgl                      4875 GIC         500 :         colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex;
 3751 tgl                      4876 LBC           0 :     else if (IsA(j->rarg, JoinExpr))
 3751 tgl                      4877 UIC           0 :         colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex;
 3751 tgl                      4878 ECB             :     else
 3751 tgl                      4879 UIC           0 :         elog(ERROR, "unrecognized node type in jointree: %d",
 3751 tgl                      4880 ECB             :              (int) nodeTag(j->rarg));
                               4881                 : 
                               4882                 :     /* Assert children will be processed earlier than join in second pass */
 3751 tgl                      4883 CBC         500 :     Assert(colinfo->leftrti < j->rtindex);
 3751 tgl                      4884 GIC         500 :     Assert(colinfo->rightrti < j->rtindex);
 3751 tgl                      4885 ECB             : 
                               4886                 :     /* Initialize result arrays with zeroes */
 3751 tgl                      4887 GIC         500 :     numjoincols = list_length(jrte->joinaliasvars);
 3751 tgl                      4888 CBC         500 :     Assert(numjoincols == list_length(jrte->eref->colnames));
                               4889             500 :     colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int));
 3751 tgl                      4890 GIC         500 :     colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int));
 3751 tgl                      4891 ECB             : 
                               4892                 :     /*
                               4893                 :      * Deconstruct RTE's joinleftcols/joinrightcols into desired format.
                               4894                 :      * Recall that the column(s) merged due to USING are the first column(s)
                               4895                 :      * of the join output.  We need not do anything special while scanning
                               4896                 :      * joinleftcols, but while scanning joinrightcols we must distinguish
                               4897                 :      * merged from unmerged columns.
                               4898                 :      */
 1186 tgl                      4899 GIC         500 :     jcolno = 0;
 1186 tgl                      4900 CBC        9348 :     foreach(lc, jrte->joinleftcols)
                               4901                 :     {
                               4902            8848 :         int         leftattno = lfirst_int(lc);
                               4903                 : 
                               4904            8848 :         colinfo->leftattnos[jcolno++] = leftattno;
 3751 tgl                      4905 ECB             :     }
 1186 tgl                      4906 GIC         500 :     rcolno = 0;
                               4907            4550 :     foreach(lc, jrte->joinrightcols)
                               4908                 :     {
                               4909            4050 :         int         rightattno = lfirst_int(lc);
                               4910                 : 
                               4911            4050 :         if (rcolno < jrte->joinmergedcols)    /* merged column? */
                               4912             290 :             colinfo->rightattnos[rcolno] = rightattno;
                               4913                 :         else
                               4914            3760 :             colinfo->rightattnos[jcolno++] = rightattno;
                               4915            4050 :         rcolno++;
                               4916                 :     }
                               4917             500 :     Assert(jcolno == numjoincols);
 3751                          4918             500 : }
 3751 tgl                      4919 ECB             : 
                               4920                 : /*
 3852                          4921                 :  * get_rtable_name: convenience function to get a previously assigned RTE alias
                               4922                 :  *
                               4923                 :  * The RTE must belong to the topmost namespace level in "context".
                               4924                 :  */
                               4925                 : static char *
 3852 tgl                      4926 GIC        2564 : get_rtable_name(int rtindex, deparse_context *context)
                               4927                 : {
                               4928            2564 :     deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
 3852 tgl                      4929 ECB             : 
 3852 tgl                      4930 CBC        2564 :     Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
                               4931            2564 :     return (char *) list_nth(dpns->rtable_names, rtindex - 1);
 3852 tgl                      4932 ECB             : }
                               4933                 : 
 4653                          4934                 : /*
                               4935                 :  * set_deparse_plan: set up deparse_namespace to parse subexpressions
 1215                          4936                 :  * of a given Plan node
 4653                          4937                 :  *
                               4938                 :  * This sets the plan, outer_plan, inner_plan, outer_tlist, inner_tlist,
  545                          4939                 :  * and index_tlist fields.  Caller must already have adjusted the ancestors
                               4940                 :  * list if necessary.  Note that the rtable, subplans, and ctes fields do
                               4941                 :  * not need to change when shifting attention to different plan nodes in a
                               4942                 :  * single plan tree.
                               4943                 :  */
                               4944                 : static void
 1215 tgl                      4945 GIC       49052 : set_deparse_plan(deparse_namespace *dpns, Plan *plan)
                               4946                 : {
                               4947           49052 :     dpns->plan = plan;
                               4948                 : 
                               4949                 :     /*
                               4950                 :      * We special-case Append and MergeAppend to pretend that the first child
                               4951                 :      * plan is the OUTER referent; we have to interpret OUTER Vars in their
                               4952                 :      * tlists according to one of the children, and the first one is the most
                               4953                 :      * natural choice.
                               4954                 :      */
 1215 tgl                      4955 CBC       49052 :     if (IsA(plan, Append))
                               4956            1924 :         dpns->outer_plan = linitial(((Append *) plan)->appendplans);
                               4957           47128 :     else if (IsA(plan, MergeAppend))
                               4958             213 :         dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
 4653 tgl                      4959 ECB             :     else
 1215 tgl                      4960 CBC       46915 :         dpns->outer_plan = outerPlan(plan);
 4653 tgl                      4961 ECB             : 
 1215 tgl                      4962 GIC       49052 :     if (dpns->outer_plan)
 1215 tgl                      4963 CBC       21939 :         dpns->outer_tlist = dpns->outer_plan->targetlist;
 4653 tgl                      4964 ECB             :     else
 4198 tgl                      4965 GIC       27113 :         dpns->outer_tlist = NIL;
 5298 tgl                      4966 ECB             : 
                               4967                 :     /*
 4653                          4968                 :      * For a SubqueryScan, pretend the subplan is INNER referent.  (We don't
                               4969                 :      * use OUTER because that could someday conflict with the normal meaning.)
                               4970                 :      * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
  570                          4971                 :      * For a WorkTableScan, locate the parent RecursiveUnion plan node and use
                               4972                 :      * that as INNER referent.
                               4973                 :      *
                               4974                 :      * For MERGE, make the inner tlist point to the merge source tlist, which
  377 alvherre                 4975                 :      * is same as the targetlist that the ModifyTable's source plan provides.
 2893 andres                   4976                 :      * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the
                               4977                 :      * excluded expression's tlist. (Similar to the SubqueryScan we don't want
                               4978                 :      * to reuse OUTER, it's used for RETURNING in some modify table cases,
                               4979                 :      * although not INSERT .. CONFLICT).
                               4980                 :      */
 1215 tgl                      4981 CBC       49052 :     if (IsA(plan, SubqueryScan))
                               4982             238 :         dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
                               4983           48814 :     else if (IsA(plan, CteScan))
                               4984             240 :         dpns->inner_plan = list_nth(dpns->subplans,
                               4985             240 :                                     ((CteScan *) plan)->ctePlanId - 1);
  570 tgl                      4986 GBC       48574 :     else if (IsA(plan, WorkTableScan))
  570 tgl                      4987 GIC          87 :         dpns->inner_plan = find_recursive_union(dpns,
  570 tgl                      4988 ECB             :                                                 (WorkTableScan *) plan);
 1215 tgl                      4989 CBC       48487 :     else if (IsA(plan, ModifyTable))
 1215 tgl                      4990 GIC         107 :         dpns->inner_plan = plan;
                               4991                 :     else
                               4992           48380 :         dpns->inner_plan = innerPlan(plan);
                               4993                 : 
                               4994           49052 :     if (IsA(plan, ModifyTable))
                               4995                 :     {
  377 alvherre                 4996             107 :         if (((ModifyTable *) plan)->operation == CMD_MERGE)
  354 alvherre                 4997 CBC           3 :             dpns->inner_tlist = dpns->outer_tlist;
                               4998                 :         else
  377 alvherre                 4999 GIC         104 :             dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
                               5000                 :     }
 1215 tgl                      5001 CBC       48945 :     else if (dpns->inner_plan)
 1215 tgl                      5002 GIC        7593 :         dpns->inner_tlist = dpns->inner_plan->targetlist;
 4653 tgl                      5003 ECB             :     else
 4198 tgl                      5004 GIC       41352 :         dpns->inner_tlist = NIL;
 4198 tgl                      5005 ECB             : 
 2891                          5006                 :     /* Set up referent for INDEX_VAR Vars, if needed */
 1215 tgl                      5007 CBC       49052 :     if (IsA(plan, IndexOnlyScan))
 1215 tgl                      5008 GIC        1229 :         dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
 1215 tgl                      5009 GBC       47823 :     else if (IsA(plan, ForeignScan))
 1215 tgl                      5010 GIC        1360 :         dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
                               5011           46463 :     else if (IsA(plan, CustomScan))
 1215 tgl                      5012 UIC           0 :         dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
                               5013                 :     else
 4198 tgl                      5014 GIC       46463 :         dpns->index_tlist = NIL;
 4653                          5015           49052 : }
                               5016                 : 
                               5017                 : /*
                               5018                 :  * Locate the ancestor plan node that is the RecursiveUnion generating
                               5019                 :  * the WorkTableScan's work table.  We can match on wtParam, since that
                               5020                 :  * should be unique within the plan tree.
                               5021                 :  */
                               5022                 : static Plan *
  570                          5023              87 : find_recursive_union(deparse_namespace *dpns, WorkTableScan *wtscan)
                               5024                 : {
                               5025                 :     ListCell   *lc;
                               5026                 : 
  570 tgl                      5027 CBC         219 :     foreach(lc, dpns->ancestors)
                               5028                 :     {
  570 tgl                      5029 GIC         219 :         Plan       *ancestor = (Plan *) lfirst(lc);
                               5030                 : 
  570 tgl                      5031 CBC         219 :         if (IsA(ancestor, RecursiveUnion) &&
  570 tgl                      5032 GIC          87 :             ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
                               5033              87 :             return ancestor;
  570 tgl                      5034 ECB             :     }
  570 tgl                      5035 UIC           0 :     elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
                               5036                 :          wtscan->wtParam);
  570 tgl                      5037 ECB             :     return NULL;
                               5038                 : }
                               5039                 : 
                               5040                 : /*
                               5041                 :  * push_child_plan: temporarily transfer deparsing attention to a child plan
                               5042                 :  *
                               5043                 :  * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the
 4198                          5044                 :  * deparse context in case the referenced expression itself uses
                               5045                 :  * OUTER_VAR/INNER_VAR.  We modify the top stack entry in-place to avoid
                               5046                 :  * affecting levelsup issues (although in a Plan tree there really shouldn't
                               5047                 :  * be any).
                               5048                 :  *
 4653                          5049                 :  * Caller must provide a local deparse_namespace variable to save the
                               5050                 :  * previous state for pop_child_plan.
                               5051                 :  */
                               5052                 : static void
 1215 tgl                      5053 GIC       26217 : push_child_plan(deparse_namespace *dpns, Plan *plan,
                               5054                 :                 deparse_namespace *save_dpns)
 4653 tgl                      5055 ECB             : {
                               5056                 :     /* Save state for restoration later */
 4653 tgl                      5057 GIC       26217 :     *save_dpns = *dpns;
                               5058                 : 
                               5059                 :     /* Link current plan node into ancestors list */
 1215                          5060           26217 :     dpns->ancestors = lcons(dpns->plan, dpns->ancestors);
                               5061                 : 
                               5062                 :     /* Set attention on selected child */
                               5063           26217 :     set_deparse_plan(dpns, plan);
 8089                          5064           26217 : }
                               5065                 : 
                               5066                 : /*
                               5067                 :  * pop_child_plan: undo the effects of push_child_plan
                               5068                 :  */
                               5069                 : static void
 4653                          5070           26217 : pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
                               5071                 : {
                               5072                 :     List       *ancestors;
                               5073                 : 
 3874 tgl                      5074 ECB             :     /* Get rid of ancestors list cell added by push_child_plan */
 3874 tgl                      5075 GIC       26217 :     ancestors = list_delete_first(dpns->ancestors);
                               5076                 : 
 4653 tgl                      5077 ECB             :     /* Restore fields changed by push_child_plan */
 4653 tgl                      5078 GIC       26217 :     *dpns = *save_dpns;
                               5079                 : 
 3874 tgl                      5080 ECB             :     /* Make sure dpns->ancestors is right (may be unnecessary) */
 3874 tgl                      5081 GIC       26217 :     dpns->ancestors = ancestors;
 4653                          5082           26217 : }
 4653 tgl                      5083 ECB             : 
                               5084                 : /*
                               5085                 :  * push_ancestor_plan: temporarily transfer deparsing attention to an
                               5086                 :  * ancestor plan
                               5087                 :  *
                               5088                 :  * When expanding a Param reference, we must adjust the deparse context
                               5089                 :  * to match the plan node that contains the expression being printed;
                               5090                 :  * otherwise we'd fail if that expression itself contains a Param or
                               5091                 :  * OUTER_VAR/INNER_VAR/INDEX_VAR variable.
                               5092                 :  *
                               5093                 :  * The target ancestor is conveniently identified by the ListCell holding it
                               5094                 :  * in dpns->ancestors.
                               5095                 :  *
                               5096                 :  * Caller must provide a local deparse_namespace variable to save the
                               5097                 :  * previous state for pop_ancestor_plan.
                               5098                 :  */
                               5099                 : static void
 4653 tgl                      5100 GIC        1396 : push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
 4653 tgl                      5101 ECB             :                    deparse_namespace *save_dpns)
                               5102                 : {
 1215 tgl                      5103 GIC        1396 :     Plan       *plan = (Plan *) lfirst(ancestor_cell);
                               5104                 : 
                               5105                 :     /* Save state for restoration later */
 4653                          5106            1396 :     *save_dpns = *dpns;
                               5107                 : 
                               5108                 :     /* Build a new ancestor list with just this node's ancestors */
 1364                          5109            1396 :     dpns->ancestors =
                               5110            1396 :         list_copy_tail(dpns->ancestors,
 1364 tgl                      5111 CBC        1396 :                        list_cell_number(dpns->ancestors, ancestor_cell) + 1);
                               5112                 : 
                               5113                 :     /* Set attention on selected ancestor */
 1215 tgl                      5114 GIC        1396 :     set_deparse_plan(dpns, plan);
 4653                          5115            1396 : }
                               5116                 : 
                               5117                 : /*
                               5118                 :  * pop_ancestor_plan: undo the effects of push_ancestor_plan
                               5119                 :  */
                               5120                 : static void
                               5121            1396 : pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
 4653 tgl                      5122 ECB             : {
                               5123                 :     /* Free the ancestor list made in push_ancestor_plan */
 4653 tgl                      5124 GIC        1396 :     list_free(dpns->ancestors);
                               5125                 : 
                               5126                 :     /* Restore fields changed by push_ancestor_plan */
                               5127            1396 :     *dpns = *save_dpns;
                               5128            1396 : }
                               5129                 : 
 4653 tgl                      5130 ECB             : 
 8994 bruce                    5131                 : /* ----------
                               5132                 :  * make_ruledef         - reconstruct the CREATE RULE command
                               5133                 :  *                for a given pg_rewrite tuple
                               5134                 :  * ----------
                               5135                 :  */
 8590 tgl                      5136                 : static void
 7193 tgl                      5137 CBC         264 : make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
 7193 tgl                      5138 ECB             :              int prettyFlags)
                               5139                 : {
 7661                          5140                 :     char       *rulename;
 8986 bruce                    5141                 :     char        ev_type;
                               5142                 :     Oid         ev_class;
                               5143                 :     bool        is_instead;
                               5144                 :     char       *ev_qual;
                               5145                 :     char       *ev_action;
  888 tgl                      5146                 :     List       *actions;
 2085                          5147                 :     Relation    ev_relation;
 2085 tgl                      5148 CBC         264 :     TupleDesc   viewResultDesc = NULL;
                               5149                 :     int         fno;
 7661 tgl                      5150 ECB             :     Datum       dat;
 8986 bruce                    5151                 :     bool        isnull;
                               5152                 : 
                               5153                 :     /*
                               5154                 :      * Get the attribute values from the rules tuple
                               5155                 :      */
 7661 tgl                      5156 CBC         264 :     fno = SPI_fnumber(rulettc, "rulename");
                               5157             264 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
                               5158             264 :     Assert(!isnull);
 7661 tgl                      5159 GBC         264 :     rulename = NameStr(*(DatumGetName(dat)));
                               5160                 : 
 8986 bruce                    5161 CBC         264 :     fno = SPI_fnumber(rulettc, "ev_type");
 7661 tgl                      5162 GIC         264 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
                               5163             264 :     Assert(!isnull);
                               5164             264 :     ev_type = DatumGetChar(dat);
                               5165                 : 
 8986 bruce                    5166 CBC         264 :     fno = SPI_fnumber(rulettc, "ev_class");
 7661 tgl                      5167 GIC         264 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
                               5168             264 :     Assert(!isnull);
 7661 tgl                      5169 CBC         264 :     ev_class = DatumGetObjectId(dat);
 8986 bruce                    5170 ECB             : 
 8986 bruce                    5171 GIC         264 :     fno = SPI_fnumber(rulettc, "is_instead");
 7661 tgl                      5172 GBC         264 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
 7661 tgl                      5173 GIC         264 :     Assert(!isnull);
                               5174             264 :     is_instead = DatumGetBool(dat);
 8986 bruce                    5175 ECB             : 
 8986 bruce                    5176 GIC         264 :     fno = SPI_fnumber(rulettc, "ev_qual");
 8986 bruce                    5177 CBC         264 :     ev_qual = SPI_getvalue(ruletup, rulettc, fno);
  888 tgl                      5178             264 :     Assert(ev_qual != NULL);
 8986 bruce                    5179 ECB             : 
 8986 bruce                    5180 CBC         264 :     fno = SPI_fnumber(rulettc, "ev_action");
 8986 bruce                    5181 GIC         264 :     ev_action = SPI_getvalue(ruletup, rulettc, fno);
  888 tgl                      5182 CBC         264 :     Assert(ev_action != NULL);
                               5183             264 :     actions = (List *) stringToNode(ev_action);
                               5184             264 :     if (actions == NIL)
  888 tgl                      5185 UIC           0 :         elog(ERROR, "invalid empty ev_action list");
 8986 bruce                    5186 ECB             : 
 1539 andres                   5187 CBC         264 :     ev_relation = table_open(ev_class, AccessShareLock);
 2085 tgl                      5188 ECB             : 
                               5189                 :     /*
 8986 bruce                    5190                 :      * Build the rules definition text
                               5191                 :      */
 7193 tgl                      5192 CBC         264 :     appendStringInfo(buf, "CREATE RULE %s AS",
                               5193                 :                      quote_identifier(rulename));
 8986 bruce                    5194 EUB             : 
 7193 tgl                      5195 GBC         264 :     if (prettyFlags & PRETTYFLAG_INDENT)
 7188 bruce                    5196 GIC         264 :         appendStringInfoString(buf, "\n    ON ");
                               5197                 :     else
 7188 bruce                    5198 UIC           0 :         appendStringInfoString(buf, " ON ");
                               5199                 : 
                               5200                 :     /* The event the rule is fired for */
 8986 bruce                    5201 GIC         264 :     switch (ev_type)
                               5202                 :     {
 8986 bruce                    5203 CBC           3 :         case '1':
 3447 rhaas                    5204               3 :             appendStringInfoString(buf, "SELECT");
 2085 tgl                      5205               3 :             viewResultDesc = RelationGetDescr(ev_relation);
 8994 bruce                    5206               3 :             break;
                               5207                 : 
 8986 bruce                    5208 GIC          71 :         case '2':
 3447 rhaas                    5209 CBC          71 :             appendStringInfoString(buf, "UPDATE");
 8994 bruce                    5210 GIC          71 :             break;
                               5211                 : 
 8986                          5212             138 :         case '3':
 3447 rhaas                    5213             138 :             appendStringInfoString(buf, "INSERT");
 8994 bruce                    5214             138 :             break;
                               5215                 : 
 8986 bruce                    5216 CBC          52 :         case '4':
 3447 rhaas                    5217              52 :             appendStringInfoString(buf, "DELETE");
 8994 bruce                    5218              52 :             break;
                               5219                 : 
 8986 bruce                    5220 LBC           0 :         default:
 7196 tgl                      5221 UIC           0 :             ereport(ERROR,
                               5222                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               5223                 :                      errmsg("rule \"%s\" has unsupported event type %d",
                               5224                 :                             rulename, ev_type)));
                               5225                 :             break;
                               5226                 :     }
 8994 bruce                    5227 ECB             : 
                               5228                 :     /* The relation the rule is fired on */
 1868 tgl                      5229 GIC         264 :     appendStringInfo(buf, " TO %s",
                               5230             264 :                      (prettyFlags & PRETTYFLAG_SCHEMA) ?
                               5231              48 :                      generate_relation_name(ev_class, NIL) :
                               5232             216 :                      generate_qualified_relation_name(ev_class));
                               5233                 : 
 8986 bruce                    5234 ECB             :     /* If the rule has an event qualification, add it */
  888 tgl                      5235 GIC         264 :     if (strcmp(ev_qual, "<>") != 0)
                               5236                 :     {
 8986 bruce                    5237 ECB             :         Node       *qual;
                               5238                 :         Query      *query;
 8397                          5239                 :         deparse_context context;
 8089 tgl                      5240                 :         deparse_namespace dpns;
 8589                          5241                 : 
 7193 tgl                      5242 CBC          58 :         if (prettyFlags & PRETTYFLAG_INDENT)
 7188 bruce                    5243              58 :             appendStringInfoString(buf, "\n  ");
 3447 rhaas                    5244              58 :         appendStringInfoString(buf, " WHERE ");
 8994 bruce                    5245 ECB             : 
 8986 bruce                    5246 CBC          58 :         qual = stringToNode(ev_qual);
 7804 tgl                      5247 ECB             : 
                               5248                 :         /*
                               5249                 :          * We need to make a context for recognizing any Vars in the qual
 6385 bruce                    5250                 :          * (which can only be references to OLD and NEW).  Use the rtable of
                               5251                 :          * the first query in the action list for this purpose.
 7804 tgl                      5252                 :          */
 6892 neilc                    5253 GIC          58 :         query = (Query *) linitial(actions);
                               5254                 : 
 7804 tgl                      5255 ECB             :         /*
                               5256                 :          * If the action is INSERT...SELECT, OLD/NEW have been pushed down
                               5257                 :          * into the SELECT, and that's what we need to look at. (Ugly kluge
 6385 bruce                    5258                 :          * ... try to fix this when we redesign querytrees.)
 7804 tgl                      5259                 :          */
 7804 tgl                      5260 GIC          58 :         query = getInsertSelectQuery(query, NULL);
                               5261                 : 
 6519 tgl                      5262 ECB             :         /* Must acquire locks right away; see notes in get_query_def() */
 3321 tgl                      5263 GIC          58 :         AcquireRewriteLocks(query, false, false);
                               5264                 : 
 8589                          5265              58 :         context.buf = buf;
 6888 neilc                    5266              58 :         context.namespaces = list_make1(&dpns);
 5215 tgl                      5267 CBC          58 :         context.windowClause = NIL;
                               5268              58 :         context.windowTList = NIL;
 6888 neilc                    5269 GIC          58 :         context.varprefix = (list_length(query->rtable) != 1);
 7193 tgl                      5270 CBC          58 :         context.prettyFlags = prettyFlags;
 3758                          5271              58 :         context.wrapColumn = WRAP_COLUMN_DEFAULT;
 7193 tgl                      5272 GIC          58 :         context.indentLevel = PRETTYINDENT_STD;
 2885 andres                   5273 CBC          58 :         context.special_exprkind = EXPR_KIND_NONE;
 1215 tgl                      5274              58 :         context.appendparents = NULL;
                               5275                 : 
 3751 tgl                      5276 GBC          58 :         set_deparse_for_query(&dpns, query, NIL);
                               5277                 : 
 7507 tgl                      5278 CBC          58 :         get_rule_expr(qual, &context, false);
                               5279                 :     }
                               5280                 : 
 3447 rhaas                    5281 GIC         264 :     appendStringInfoString(buf, " DO ");
                               5282                 : 
                               5283                 :     /* The INSTEAD keyword (if so) */
 8986 bruce                    5284 CBC         264 :     if (is_instead)
 3447 rhaas                    5285             162 :         appendStringInfoString(buf, "INSTEAD ");
                               5286                 : 
 8986 bruce                    5287 ECB             :     /* Finally the rules actions */
 6888 neilc                    5288 GIC         264 :     if (list_length(actions) > 1)
                               5289                 :     {
 6892 neilc                    5290 ECB             :         ListCell   *action;
 8986 bruce                    5291                 :         Query      *query;
                               5292                 : 
 3447 rhaas                    5293 GIC          10 :         appendStringInfoChar(buf, '(');
 8986 bruce                    5294              30 :         foreach(action, actions)
                               5295                 :         {
                               5296              20 :             query = (Query *) lfirst(action);
  323 tgl                      5297              20 :             get_query_def(query, buf, NIL, viewResultDesc, true,
                               5298                 :                           prettyFlags, WRAP_COLUMN_DEFAULT, 0);
 7193                          5299              20 :             if (prettyFlags)
 3447 rhaas                    5300 CBC          20 :                 appendStringInfoString(buf, ";\n");
                               5301                 :             else
 3447 rhaas                    5302 UIC           0 :                 appendStringInfoString(buf, "; ");
                               5303                 :         }
 3447 rhaas                    5304 GIC          10 :         appendStringInfoString(buf, ");");
                               5305                 :     }
                               5306                 :     else
                               5307                 :     {
                               5308                 :         Query      *query;
                               5309                 : 
 6892 neilc                    5310             254 :         query = (Query *) linitial(actions);
  323 tgl                      5311             254 :         get_query_def(query, buf, NIL, viewResultDesc, true,
                               5312                 :                       prettyFlags, WRAP_COLUMN_DEFAULT, 0);
 3447 rhaas                    5313             254 :         appendStringInfoChar(buf, ';');
                               5314                 :     }
                               5315                 : 
 1539 andres                   5316             264 :     table_close(ev_relation, AccessShareLock);
 8994 bruce                    5317             264 : }
 8994 bruce                    5318 ECB             : 
                               5319                 : 
                               5320                 : /* ----------
                               5321                 :  * make_viewdef         - reconstruct the SELECT part of a
                               5322                 :  *                view rewrite rule
                               5323                 :  * ----------
                               5324                 :  */
 8590 tgl                      5325                 : static void
 7193 tgl                      5326 CBC        1408 : make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
                               5327                 :              int prettyFlags, int wrapColumn)
 8994 bruce                    5328 ECB             : {
 8986                          5329                 :     Query      *query;
                               5330                 :     char        ev_type;
                               5331                 :     Oid         ev_class;
                               5332                 :     bool        is_instead;
                               5333                 :     char       *ev_qual;
                               5334                 :     char       *ev_action;
  888 tgl                      5335                 :     List       *actions;
                               5336                 :     Relation    ev_relation;
 8986 bruce                    5337                 :     int         fno;
 2085 tgl                      5338                 :     Datum       dat;
 8986 bruce                    5339                 :     bool        isnull;
                               5340                 : 
                               5341                 :     /*
                               5342                 :      * Get the attribute values from the rules tuple
                               5343                 :      */
 8986 bruce                    5344 GIC        1408 :     fno = SPI_fnumber(rulettc, "ev_type");
 2085 tgl                      5345 GBC        1408 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
 2085 tgl                      5346 GIC        1408 :     Assert(!isnull);
                               5347            1408 :     ev_type = DatumGetChar(dat);
 8986 bruce                    5348 ECB             : 
 8986 bruce                    5349 GIC        1408 :     fno = SPI_fnumber(rulettc, "ev_class");
 2085 tgl                      5350 CBC        1408 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
                               5351            1408 :     Assert(!isnull);
 2085 tgl                      5352 GIC        1408 :     ev_class = DatumGetObjectId(dat);
                               5353                 : 
 8986 bruce                    5354 GBC        1408 :     fno = SPI_fnumber(rulettc, "is_instead");
 2085 tgl                      5355 GIC        1408 :     dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
                               5356            1408 :     Assert(!isnull);
 2085 tgl                      5357 CBC        1408 :     is_instead = DatumGetBool(dat);
                               5358                 : 
 8986 bruce                    5359            1408 :     fno = SPI_fnumber(rulettc, "ev_qual");
 8986 bruce                    5360 GIC        1408 :     ev_qual = SPI_getvalue(ruletup, rulettc, fno);
  888 tgl                      5361 CBC        1408 :     Assert(ev_qual != NULL);
                               5362                 : 
 8986 bruce                    5363            1408 :     fno = SPI_fnumber(rulettc, "ev_action");
 8986 bruce                    5364 GIC        1408 :     ev_action = SPI_getvalue(ruletup, rulettc, fno);
  888 tgl                      5365            1408 :     Assert(ev_action != NULL);
                               5366            1408 :     actions = (List *) stringToNode(ev_action);
                               5367                 : 
 6888 neilc                    5368            1408 :     if (list_length(actions) != 1)
                               5369                 :     {
                               5370                 :         /* keep output buffer empty and leave */
 8590 tgl                      5371 UIC           0 :         return;
                               5372                 :     }
                               5373                 : 
 6892 neilc                    5374 GIC        1408 :     query = (Query *) linitial(actions);
                               5375                 : 
 3503 kgrittn                  5376            1408 :     if (ev_type != '1' || !is_instead ||
 7549 tgl                      5377            1408 :         strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
                               5378                 :     {
                               5379                 :         /* keep output buffer empty and leave */
 8590 tgl                      5380 UIC           0 :         return;
                               5381                 :     }
                               5382                 : 
 1539 andres                   5383 GIC        1408 :     ev_relation = table_open(ev_class, AccessShareLock);
                               5384                 : 
  323 tgl                      5385 CBC        1408 :     get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), true,
                               5386                 :                   prettyFlags, wrapColumn, 0);
 3447 rhaas                    5387 GIC        1408 :     appendStringInfoChar(buf, ';');
                               5388                 : 
 1539 andres                   5389            1408 :     table_close(ev_relation, AccessShareLock);
                               5390                 : }
                               5391                 : 
                               5392                 : 
 8994 bruce                    5393 ECB             : /* ----------
 7549 tgl                      5394                 :  * get_query_def            - Parse back one query parsetree
                               5395                 :  *
                               5396                 :  * query: parsetree to be displayed
                               5397                 :  * buf: output text is appended to buf
                               5398                 :  * parentnamespace: list (initially empty) of outer-level deparse_namespace's
                               5399                 :  * resultDesc: if not NULL, the output tuple descriptor for the view
                               5400                 :  *      represented by a SELECT query.  We use the column names from it
                               5401                 :  *      to label SELECT output columns, in preference to names in the query
                               5402                 :  * colNamesVisible: true if the surrounding context cares about the output
                               5403                 :  *      column names at all (as, for example, an EXISTS() context does not);
                               5404                 :  *      when false, we can suppress dummy column labels such as "?column?"
  323                          5405                 :  * prettyFlags: bitmask of PRETTYFLAG_XXX options
                               5406                 :  * wrapColumn: maximum line length, or -1 to disable wrapping
                               5407                 :  * startIndent: initial indentation amount
 8994 bruce                    5408                 :  * ----------
                               5409                 :  */
 8590 tgl                      5410                 : static void
 7549 tgl                      5411 CBC        2294 : get_query_def(Query *query, StringInfo buf, List *parentnamespace,
  323 tgl                      5412 ECB             :               TupleDesc resultDesc, bool colNamesVisible,
 3758                          5413                 :               int prettyFlags, int wrapColumn, int startIndent)
 8994 bruce                    5414                 : {
 8397                          5415                 :     deparse_context context;
 8089 tgl                      5416                 :     deparse_namespace dpns;
 8955 bruce                    5417                 : 
                               5418                 :     /* Guard against excessively long or deeply-nested queries */
 3266 tgl                      5419 CBC        2294 :     CHECK_FOR_INTERRUPTS();
 3266 tgl                      5420 GIC        2294 :     check_stack_depth();
 3266 tgl                      5421 ECB             : 
                               5422                 :     /*
 6519                          5423                 :      * Before we begin to examine the query, acquire locks on referenced
 3260 bruce                    5424                 :      * relations, and fix up deleted columns in JOIN RTEs.  This ensures
                               5425                 :      * consistent results.  Note we assume it's OK to scribble on the passed
                               5426                 :      * querytree!
 3321 tgl                      5427                 :      *
                               5428                 :      * We are only deparsing the query (we are not about to execute it), so we
                               5429                 :      * only need AccessShareLock on the relations it mentions.
                               5430                 :      */
 3321 tgl                      5431 CBC        2294 :     AcquireRewriteLocks(query, false, false);
 6519 tgl                      5432 ECB             : 
 8589 tgl                      5433 CBC        2294 :     context.buf = buf;
 6892 neilc                    5434 GIC        2294 :     context.namespaces = lcons(&dpns, list_copy(parentnamespace));
 5215 tgl                      5435 CBC        2294 :     context.windowClause = NIL;
                               5436            2294 :     context.windowTList = NIL;
 8089                          5437            3976 :     context.varprefix = (parentnamespace != NIL ||
 6888 neilc                    5438 GIC        1682 :                          list_length(query->rtable) != 1);
 7193 tgl                      5439 CBC        2294 :     context.prettyFlags = prettyFlags;
 3758                          5440            2294 :     context.wrapColumn = wrapColumn;
 7193                          5441            2294 :     context.indentLevel = startIndent;
 2885 andres                   5442 GIC        2294 :     context.special_exprkind = EXPR_KIND_NONE;
 1215 tgl                      5443 CBC        2294 :     context.appendparents = NULL;
 7193 tgl                      5444 ECB             : 
 3751 tgl                      5445 CBC        2294 :     set_deparse_for_query(&dpns, query, parentnamespace);
                               5446                 : 
 8986 bruce                    5447 GBC        2294 :     switch (query->commandType)
 8986 bruce                    5448 EUB             :     {
 8720 bruce                    5449 GIC        2004 :         case CMD_SELECT:
  323 tgl                      5450            2004 :             get_select_query_def(query, &context, resultDesc, colNamesVisible);
 8986 bruce                    5451            2004 :             break;
 8986 bruce                    5452 ECB             : 
 8986 bruce                    5453 GIC          65 :         case CMD_UPDATE:
  323 tgl                      5454              65 :             get_update_query_def(query, &context, colNamesVisible);
 8986 bruce                    5455              65 :             break;
                               5456                 : 
                               5457             161 :         case CMD_INSERT:
  323 tgl                      5458             161 :             get_insert_query_def(query, &context, colNamesVisible);
 8986 bruce                    5459 CBC         161 :             break;
                               5460                 : 
                               5461              38 :         case CMD_DELETE:
  323 tgl                      5462              38 :             get_delete_query_def(query, &context, colNamesVisible);
 8986 bruce                    5463 GIC          38 :             break;
                               5464                 : 
 8986 bruce                    5465 CBC          18 :         case CMD_NOTHING:
 3447 rhaas                    5466 GIC          18 :             appendStringInfoString(buf, "NOTHING");
 8986 bruce                    5467 CBC          18 :             break;
                               5468                 : 
 8131 tgl                      5469               8 :         case CMD_UTILITY:
                               5470               8 :             get_utility_query_def(query, &context);
 8131 tgl                      5471 GIC           8 :             break;
                               5472                 : 
 8986 bruce                    5473 LBC           0 :         default:
 7196 tgl                      5474               0 :             elog(ERROR, "unrecognized query command type: %d",
                               5475                 :                  query->commandType);
 8986 bruce                    5476 ECB             :             break;
                               5477                 :     }
 8994 bruce                    5478 CBC        2294 : }
 8994 bruce                    5479 ECB             : 
                               5480                 : /* ----------
 6094 mail                     5481                 :  * get_values_def           - Parse back a VALUES list
                               5482                 :  * ----------
                               5483                 :  */
                               5484                 : static void
 6094 mail                     5485 GIC         130 : get_values_def(List *values_lists, deparse_context *context)
 6094 mail                     5486 ECB             : {
 6094 mail                     5487 GIC         130 :     StringInfo  buf = context->buf;
                               5488             130 :     bool        first_list = true;
                               5489                 :     ListCell   *vtl;
                               5490                 : 
 6094 mail                     5491 CBC         130 :     appendStringInfoString(buf, "VALUES ");
                               5492                 : 
                               5493             374 :     foreach(vtl, values_lists)
                               5494                 :     {
                               5495             244 :         List       *sublist = (List *) lfirst(vtl);
 6094 mail                     5496 GIC         244 :         bool        first_col = true;
                               5497                 :         ListCell   *lc;
                               5498                 : 
                               5499             244 :         if (first_list)
                               5500             130 :             first_list = false;
                               5501                 :         else
 6094 mail                     5502 CBC         114 :             appendStringInfoString(buf, ", ");
                               5503                 : 
                               5504             244 :         appendStringInfoChar(buf, '(');
 6094 mail                     5505 GIC         955 :         foreach(lc, sublist)
                               5506                 :         {
 6031 bruce                    5507             711 :             Node       *col = (Node *) lfirst(lc);
 6094 mail                     5508 ECB             : 
 6094 mail                     5509 CBC         711 :             if (first_col)
 6094 mail                     5510 GIC         244 :                 first_col = false;
 6094 mail                     5511 ECB             :             else
 6094 mail                     5512 GIC         467 :                 appendStringInfoChar(buf, ',');
 6094 mail                     5513 ECB             : 
                               5514                 :             /*
                               5515                 :              * Print the value.  Whole-row Vars need special treatment.
                               5516                 :              */
 2440 tgl                      5517 CBC         711 :             get_rule_expr_toplevel(col, context, false);
 6094 mail                     5518 ECB             :         }
 6094 mail                     5519 GIC         244 :         appendStringInfoChar(buf, ')');
 6094 mail                     5520 ECB             :     }
 6094 mail                     5521 CBC         130 : }
                               5522                 : 
 5300 tgl                      5523 ECB             : /* ----------
                               5524                 :  * get_with_clause          - Parse back a WITH clause
                               5525                 :  * ----------
                               5526                 :  */
                               5527                 : static void
 5300 tgl                      5528 GIC        2268 : get_with_clause(Query *query, deparse_context *context)
 5300 tgl                      5529 ECB             : {
 5300 tgl                      5530 GIC        2268 :     StringInfo  buf = context->buf;
                               5531                 :     const char *sep;
 5050 bruce                    5532 ECB             :     ListCell   *l;
 5300 tgl                      5533                 : 
 5300 tgl                      5534 GIC        2268 :     if (query->cteList == NIL)
 5300 tgl                      5535 CBC        2226 :         return;
 5300 tgl                      5536 ECB             : 
 5300 tgl                      5537 GIC          42 :     if (PRETTY_INDENT(context))
 5300 tgl                      5538 ECB             :     {
 5300 tgl                      5539 CBC          42 :         context->indentLevel += PRETTYINDENT_STD;
                               5540              42 :         appendStringInfoChar(buf, ' ');
                               5541                 :     }
 5300 tgl                      5542 ECB             : 
 5300 tgl                      5543 GIC          42 :     if (query->hasRecursive)
 5300 tgl                      5544 CBC          28 :         sep = "WITH RECURSIVE ";
 5300 tgl                      5545 ECB             :     else
 5300 tgl                      5546 GIC          14 :         sep = "WITH ";
 5300 tgl                      5547 CBC         100 :     foreach(l, query->cteList)
 5300 tgl                      5548 ECB             :     {
 5300 tgl                      5549 CBC          58 :         CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
 5300 tgl                      5550 ECB             : 
 5300 tgl                      5551 CBC          58 :         appendStringInfoString(buf, sep);
 5300 tgl                      5552 GBC          58 :         appendStringInfoString(buf, quote_identifier(cte->ctename));
                               5553              58 :         if (cte->aliascolnames)
 5300 tgl                      5554 EUB             :         {
 5300 tgl                      5555 GIC          22 :             bool        first = true;
 5300 tgl                      5556 ECB             :             ListCell   *col;
                               5557                 : 
 5300 tgl                      5558 CBC          22 :             appendStringInfoChar(buf, '(');
                               5559              62 :             foreach(col, cte->aliascolnames)
                               5560                 :             {
 5300 tgl                      5561 GIC          40 :                 if (first)
                               5562              22 :                     first = false;
 5300 tgl                      5563 ECB             :                 else
 5300 tgl                      5564 CBC          18 :                     appendStringInfoString(buf, ", ");
                               5565              40 :                 appendStringInfoString(buf,
 5300 tgl                      5566 GIC          40 :                                        quote_identifier(strVal(lfirst(col))));
 5300 tgl                      5567 ECB             :             }
 5300 tgl                      5568 GIC          22 :             appendStringInfoChar(buf, ')');
 5300 tgl                      5569 ECB             :         }
 1513 tgl                      5570 GIC          58 :         appendStringInfoString(buf, " AS ");
                               5571              58 :         switch (cte->ctematerialized)
 1513 tgl                      5572 ECB             :         {
 1513 tgl                      5573 CBC          52 :             case CTEMaterializeDefault:
 1513 tgl                      5574 GIC          52 :                 break;
 1513 tgl                      5575 CBC           6 :             case CTEMaterializeAlways:
 1513 tgl                      5576 GIC           6 :                 appendStringInfoString(buf, "MATERIALIZED ");
 1513 tgl                      5577 CBC           6 :                 break;
 1513 tgl                      5578 LBC           0 :             case CTEMaterializeNever:
 1513 tgl                      5579 UIC           0 :                 appendStringInfoString(buf, "NOT MATERIALIZED ");
 1513 tgl                      5580 LBC           0 :                 break;
 1513 tgl                      5581 ECB             :         }
 1513 tgl                      5582 CBC          58 :         appendStringInfoChar(buf, '(');
 5300 tgl                      5583 GIC          58 :         if (PRETTY_INDENT(context))
                               5584              58 :             appendContextKeyword(context, "", 0, 0, 0);
 5300 tgl                      5585 CBC          58 :         get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
                               5586                 :                       true,
                               5587                 :                       context->prettyFlags, context->wrapColumn,
 3758 tgl                      5588 ECB             :                       context->indentLevel);
 5300 tgl                      5589 GIC          58 :         if (PRETTY_INDENT(context))
 5300 tgl                      5590 CBC          58 :             appendContextKeyword(context, "", 0, 0, 0);
 5300 tgl                      5591 GIC          58 :         appendStringInfoChar(buf, ')');
                               5592                 : 
  797 peter                    5593 CBC          58 :         if (cte->search_clause)
                               5594                 :         {
                               5595               3 :             bool        first = true;
                               5596                 :             ListCell   *lc;
  797 peter                    5597 ECB             : 
  797 peter                    5598 CBC           3 :             appendStringInfo(buf, " SEARCH %s FIRST BY ",
  797 peter                    5599 GIC           3 :                              cte->search_clause->search_breadth_first ? "BREADTH" : "DEPTH");
  797 peter                    5600 ECB             : 
  797 peter                    5601 CBC           9 :             foreach(lc, cte->search_clause->search_col_list)
  797 peter                    5602 ECB             :             {
  797 peter                    5603 GIC           6 :                 if (first)
                               5604               3 :                     first = false;
  797 peter                    5605 ECB             :                 else
  797 peter                    5606 GIC           3 :                     appendStringInfoString(buf, ", ");
                               5607               6 :                 appendStringInfoString(buf,
  797 peter                    5608 CBC           6 :                                        quote_identifier(strVal(lfirst(lc))));
  797 peter                    5609 ECB             :             }
                               5610                 : 
  797 peter                    5611 CBC           3 :             appendStringInfo(buf, " SET %s", quote_identifier(cte->search_clause->search_seq_column));
  797 peter                    5612 ECB             :         }
                               5613                 : 
  797 peter                    5614 CBC          58 :         if (cte->cycle_clause)
  797 peter                    5615 ECB             :         {
  797 peter                    5616 CBC           6 :             bool        first = true;
  797 peter                    5617 ECB             :             ListCell   *lc;
                               5618                 : 
  797 peter                    5619 GIC           6 :             appendStringInfoString(buf, " CYCLE ");
                               5620                 : 
  797 peter                    5621 CBC          18 :             foreach(lc, cte->cycle_clause->cycle_col_list)
                               5622                 :             {
  797 peter                    5623 GIC          12 :                 if (first)
  797 peter                    5624 CBC           6 :                     first = false;
                               5625                 :                 else
  797 peter                    5626 GIC           6 :                     appendStringInfoString(buf, ", ");
  797 peter                    5627 CBC          12 :                 appendStringInfoString(buf,
  797 peter                    5628 GIC          12 :                                        quote_identifier(strVal(lfirst(lc))));
  797 peter                    5629 ECB             :             }
                               5630                 : 
  797 peter                    5631 GIC           6 :             appendStringInfo(buf, " SET %s", quote_identifier(cte->cycle_clause->cycle_mark_column));
                               5632                 : 
  771 peter                    5633 EUB             :             {
  771 peter                    5634 GIC           6 :                 Const      *cmv = castNode(Const, cte->cycle_clause->cycle_mark_value);
                               5635               6 :                 Const      *cmd = castNode(Const, cte->cycle_clause->cycle_mark_default);
                               5636                 : 
                               5637               9 :                 if (!(cmv->consttype == BOOLOID && !cmv->constisnull && DatumGetBool(cmv->constvalue) == true &&
                               5638               3 :                       cmd->consttype == BOOLOID && !cmd->constisnull && DatumGetBool(cmd->constvalue) == false))
                               5639                 :                 {
                               5640               3 :                     appendStringInfoString(buf, " TO ");
  771 peter                    5641 CBC           3 :                     get_rule_expr(cte->cycle_clause->cycle_mark_value, context, false);
  771 peter                    5642 GIC           3 :                     appendStringInfoString(buf, " DEFAULT ");
                               5643               3 :                     get_rule_expr(cte->cycle_clause->cycle_mark_default, context, false);
  771 peter                    5644 ECB             :                 }
                               5645                 :             }
                               5646                 : 
  797 peter                    5647 GIC           6 :             appendStringInfo(buf, " USING %s", quote_identifier(cte->cycle_clause->cycle_path_column));
                               5648                 :         }
                               5649                 : 
 5300 tgl                      5650              58 :         sep = ", ";
 5300 tgl                      5651 ECB             :     }
                               5652                 : 
 5300 tgl                      5653 GIC          42 :     if (PRETTY_INDENT(context))
 5300 tgl                      5654 ECB             :     {
 5300 tgl                      5655 CBC          42 :         context->indentLevel -= PRETTYINDENT_STD;
                               5656              42 :         appendContextKeyword(context, "", 0, 0, 0);
 5300 tgl                      5657 ECB             :     }
                               5658                 :     else
 5300 tgl                      5659 UIC           0 :         appendStringInfoChar(buf, ' ');
                               5660                 : }
                               5661                 : 
                               5662                 : /* ----------
                               5663                 :  * get_select_query_def         - Parse back a SELECT parsetree
 8994 bruce                    5664 ECB             :  * ----------
                               5665                 :  */
 8590 tgl                      5666                 : static void
 7549 tgl                      5667 GIC        2004 : get_select_query_def(Query *query, deparse_context *context,
                               5668                 :                      TupleDesc resultDesc, bool colNamesVisible)
 8221 tgl                      5669 ECB             : {
 8221 tgl                      5670 GIC        2004 :     StringInfo  buf = context->buf;
                               5671                 :     List       *save_windowclause;
                               5672                 :     List       *save_windowtlist;
 8029 tgl                      5673 ECB             :     bool        force_colno;
 6892 neilc                    5674                 :     ListCell   *l;
                               5675                 : 
                               5676                 :     /* Insert the WITH clause if given */
 5300 tgl                      5677 GIC        2004 :     get_with_clause(query, context);
 5300 tgl                      5678 ECB             : 
                               5679                 :     /* Set up context for possible window functions */
 5215 tgl                      5680 CBC        2004 :     save_windowclause = context->windowClause;
 5215 tgl                      5681 GIC        2004 :     context->windowClause = query->windowClause;
 5215 tgl                      5682 CBC        2004 :     save_windowtlist = context->windowTList;
 5215 tgl                      5683 GIC        2004 :     context->windowTList = query->targetList;
                               5684                 : 
                               5685                 :     /*
                               5686                 :      * If the Query node has a setOperations tree, then it's the top level of
                               5687                 :      * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
                               5688                 :      * fields are interesting in the top query itself.
                               5689                 :      */
 8221 tgl                      5690 CBC        2004 :     if (query->setOperations)
                               5691                 :     {
  323                          5692              70 :         get_setop_query(query->setOperations, query, context, resultDesc,
                               5693                 :                         colNamesVisible);
 8221 tgl                      5694 ECB             :         /* ORDER BY clauses must be simple in this case */
 8029 tgl                      5695 GIC          70 :         force_colno = true;
 8221 tgl                      5696 ECB             :     }
                               5697                 :     else
                               5698                 :     {
  323 tgl                      5699 GIC        1934 :         get_basic_select_query(query, context, resultDesc, colNamesVisible);
 8029 tgl                      5700 CBC        1934 :         force_colno = false;
                               5701                 :     }
 8221 tgl                      5702 ECB             : 
                               5703                 :     /* Add the ORDER BY clause if given */
 8221 tgl                      5704 GIC        2004 :     if (query->sortClause != NIL)
                               5705                 :     {
 7188 bruce                    5706              64 :         appendContextKeyword(context, " ORDER BY ",
 7188 bruce                    5707 ECB             :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
 5215 tgl                      5708 GIC          64 :         get_rule_orderby(query->sortClause, query->targetList,
 5215 tgl                      5709 ECB             :                          force_colno, context);
 8221                          5710                 :     }
 8200                          5711                 : 
                               5712                 :     /*
 1097 alvherre                 5713                 :      * Add the LIMIT/OFFSET clauses if given. If non-default options, use the
                               5714                 :      * standard spelling of LIMIT.
                               5715                 :      */
 8200 tgl                      5716 GIC        2004 :     if (query->limitOffset != NULL)
                               5717                 :     {
 7193 tgl                      5718 CBC          16 :         appendContextKeyword(context, " OFFSET ",
                               5719                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
 7507                          5720              16 :         get_rule_expr(query->limitOffset, context, false);
                               5721                 :     }
 8200                          5722            2004 :     if (query->limitCount != NULL)
                               5723                 :     {
 1097 alvherre                 5724 GIC          35 :         if (query->limitOption == LIMIT_OPTION_WITH_TIES)
 1097 alvherre                 5725 ECB             :         {
 1097 alvherre                 5726 GBC          16 :             appendContextKeyword(context, " FETCH FIRST ",
                               5727                 :                                  -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
 7507 tgl                      5728 CBC          16 :             get_rule_expr(query->limitCount, context, false);
  906 drowley                  5729 GIC          16 :             appendStringInfoString(buf, " ROWS WITH TIES");
 1097 alvherre                 5730 EUB             :         }
                               5731                 :         else
                               5732                 :         {
 1097 alvherre                 5733 GIC          19 :             appendContextKeyword(context, " LIMIT ",
                               5734                 :                                  -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
 1097 alvherre                 5735 GBC          19 :             if (IsA(query->limitCount, Const) &&
                               5736               8 :                 ((Const *) query->limitCount)->constisnull)
 1097 alvherre                 5737 GIC           8 :                 appendStringInfoString(buf, "ALL");
 1097 alvherre                 5738 EUB             :             else
 1097 alvherre                 5739 GBC          11 :                 get_rule_expr(query->limitCount, context, false);
 1097 alvherre                 5740 EUB             :         }
                               5741                 :     }
 6523 tgl                      5742                 : 
 3728 alvherre                 5743                 :     /* Add FOR [KEY] UPDATE/SHARE clauses if present */
 4911 tgl                      5744 GBC        2004 :     if (query->hasForUpdate)
                               5745                 :     {
                               5746               6 :         foreach(l, query->rowMarks)
 4911 tgl                      5747 ECB             :         {
 4911 tgl                      5748 CBC           3 :             RowMarkClause *rc = (RowMarkClause *) lfirst(l);
                               5749                 : 
 4911 tgl                      5750 ECB             :             /* don't print implicit clauses */
 4911 tgl                      5751 GIC           3 :             if (rc->pushedDown)
 4911 tgl                      5752 UIC           0 :                 continue;
 4911 tgl                      5753 ECB             : 
 3728 alvherre                 5754 CBC           3 :             switch (rc->strength)
                               5755                 :             {
 2947 tgl                      5756 LBC           0 :                 case LCS_NONE:
 2947 tgl                      5757 EUB             :                     /* we intentionally throw an error for LCS_NONE */
 2947 tgl                      5758 LBC           0 :                     elog(ERROR, "unrecognized LockClauseStrength %d",
 2947 tgl                      5759 EUB             :                          (int) rc->strength);
                               5760                 :                     break;
 3728 alvherre                 5761 UIC           0 :                 case LCS_FORKEYSHARE:
                               5762               0 :                     appendContextKeyword(context, " FOR KEY SHARE",
 2118 tgl                      5763 ECB             :                                          -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
 3728 alvherre                 5764 LBC           0 :                     break;
                               5765               0 :                 case LCS_FORSHARE:
 3728 alvherre                 5766 UIC           0 :                     appendContextKeyword(context, " FOR SHARE",
                               5767                 :                                          -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
                               5768               0 :                     break;
                               5769               0 :                 case LCS_FORNOKEYUPDATE:
                               5770               0 :                     appendContextKeyword(context, " FOR NO KEY UPDATE",
                               5771                 :                                          -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
                               5772               0 :                     break;
 3728 alvherre                 5773 CBC           3 :                 case LCS_FORUPDATE:
 3728 alvherre                 5774 GIC           3 :                     appendContextKeyword(context, " FOR UPDATE",
 2118 tgl                      5775 ECB             :                                          -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
 3728 alvherre                 5776 GIC           3 :                     break;
                               5777                 :             }
                               5778                 : 
 4911 tgl                      5779               3 :             appendStringInfo(buf, " OF %s",
 3852                          5780               3 :                              quote_identifier(get_rtable_name(rc->rti,
                               5781                 :                                                               context)));
 3106 alvherre                 5782               3 :             if (rc->waitPolicy == LockWaitError)
 3447 rhaas                    5783 LBC           0 :                 appendStringInfoString(buf, " NOWAIT");
 3106 alvherre                 5784 GIC           3 :             else if (rc->waitPolicy == LockWaitSkip)
 3106 alvherre                 5785 LBC           0 :                 appendStringInfoString(buf, " SKIP LOCKED");
                               5786                 :         }
 6523 tgl                      5787 ECB             :     }
                               5788                 : 
 5215 tgl                      5789 CBC        2004 :     context->windowClause = save_windowclause;
                               5790            2004 :     context->windowTList = save_windowtlist;
 8221                          5791            2004 : }
                               5792                 : 
 3885 tgl                      5793 ECB             : /*
 1240                          5794                 :  * Detect whether query looks like SELECT ... FROM VALUES(),
                               5795                 :  * with no need to rename the output columns of the VALUES RTE.
                               5796                 :  * If so, return the VALUES RTE.  Otherwise return NULL.
                               5797                 :  */
                               5798                 : static RangeTblEntry *
 1240 tgl                      5799 GIC        1934 : get_simple_values_rte(Query *query, TupleDesc resultDesc)
                               5800                 : {
 3885                          5801            1934 :     RangeTblEntry *result = NULL;
                               5802                 :     ListCell   *lc;
                               5803                 : 
                               5804                 :     /*
                               5805                 :      * We want to detect a match even if the Query also contains OLD or NEW
                               5806                 :      * rule RTEs.  So the idea is to scan the rtable and see if there is only
                               5807                 :      * one inFromCl RTE that is a VALUES RTE.
 3885 tgl                      5808 ECB             :      */
 3885 tgl                      5809 GIC        2105 :     foreach(lc, query->rtable)
                               5810                 :     {
                               5811            1756 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
                               5812                 : 
 3885 tgl                      5813 CBC        1756 :         if (rte->rtekind == RTE_VALUES && rte->inFromCl)
 3885 tgl                      5814 EUB             :         {
 3885 tgl                      5815 CBC         111 :             if (result)
                               5816            1585 :                 return NULL;    /* multiple VALUES (probably not possible) */
 3885 tgl                      5817 GIC         111 :             result = rte;
 3885 tgl                      5818 ECB             :         }
 3885 tgl                      5819 CBC        1645 :         else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
 3885 tgl                      5820 GIC          60 :             continue;           /* ignore rule entries */
                               5821                 :         else
 3885 tgl                      5822 CBC        1585 :             return NULL;        /* something else -> not simple VALUES */
 3885 tgl                      5823 ECB             :     }
                               5824                 : 
                               5825                 :     /*
 2965                          5826                 :      * We don't need to check the targetlist in any great detail, because
                               5827                 :      * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
                               5828                 :      * appear inside auto-generated sub-queries with very restricted
                               5829                 :      * structure.  However, DefineView might have modified the tlist by
 1240                          5830                 :      * injecting new column aliases, or we might have some other column
                               5831                 :      * aliases forced by a resultDesc.  We can only simplify if the RTE's
                               5832                 :      * column names match the names that get_target_list() would select.
 2965                          5833                 :      */
 2965 tgl                      5834 CBC         349 :     if (result)
                               5835                 :     {
                               5836                 :         ListCell   *lcn;
                               5837                 :         int         colno;
 2965 tgl                      5838 ECB             : 
 2965 tgl                      5839 GIC         111 :         if (list_length(query->targetList) != list_length(result->eref->colnames))
 2965 tgl                      5840 UIC           0 :             return NULL;        /* this probably cannot happen */
 1240 tgl                      5841 GIC         111 :         colno = 0;
 2965 tgl                      5842 CBC         415 :         forboth(lc, query->targetList, lcn, result->eref->colnames)
                               5843                 :         {
 2965 tgl                      5844 GIC         310 :             TargetEntry *tle = (TargetEntry *) lfirst(lc);
 2965 tgl                      5845 CBC         310 :             char       *cname = strVal(lfirst(lcn));
                               5846                 :             char       *colname;
                               5847                 : 
 2965 tgl                      5848 GIC         310 :             if (tle->resjunk)
                               5849               6 :                 return NULL;    /* this probably cannot happen */
 1240 tgl                      5850 ECB             : 
                               5851                 :             /* compute name that get_target_list would use for column */
 1240 tgl                      5852 CBC         310 :             colno++;
                               5853             310 :             if (resultDesc && colno <= resultDesc->natts)
 1240 tgl                      5854 GIC          15 :                 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
                               5855                 :             else
                               5856             295 :                 colname = tle->resname;
                               5857                 : 
                               5858                 :             /* does it match the VALUES RTE? */
                               5859             310 :             if (colname == NULL || strcmp(colname, cname) != 0)
 2965                          5860               6 :                 return NULL;    /* column name has been changed */
 2965 tgl                      5861 ECB             :         }
                               5862                 :     }
                               5863                 : 
 3885 tgl                      5864 CBC         343 :     return result;
 3885 tgl                      5865 ECB             : }
                               5866                 : 
                               5867                 : static void
 7549 tgl                      5868 GIC        1934 : get_basic_select_query(Query *query, deparse_context *context,
                               5869                 :                        TupleDesc resultDesc, bool colNamesVisible)
                               5870                 : {
 8589 tgl                      5871 CBC        1934 :     StringInfo  buf = context->buf;
 3885 tgl                      5872 ECB             :     RangeTblEntry *values_rte;
                               5873                 :     char       *sep;
 6892 neilc                    5874                 :     ListCell   *l;
                               5875                 : 
 7193 tgl                      5876 GIC        1934 :     if (PRETTY_INDENT(context))
 7193 tgl                      5877 ECB             :     {
 7188 bruce                    5878 GIC        1912 :         context->indentLevel += PRETTYINDENT_STD;
 7188 bruce                    5879 GBC        1912 :         appendStringInfoChar(buf, ' ');
                               5880                 :     }
 6094 mail                     5881 EUB             : 
                               5882                 :     /*
 6031 bruce                    5883                 :      * If the query looks like SELECT * FROM (VALUES ...), then print just the
                               5884                 :      * VALUES part.  This reverses what transformValuesClause() did at parse
 3885 tgl                      5885                 :      * time.
                               5886                 :      */
 1240 tgl                      5887 GBC        1934 :     values_rte = get_simple_values_rte(query, resultDesc);
 3885                          5888            1934 :     if (values_rte)
                               5889                 :     {
                               5890             105 :         get_values_def(values_rte->values_lists, context);
 3885 tgl                      5891 GIC         105 :         return;
 6094 mail                     5892 EUB             :     }
                               5893                 : 
                               5894                 :     /*
                               5895                 :      * Build up the query string - first we say SELECT
                               5896                 :      */
  732 peter                    5897 GIC        1829 :     if (query->isReturn)
                               5898              25 :         appendStringInfoString(buf, "RETURN");
  732 peter                    5899 ECB             :     else
  732 peter                    5900 GIC        1804 :         appendStringInfoString(buf, "SELECT");
                               5901                 : 
 8221 tgl                      5902 ECB             :     /* Add the DISTINCT clause if given */
 8221 tgl                      5903 GIC        1829 :     if (query->distinctClause != NIL)
                               5904                 :     {
 5363 tgl                      5905 LBC           0 :         if (query->hasDistinctOn)
                               5906                 :         {
 3447 rhaas                    5907               0 :             appendStringInfoString(buf, " DISTINCT ON (");
 8221 tgl                      5908 UIC           0 :             sep = "";
 8221 tgl                      5909 LBC           0 :             foreach(l, query->distinctClause)
                               5910                 :             {
 5363 tgl                      5911 UIC           0 :                 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
                               5912                 : 
 6553 neilc                    5913 LBC           0 :                 appendStringInfoString(buf, sep);
 2885 andres                   5914 UIC           0 :                 get_rule_sortgroupclause(srt->tleSortGroupRef, query->targetList,
                               5915                 :                                          false, context);
 8221 tgl                      5916               0 :                 sep = ", ";
 8221 tgl                      5917 ECB             :             }
 3447 rhaas                    5918 UIC           0 :             appendStringInfoChar(buf, ')');
 8221 tgl                      5919 ECB             :         }
 7922 tgl                      5920 EUB             :         else
 3447 rhaas                    5921 UIC           0 :             appendStringInfoString(buf, " DISTINCT");
 8221 tgl                      5922 ECB             :     }
                               5923                 : 
                               5924                 :     /* Then we tell what to select (the targetlist) */
  323 tgl                      5925 CBC        1829 :     get_target_list(query->targetList, context, resultDesc, colNamesVisible);
                               5926                 : 
 6084 tgl                      5927 ECB             :     /* Add the FROM clause if needed */
 6084 tgl                      5928 CBC        1829 :     get_from_clause(query, " FROM ", context);
                               5929                 : 
 6084 tgl                      5930 ECB             :     /* Add the WHERE clause if given */
 6084 tgl                      5931 GIC        1829 :     if (query->jointree->quals != NULL)
 6084 tgl                      5932 ECB             :     {
 6084 tgl                      5933 CBC         534 :         appendContextKeyword(context, " WHERE ",
                               5934                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
                               5935             534 :         get_rule_expr(query->jointree->quals, context, false);
                               5936                 :     }
                               5937                 : 
                               5938                 :     /* Add the GROUP BY clause if given */
 2885 andres                   5939 GIC        1829 :     if (query->groupClause != NULL || query->groupingSets != NULL)
 6084 tgl                      5940 ECB             :     {
 2878 bruce                    5941                 :         ParseExprKind save_exprkind;
                               5942                 : 
 6084 tgl                      5943 CBC          37 :         appendContextKeyword(context, " GROUP BY ",
                               5944                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
  752 tomas.vondra             5945              37 :         if (query->groupDistinct)
  752 tomas.vondra             5946 LBC           0 :             appendStringInfoString(buf, "DISTINCT ");
 2885 andres                   5947 ECB             : 
 2885 andres                   5948 GIC          37 :         save_exprkind = context->special_exprkind;
                               5949              37 :         context->special_exprkind = EXPR_KIND_GROUP_BY;
                               5950                 : 
 2885 andres                   5951 CBC          37 :         if (query->groupingSets == NIL)
                               5952                 :         {
 2885 andres                   5953 GIC          34 :             sep = "";
                               5954              85 :             foreach(l, query->groupClause)
 2885 andres                   5955 ECB             :             {
 2885 andres                   5956 GIC          51 :                 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
 6084 tgl                      5957 ECB             : 
 2885 andres                   5958 GIC          51 :                 appendStringInfoString(buf, sep);
 2885 andres                   5959 CBC          51 :                 get_rule_sortgroupclause(grp->tleSortGroupRef, query->targetList,
                               5960                 :                                          false, context);
 2885 andres                   5961 GIC          51 :                 sep = ", ";
                               5962                 :             }
 6084 tgl                      5963 ECB             :         }
 2885 andres                   5964                 :         else
                               5965                 :         {
 2885 andres                   5966 GIC           3 :             sep = "";
                               5967               6 :             foreach(l, query->groupingSets)
                               5968                 :             {
                               5969               3 :                 GroupingSet *grp = lfirst(l);
                               5970                 : 
                               5971               3 :                 appendStringInfoString(buf, sep);
                               5972               3 :                 get_rule_groupingset(grp, query->targetList, true, context);
                               5973               3 :                 sep = ", ";
                               5974                 :             }
                               5975                 :         }
 2885 andres                   5976 ECB             : 
 2885 andres                   5977 GIC          37 :         context->special_exprkind = save_exprkind;
                               5978                 :     }
 6084 tgl                      5979 ECB             : 
                               5980                 :     /* Add the HAVING clause if given */
 6084 tgl                      5981 CBC        1829 :     if (query->havingQual != NULL)
                               5982                 :     {
 6084 tgl                      5983 GIC           5 :         appendContextKeyword(context, " HAVING ",
                               5984                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
                               5985               5 :         get_rule_expr(query->havingQual, context, false);
                               5986                 :     }
 5215 tgl                      5987 ECB             : 
                               5988                 :     /* Add the WINDOW clause if needed */
 5215 tgl                      5989 CBC        1829 :     if (query->windowClause != NIL)
                               5990              21 :         get_rule_windowclause(query, context);
 6084 tgl                      5991 ECB             : }
                               5992                 : 
                               5993                 : /* ----------
                               5994                 :  * get_target_list          - Parse back a SELECT target list
                               5995                 :  *
                               5996                 :  * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
  323                          5997                 :  *
                               5998                 :  * resultDesc and colNamesVisible are as for get_query_def()
                               5999                 :  * ----------
 6084                          6000                 :  */
                               6001                 : static void
 6084 tgl                      6002 CBC        1887 : get_target_list(List *targetList, deparse_context *context,
                               6003                 :                 TupleDesc resultDesc, bool colNamesVisible)
                               6004                 : {
 6084 tgl                      6005 GIC        1887 :     StringInfo  buf = context->buf;
                               6006                 :     StringInfoData targetbuf;
 3758                          6007            1887 :     bool        last_was_multiline = false;
 6084 tgl                      6008 ECB             :     char       *sep;
                               6009                 :     int         colno;
                               6010                 :     ListCell   *l;
                               6011                 : 
                               6012                 :     /* we use targetbuf to hold each TLE's text temporarily */
 3758 tgl                      6013 GIC        1887 :     initStringInfo(&targetbuf);
                               6014                 : 
 8994 bruce                    6015            1887 :     sep = " ";
 7549 tgl                      6016            1887 :     colno = 0;
 6084                          6017            8180 :     foreach(l, targetList)
                               6018                 :     {
 8244                          6019            6293 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
                               6020                 :         char       *colname;
 6282 tgl                      6021 ECB             :         char       *attname;
                               6022                 : 
 6577 tgl                      6023 CBC        6293 :         if (tle->resjunk)
 8227 tgl                      6024 GIC          20 :             continue;           /* ignore junk entries */
                               6025                 : 
 6553 neilc                    6026            6273 :         appendStringInfoString(buf, sep);
 8986 bruce                    6027 CBC        6273 :         sep = ", ";
 7549 tgl                      6028 GIC        6273 :         colno++;
                               6029                 : 
                               6030                 :         /*
                               6031                 :          * Put the new field text into targetbuf so we can decide after we've
                               6032                 :          * got it whether or not it needs to go on a new line.
                               6033                 :          */
 3758 tgl                      6034 CBC        6273 :         resetStringInfo(&targetbuf);
 4067 andrew                   6035 GIC        6273 :         context->buf = &targetbuf;
                               6036                 : 
                               6037                 :         /*
                               6038                 :          * We special-case Var nodes rather than using get_rule_expr. This is
                               6039                 :          * needed because get_rule_expr will display a whole-row Var as
                               6040                 :          * "foo.*", which is the preferred notation in most contexts, but at
                               6041                 :          * the top level of a SELECT list it's not right (the parser will
                               6042                 :          * expand that notation into multiple columns, yielding behavior
 3999 tgl                      6043 ECB             :          * different from a whole-row Var).  We need to call get_variable
 2702                          6044                 :          * directly so that we can tell it to do the right thing, and so that
                               6045                 :          * we can get the attribute name which is the default AS label.
 6282                          6046                 :          */
 2885 andres                   6047 GIC        6273 :         if (tle->expr && (IsA(tle->expr, Var)))
                               6048                 :         {
 3999 tgl                      6049 CBC        4813 :             attname = get_variable((Var *) tle->expr, 0, true, context);
                               6050                 :         }
 6282 tgl                      6051 ECB             :         else
                               6052                 :         {
 6282 tgl                      6053 GIC        1460 :             get_rule_expr((Node *) tle->expr, context, true);
                               6054                 : 
                               6055                 :             /*
  323 tgl                      6056 ECB             :              * When colNamesVisible is true, we should always show the
                               6057                 :              * assigned column name explicitly.  Otherwise, show it only if
                               6058                 :              * it's not FigureColname's fallback.
                               6059                 :              */
  323 tgl                      6060 GIC        1460 :             attname = colNamesVisible ? NULL : "?column?";
                               6061                 :         }
                               6062                 : 
                               6063                 :         /*
 3260 bruce                    6064 ECB             :          * Figure out what the result column should be called.  In the context
 6385                          6065                 :          * of a view, use the view's tuple descriptor (so as to pick up the
                               6066                 :          * effects of any column RENAME that's been done on the view).
                               6067                 :          * Otherwise, just use what we can find in the TLE.
                               6068                 :          */
 7549 tgl                      6069 GIC        6273 :         if (resultDesc && colno <= resultDesc->natts)
 2058 andres                   6070 CBC        5681 :             colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname);
                               6071                 :         else
 6577 tgl                      6072 GIC         592 :             colname = tle->resname;
 7549 tgl                      6073 ECB             : 
                               6074                 :         /* Show AS unless the column's name is correct as-is */
 7181 tgl                      6075 GIC        6273 :         if (colname)            /* resname could be NULL */
                               6076                 :         {
 6282                          6077            6248 :             if (attname == NULL || strcmp(attname, colname) != 0)
 4067 andrew                   6078            1941 :                 appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
                               6079                 :         }
 4067 andrew                   6080 ECB             : 
 3758 tgl                      6081                 :         /* Restore context's output buffer */
 4067 andrew                   6082 CBC        6273 :         context->buf = buf;
                               6083                 : 
 3758 tgl                      6084 ECB             :         /* Consider line-wrapping if enabled */
 3758 tgl                      6085 GIC        6273 :         if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
                               6086                 :         {
                               6087                 :             int         leading_nl_pos;
                               6088                 : 
                               6089                 :             /* Does the new field start with a new line? */
 3436                          6090            6251 :             if (targetbuf.len > 0 && targetbuf.data[0] == '\n')
 3436 tgl                      6091 CBC         111 :                 leading_nl_pos = 0;
 3436 tgl                      6092 ECB             :             else
 3436 tgl                      6093 GIC        6140 :                 leading_nl_pos = -1;
 3436 tgl                      6094 ECB             : 
                               6095                 :             /* If so, we shouldn't add anything */
 3436 tgl                      6096 GIC        6251 :             if (leading_nl_pos >= 0)
                               6097                 :             {
                               6098                 :                 /* instead, remove any trailing spaces currently in buf */
 3436 tgl                      6099 CBC         111 :                 removeStringInfoSpaces(buf);
 4067 andrew                   6100 ECB             :             }
                               6101                 :             else
                               6102                 :             {
                               6103                 :                 char       *trailing_nl;
                               6104                 : 
                               6105                 :                 /* Locate the start of the current line in the output buffer */
 3436 tgl                      6106 GIC        6140 :                 trailing_nl = strrchr(buf->data, '\n');
                               6107            6140 :                 if (trailing_nl == NULL)
 3436 tgl                      6108 CBC        2229 :                     trailing_nl = buf->data;
 3436 tgl                      6109 ECB             :                 else
 3436 tgl                      6110 GIC        3911 :                     trailing_nl++;
                               6111                 : 
 3436 tgl                      6112 ECB             :                 /*
                               6113                 :                  * Add a newline, plus some indentation, if the new field is
                               6114                 :                  * not the first and either the new field would cause an
                               6115                 :                  * overflow or the last field used more than one line.
                               6116                 :                  */
 3436 tgl                      6117 GIC        6140 :                 if (colno > 1 &&
                               6118            4283 :                     ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) ||
 3436 tgl                      6119 ECB             :                      last_was_multiline))
 3436 tgl                      6120 CBC        4283 :                     appendContextKeyword(context, "", -PRETTYINDENT_STD,
                               6121                 :                                          PRETTYINDENT_STD, PRETTYINDENT_VAR);
 3436 tgl                      6122 ECB             :             }
                               6123                 : 
 3758                          6124                 :             /* Remember this field's multiline status for next iteration */
 3758 tgl                      6125 CBC        6251 :             last_was_multiline =
                               6126            6251 :                 (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL);
                               6127                 :         }
 4067 andrew                   6128 ECB             : 
                               6129                 :         /* Add the new field */
 1356 drowley                  6130 GIC        6273 :         appendBinaryStringInfo(buf, targetbuf.data, targetbuf.len);
 8994 bruce                    6131 ECB             :     }
 3758 tgl                      6132                 : 
                               6133                 :     /* clean up */
 3758 tgl                      6134 CBC        1887 :     pfree(targetbuf.data);
 8221                          6135            1887 : }
 8221 tgl                      6136 ECB             : 
 8221 tgl                      6137 EUB             : static void
 7549 tgl                      6138 CBC         276 : get_setop_query(Node *setOp, Query *query, deparse_context *context,
                               6139                 :                 TupleDesc resultDesc, bool colNamesVisible)
                               6140                 : {
 8221 tgl                      6141 GIC         276 :     StringInfo  buf = context->buf;
 6851 tgl                      6142 ECB             :     bool        need_paren;
 8221 tgl                      6143 EUB             : 
                               6144                 :     /* Guard against excessively long or deeply-nested queries */
 3266 tgl                      6145 CBC         276 :     CHECK_FOR_INTERRUPTS();
 3266 tgl                      6146 GIC         276 :     check_stack_depth();
 3266 tgl                      6147 ECB             : 
 8221 tgl                      6148 GIC         276 :     if (IsA(setOp, RangeTblRef))
                               6149                 :     {
                               6150             173 :         RangeTblRef *rtr = (RangeTblRef *) setOp;
                               6151             173 :         RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
 8053 bruce                    6152             173 :         Query      *subquery = rte->subquery;
                               6153                 : 
 8221 tgl                      6154             173 :         Assert(subquery != NULL);
 6851                          6155             173 :         Assert(subquery->setOperations == NULL);
                               6156                 :         /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
 5300                          6157             519 :         need_paren = (subquery->cteList ||
                               6158             173 :                       subquery->sortClause ||
 6851                          6159             173 :                       subquery->rowMarks ||
                               6160             519 :                       subquery->limitOffset ||
 6851 tgl                      6161 CBC         173 :                       subquery->limitCount);
 6851 tgl                      6162 GIC         173 :         if (need_paren)
 6851 tgl                      6163 LBC           0 :             appendStringInfoChar(buf, '(');
 7193 tgl                      6164 GIC         173 :         get_query_def(subquery, buf, context->namespaces, resultDesc,
  323 tgl                      6165 ECB             :                       colNamesVisible,
 3758                          6166                 :                       context->prettyFlags, context->wrapColumn,
                               6167                 :                       context->indentLevel);
 6851 tgl                      6168 GBC         173 :         if (need_paren)
 6851 tgl                      6169 UIC           0 :             appendStringInfoChar(buf, ')');
                               6170                 :     }
 8221 tgl                      6171 CBC         103 :     else if (IsA(setOp, SetOperationStmt))
                               6172                 :     {
                               6173             103 :         SetOperationStmt *op = (SetOperationStmt *) setOp;
                               6174                 :         int         subindent;
 5300 tgl                      6175 EUB             : 
 6851                          6176                 :         /*
 3266                          6177                 :          * We force parens when nesting two SetOperationStmts, except when the
                               6178                 :          * lefthand input is another setop of the same kind.  Syntactically,
                               6179                 :          * we could omit parens in rather more cases, but it seems best to use
 3266 tgl                      6180 ECB             :          * parens to flag cases where the setop operator changes.  If we use
                               6181                 :          * parens, we also increase the indentation level for the child query.
                               6182                 :          *
                               6183                 :          * There are some cases in which parens are needed around a leaf query
                               6184                 :          * too, but those are more easily handled at the next level down (see
 3266 tgl                      6185 EUB             :          * code above).
 6851 tgl                      6186 ECB             :          */
 3266 tgl                      6187 CBC         103 :         if (IsA(op->larg, SetOperationStmt))
                               6188                 :         {
 3266 tgl                      6189 GBC          33 :             SetOperationStmt *lop = (SetOperationStmt *) op->larg;
                               6190                 : 
 3266 tgl                      6191 CBC          33 :             if (op->op == lop->op && op->all == lop->all)
 3266 tgl                      6192 GIC          33 :                 need_paren = false;
 3266 tgl                      6193 ECB             :             else
 3266 tgl                      6194 LBC           0 :                 need_paren = true;
 3266 tgl                      6195 ECB             :         }
 3266 tgl                      6196 EUB             :         else
 3266 tgl                      6197 GBC          70 :             need_paren = false;
 8221 tgl                      6198 EUB             : 
 6851 tgl                      6199 GBC         103 :         if (need_paren)
 3266 tgl                      6200 EUB             :         {
 6851 tgl                      6201 UBC           0 :             appendStringInfoChar(buf, '(');
 3266                          6202               0 :             subindent = PRETTYINDENT_STD;
                               6203               0 :             appendContextKeyword(context, "", subindent, 0, 0);
                               6204                 :         }
                               6205                 :         else
 3266 tgl                      6206 CBC         103 :             subindent = 0;
 3266 tgl                      6207 ECB             : 
  323 tgl                      6208 GIC         103 :         get_setop_query(op->larg, query, context, resultDesc, colNamesVisible);
                               6209                 : 
 3266 tgl                      6210 CBC         103 :         if (need_paren)
 3266 tgl                      6211 UIC           0 :             appendContextKeyword(context, ") ", -subindent, 0, 0);
 3266 tgl                      6212 GIC         103 :         else if (PRETTY_INDENT(context))
                               6213             103 :             appendContextKeyword(context, "", -subindent, 0, 0);
                               6214                 :         else
 7188 bruce                    6215 UIC           0 :             appendStringInfoChar(buf, ' ');
                               6216                 : 
 8221 tgl                      6217 CBC         103 :         switch (op->op)
                               6218                 :         {
 8221 tgl                      6219 GBC         103 :             case SETOP_UNION:
 3266                          6220             103 :                 appendStringInfoString(buf, "UNION ");
 8221 tgl                      6221 GIC         103 :                 break;
 8221 tgl                      6222 UIC           0 :             case SETOP_INTERSECT:
 3266 tgl                      6223 LBC           0 :                 appendStringInfoString(buf, "INTERSECT ");
 8221                          6224               0 :                 break;
 8221 tgl                      6225 UIC           0 :             case SETOP_EXCEPT:
 3266 tgl                      6226 LBC           0 :                 appendStringInfoString(buf, "EXCEPT ");
 8221 tgl                      6227 UIC           0 :                 break;
 8221 tgl                      6228 LBC           0 :             default:
 7196                          6229               0 :                 elog(ERROR, "unrecognized set op: %d",
 8221 tgl                      6230 ECB             :                      (int) op->op);
 8221 tgl                      6231 EUB             :         }
 8221 tgl                      6232 GIC         103 :         if (op->all)
 3447 rhaas                    6233              97 :             appendStringInfoString(buf, "ALL ");
                               6234                 : 
 3266 tgl                      6235 EUB             :         /* Always parenthesize if RHS is another setop */
 3266 tgl                      6236 GIC         103 :         need_paren = IsA(op->rarg, SetOperationStmt);
                               6237                 : 
 3266 tgl                      6238 ECB             :         /*
                               6239                 :          * The indentation code here is deliberately a bit different from that
                               6240                 :          * for the lefthand input, because we want the line breaks in
                               6241                 :          * different places.
                               6242                 :          */
 6851 tgl                      6243 GIC         103 :         if (need_paren)
                               6244                 :         {
 6851 tgl                      6245 UIC           0 :             appendStringInfoChar(buf, '(');
 3266 tgl                      6246 LBC           0 :             subindent = PRETTYINDENT_STD;
                               6247                 :         }
                               6248                 :         else
 3266 tgl                      6249 CBC         103 :             subindent = 0;
 3266 tgl                      6250 GIC         103 :         appendContextKeyword(context, "", subindent, 0, 0);
                               6251                 : 
  323                          6252             103 :         get_setop_query(op->rarg, query, context, resultDesc, false);
 5300 tgl                      6253 ECB             : 
 5300 tgl                      6254 CBC         103 :         if (PRETTY_INDENT(context))
 3266 tgl                      6255 GIC         103 :             context->indentLevel -= subindent;
                               6256             103 :         if (need_paren)
 3266 tgl                      6257 UIC           0 :             appendContextKeyword(context, ")", 0, 0, 0);
                               6258                 :     }
                               6259                 :     else
                               6260                 :     {
 7196                          6261               0 :         elog(ERROR, "unrecognized node type: %d",
                               6262                 :              (int) nodeTag(setOp));
                               6263                 :     }
 8221 tgl                      6264 GIC         276 : }
 8221 tgl                      6265 ECB             : 
                               6266                 : /*
 8029 tgl                      6267 EUB             :  * Display a sort/group clause.
 7646                          6268                 :  *
                               6269                 :  * Also returns the expression tree, so caller need not find it again.
 8029 tgl                      6270 ECB             :  */
 7646 tgl                      6271 EUB             : static Node *
 2885 andres                   6272 CBC         216 : get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
 8029 tgl                      6273 ECB             :                          deparse_context *context)
                               6274                 : {
 8029 tgl                      6275 GIC         216 :     StringInfo  buf = context->buf;
                               6276                 :     TargetEntry *tle;
                               6277                 :     Node       *expr;
                               6278                 : 
 2885 andres                   6279             216 :     tle = get_sortgroupref_tle(ref, tlist);
 7423 tgl                      6280             216 :     expr = (Node *) tle->expr;
                               6281                 : 
                               6282                 :     /*
 2878 bruce                    6283 ECB             :      * Use column-number form if requested by caller.  Otherwise, if
                               6284                 :      * expression is a constant, force it to be dumped with an explicit cast
                               6285                 :      * as decoration --- this is because a simple integer constant is
                               6286                 :      * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
                               6287                 :      * dump it without any decoration.  If it's anything more complex than a
                               6288                 :      * simple Var, then force extra parens around it, to ensure it can't be
                               6289                 :      * misinterpreted as a cube() or rollup() construct.
 8029 tgl                      6290                 :      */
 5572 tgl                      6291 CBC         216 :     if (force_colno)
 8029 tgl                      6292 ECB             :     {
 6577 tgl                      6293 LBC           0 :         Assert(!tle->resjunk);
 6577 tgl                      6294 UIC           0 :         appendStringInfo(buf, "%d", tle->resno);
                               6295                 :     }
 5572 tgl                      6296 CBC         216 :     else if (expr && IsA(expr, Const))
 5572 tgl                      6297 UIC           0 :         get_const_expr((Const *) expr, context, 1);
 2885 andres                   6298 GIC         216 :     else if (!expr || IsA(expr, Var))
                               6299             199 :         get_rule_expr(expr, context, true);
                               6300                 :     else
                               6301                 :     {
                               6302                 :         /*
 2885 andres                   6303 ECB             :          * We must force parens for function-like expressions even if
                               6304                 :          * PRETTY_PAREN is off, since those are the ones in danger of
                               6305                 :          * misparsing. For other expressions we need to force them only if
                               6306                 :          * PRETTY_PAREN is on, since otherwise the expression will output them
 2878 bruce                    6307                 :          * itself. (We can't skip the parens.)
 2885 andres                   6308                 :          */
 2878 bruce                    6309 CBC          34 :         bool        need_paren = (PRETTY_PAREN(context)
 2878 bruce                    6310 GIC          17 :                                   || IsA(expr, FuncExpr)
 1058 tgl                      6311 CBC          15 :                                   || IsA(expr, Aggref)
   11 alvherre                 6312 GNC          15 :                                   || IsA(expr, WindowFunc)
                               6313              34 :                                   || IsA(expr, JsonConstructorExpr));
 2878 bruce                    6314 EUB             : 
 2885 andres                   6315 GBC          17 :         if (need_paren)
 2063 peter_e                  6316               2 :             appendStringInfoChar(context->buf, '(');
 7507 tgl                      6317 GIC          17 :         get_rule_expr(expr, context, true);
 2885 andres                   6318 CBC          17 :         if (need_paren)
 2063 peter_e                  6319 GIC           2 :             appendStringInfoChar(context->buf, ')');
 2885 andres                   6320 ECB             :     }
 7646 tgl                      6321                 : 
 7646 tgl                      6322 GIC         216 :     return expr;
 8029 tgl                      6323 ECB             : }
                               6324                 : 
 2885 andres                   6325                 : /*
                               6326                 :  * Display a GroupingSet
                               6327                 :  */
                               6328                 : static void
 2885 andres                   6329 GIC           9 : get_rule_groupingset(GroupingSet *gset, List *targetlist,
 2885 andres                   6330 ECB             :                      bool omit_parens, deparse_context *context)
                               6331                 : {
                               6332                 :     ListCell   *l;
 2885 andres                   6333 CBC           9 :     StringInfo  buf = context->buf;
                               6334               9 :     bool        omit_child_parens = true;
 2885 andres                   6335 GIC           9 :     char       *sep = "";
 2885 andres                   6336 ECB             : 
 2885 andres                   6337 GIC           9 :     switch (gset->kind)
 2885 andres                   6338 ECB             :     {
 2885 andres                   6339 LBC           0 :         case GROUPING_SET_EMPTY:
                               6340               0 :             appendStringInfoString(buf, "()");
 2885 andres                   6341 UBC           0 :             return;
 2885 andres                   6342 EUB             : 
 2885 andres                   6343 GBC           6 :         case GROUPING_SET_SIMPLE:
 2885 andres                   6344 EUB             :             {
 2885 andres                   6345 GBC           6 :                 if (!omit_parens || list_length(gset->content) != 1)
 2063 peter_e                  6346               6 :                     appendStringInfoChar(buf, '(');
 2885 andres                   6347 EUB             : 
 2885 andres                   6348 GIC          21 :                 foreach(l, gset->content)
                               6349                 :                 {
 2878 bruce                    6350 CBC          15 :                     Index       ref = lfirst_int(l);
                               6351                 : 
 2885 andres                   6352              15 :                     appendStringInfoString(buf, sep);
                               6353              15 :                     get_rule_sortgroupclause(ref, targetlist,
 2885 andres                   6354 ECB             :                                              false, context);
 2885 andres                   6355 GIC          15 :                     sep = ", ";
                               6356                 :                 }
 2885 andres                   6357 ECB             : 
 2885 andres                   6358 GIC           6 :                 if (!omit_parens || list_length(gset->content) != 1)
 2063 peter_e                  6359               6 :                     appendStringInfoChar(buf, ')');
                               6360                 :             }
 2885 andres                   6361               6 :             return;
                               6362                 : 
                               6363               3 :         case GROUPING_SET_ROLLUP:
 2885 andres                   6364 CBC           3 :             appendStringInfoString(buf, "ROLLUP(");
 2885 andres                   6365 GIC           3 :             break;
 2885 andres                   6366 UIC           0 :         case GROUPING_SET_CUBE:
 2885 andres                   6367 LBC           0 :             appendStringInfoString(buf, "CUBE(");
 2885 andres                   6368 UIC           0 :             break;
                               6369               0 :         case GROUPING_SET_SETS:
                               6370               0 :             appendStringInfoString(buf, "GROUPING SETS (");
 2885 andres                   6371 LBC           0 :             omit_child_parens = false;
                               6372               0 :             break;
                               6373                 :     }
 2885 andres                   6374 ECB             : 
 2885 andres                   6375 GIC           9 :     foreach(l, gset->content)
                               6376                 :     {
                               6377               6 :         appendStringInfoString(buf, sep);
                               6378               6 :         get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context);
 2885 andres                   6379 CBC           6 :         sep = ", ";
 2885 andres                   6380 ECB             :     }
                               6381                 : 
 2063 peter_e                  6382 CBC           3 :     appendStringInfoChar(buf, ')');
                               6383                 : }
 2885 andres                   6384 ECB             : 
                               6385                 : /*
 5215 tgl                      6386                 :  * Display an ORDER BY list.
                               6387                 :  */
                               6388                 : static void
 5215 tgl                      6389 CBC         134 : get_rule_orderby(List *orderList, List *targetList,
 5215 tgl                      6390 EUB             :                  bool force_colno, deparse_context *context)
                               6391                 : {
 5215 tgl                      6392 CBC         134 :     StringInfo  buf = context->buf;
                               6393                 :     const char *sep;
 5215 tgl                      6394 ECB             :     ListCell   *l;
                               6395                 : 
 5215 tgl                      6396 CBC         134 :     sep = "";
                               6397             284 :     foreach(l, orderList)
                               6398                 :     {
 5215 tgl                      6399 GIC         150 :         SortGroupClause *srt = (SortGroupClause *) lfirst(l);
                               6400                 :         Node       *sortexpr;
 5215 tgl                      6401 ECB             :         Oid         sortcoltype;
                               6402                 :         TypeCacheEntry *typentry;
                               6403                 : 
 5215 tgl                      6404 GIC         150 :         appendStringInfoString(buf, sep);
 2885 andres                   6405             150 :         sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList,
 5215 tgl                      6406 ECB             :                                             force_colno, context);
 5215 tgl                      6407 GBC         150 :         sortcoltype = exprType(sortexpr);
                               6408                 :         /* See whether operator is default < or > for datatype */
 5215 tgl                      6409 CBC         150 :         typentry = lookup_type_cache(sortcoltype,
                               6410                 :                                      TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
                               6411             150 :         if (srt->sortop == typentry->lt_opr)
                               6412                 :         {
 5215 tgl                      6413 ECB             :             /* ASC is default, so emit nothing for it */
 5215 tgl                      6414 GIC         136 :             if (srt->nulls_first)
 3447 rhaas                    6415 UIC           0 :                 appendStringInfoString(buf, " NULLS FIRST");
                               6416                 :         }
 5215 tgl                      6417 GIC          14 :         else if (srt->sortop == typentry->gt_opr)
                               6418                 :         {
 3447 rhaas                    6419               5 :             appendStringInfoString(buf, " DESC");
                               6420                 :             /* DESC defaults to NULLS FIRST */
 5215 tgl                      6421               5 :             if (!srt->nulls_first)
 3447 rhaas                    6422 CBC           1 :                 appendStringInfoString(buf, " NULLS LAST");
                               6423                 :         }
 5215 tgl                      6424 ECB             :         else
                               6425                 :         {
 5215 tgl                      6426 GIC           9 :             appendStringInfo(buf, " USING %s",
                               6427                 :                              generate_operator_name(srt->sortop,
 5215 tgl                      6428 ECB             :                                                     sortcoltype,
                               6429                 :                                                     sortcoltype));
                               6430                 :             /* be specific to eliminate ambiguity */
 5215 tgl                      6431 CBC           9 :             if (srt->nulls_first)
 3447 rhaas                    6432 UIC           0 :                 appendStringInfoString(buf, " NULLS FIRST");
 5215 tgl                      6433 ECB             :             else
 3447 rhaas                    6434 CBC           9 :                 appendStringInfoString(buf, " NULLS LAST");
                               6435                 :         }
 5215 tgl                      6436 GBC         150 :         sep = ", ";
 5215 tgl                      6437 EUB             :     }
 5215 tgl                      6438 GIC         134 : }
                               6439                 : 
 5215 tgl                      6440 EUB             : /*
                               6441                 :  * Display a WINDOW clause.
                               6442                 :  *
                               6443                 :  * Note that the windowClause list might contain only anonymous window
                               6444                 :  * specifications, in which case we should print nothing here.
                               6445                 :  */
                               6446                 : static void
 5215 tgl                      6447 GIC          21 : get_rule_windowclause(Query *query, deparse_context *context)
 5215 tgl                      6448 ECB             : {
 5215 tgl                      6449 GIC          21 :     StringInfo  buf = context->buf;
                               6450                 :     const char *sep;
                               6451                 :     ListCell   *l;
                               6452                 : 
                               6453              21 :     sep = NULL;
 5215 tgl                      6454 CBC          42 :     foreach(l, query->windowClause)
                               6455                 :     {
 5215 tgl                      6456 GIC          21 :         WindowClause *wc = (WindowClause *) lfirst(l);
 5215 tgl                      6457 ECB             : 
 5215 tgl                      6458 CBC          21 :         if (wc->name == NULL)
 5215 tgl                      6459 GIC          21 :             continue;           /* ignore anonymous windows */
                               6460                 : 
 5215 tgl                      6461 UIC           0 :         if (sep == NULL)
 5215 tgl                      6462 LBC           0 :             appendContextKeyword(context, " WINDOW ",
 5215 tgl                      6463 ECB             :                                  -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
                               6464                 :         else
 5215 tgl                      6465 UBC           0 :             appendStringInfoString(buf, sep);
 5215 tgl                      6466 EUB             : 
 5215 tgl                      6467 UIC           0 :         appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
                               6468                 : 
 5215 tgl                      6469 LBC           0 :         get_rule_windowspec(wc, query->targetList, context);
                               6470                 : 
 5215 tgl                      6471 UBC           0 :         sep = ", ";
 5215 tgl                      6472 EUB             :     }
 5215 tgl                      6473 GBC          21 : }
 5215 tgl                      6474 EUB             : 
                               6475                 : /*
                               6476                 :  * Display a window definition
                               6477                 :  */
                               6478                 : static void
 5215 tgl                      6479 GBC          21 : get_rule_windowspec(WindowClause *wc, List *targetList,
 5215 tgl                      6480 EUB             :                     deparse_context *context)
                               6481                 : {
 5215 tgl                      6482 GBC          21 :     StringInfo  buf = context->buf;
 5215 tgl                      6483 GIC          21 :     bool        needspace = false;
 5215 tgl                      6484 EUB             :     const char *sep;
                               6485                 :     ListCell   *l;
                               6486                 : 
 5215 tgl                      6487 CBC          21 :     appendStringInfoChar(buf, '(');
 5215 tgl                      6488 GIC          21 :     if (wc->refname)
 5215 tgl                      6489 ECB             :     {
 5215 tgl                      6490 UBC           0 :         appendStringInfoString(buf, quote_identifier(wc->refname));
 5215 tgl                      6491 LBC           0 :         needspace = true;
 5215 tgl                      6492 ECB             :     }
 5212                          6493                 :     /* partition clauses are always inherited, so only print if no refname */
 5215 tgl                      6494 GIC          21 :     if (wc->partitionClause && !wc->refname)
                               6495                 :     {
 5215 tgl                      6496 LBC           0 :         if (needspace)
 5215 tgl                      6497 UIC           0 :             appendStringInfoChar(buf, ' ');
 5215 tgl                      6498 LBC           0 :         appendStringInfoString(buf, "PARTITION BY ");
                               6499               0 :         sep = "";
                               6500               0 :         foreach(l, wc->partitionClause)
 5215 tgl                      6501 ECB             :         {
 5215 tgl                      6502 LBC           0 :             SortGroupClause *grp = (SortGroupClause *) lfirst(l);
 5215 tgl                      6503 ECB             : 
 5215 tgl                      6504 LBC           0 :             appendStringInfoString(buf, sep);
 2885 andres                   6505               0 :             get_rule_sortgroupclause(grp->tleSortGroupRef, targetList,
                               6506                 :                                      false, context);
 5215 tgl                      6507 UBC           0 :             sep = ", ";
 5215 tgl                      6508 ECB             :         }
 5215 tgl                      6509 LBC           0 :         needspace = true;
 5215 tgl                      6510 ECB             :     }
 5212 tgl                      6511 EUB             :     /* print ordering clause only if not inherited */
 5215 tgl                      6512 CBC          21 :     if (wc->orderClause && !wc->copiedOrder)
 5215 tgl                      6513 EUB             :     {
 5215 tgl                      6514 CBC          21 :         if (needspace)
 5215 tgl                      6515 UIC           0 :             appendStringInfoChar(buf, ' ');
 5215 tgl                      6516 CBC          21 :         appendStringInfoString(buf, "ORDER BY ");
                               6517              21 :         get_rule_orderby(wc->orderClause, targetList, false, context);
                               6518              21 :         needspace = true;
 5215 tgl                      6519 EUB             :     }
 5212                          6520                 :     /* framing clause is never inherited, so print unless it's default */
 5212 tgl                      6521 GIC          21 :     if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
 5212 tgl                      6522 EUB             :     {
 5212 tgl                      6523 GIC          21 :         if (needspace)
                               6524              21 :             appendStringInfoChar(buf, ' ');
 5212 tgl                      6525 GBC          21 :         if (wc->frameOptions & FRAMEOPTION_RANGE)
 5212 tgl                      6526 CBC           3 :             appendStringInfoString(buf, "RANGE ");
 5212 tgl                      6527 GIC          18 :         else if (wc->frameOptions & FRAMEOPTION_ROWS)
 5212 tgl                      6528 CBC          15 :             appendStringInfoString(buf, "ROWS ");
 1887                          6529               3 :         else if (wc->frameOptions & FRAMEOPTION_GROUPS)
 1887 tgl                      6530 GBC           3 :             appendStringInfoString(buf, "GROUPS ");
 5212 tgl                      6531 ECB             :         else
 5212 tgl                      6532 UBC           0 :             Assert(false);
 5212 tgl                      6533 CBC          21 :         if (wc->frameOptions & FRAMEOPTION_BETWEEN)
 5212 tgl                      6534 GIC          21 :             appendStringInfoString(buf, "BETWEEN ");
 5212 tgl                      6535 CBC          21 :         if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
 5212 tgl                      6536 LBC           0 :             appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
 5212 tgl                      6537 GBC          21 :         else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
 5212 tgl                      6538 LBC           0 :             appendStringInfoString(buf, "CURRENT ROW ");
 1887 tgl                      6539 CBC          21 :         else if (wc->frameOptions & FRAMEOPTION_START_OFFSET)
                               6540                 :         {
 4804 tgl                      6541 GBC          21 :             get_rule_expr(wc->startOffset, context, false);
 1887 tgl                      6542 GIC          21 :             if (wc->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
 4804                          6543              21 :                 appendStringInfoString(buf, " PRECEDING ");
 1887 tgl                      6544 UBC           0 :             else if (wc->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
 4804 tgl                      6545 UIC           0 :                 appendStringInfoString(buf, " FOLLOWING ");
 4804 tgl                      6546 ECB             :             else
 4804 tgl                      6547 LBC           0 :                 Assert(false);
 4804 tgl                      6548 ECB             :         }
 5212                          6549                 :         else
 5212 tgl                      6550 LBC           0 :             Assert(false);
 5212 tgl                      6551 CBC          21 :         if (wc->frameOptions & FRAMEOPTION_BETWEEN)
                               6552                 :         {
                               6553              21 :             appendStringInfoString(buf, "AND ");
 5212 tgl                      6554 GIC          21 :             if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
 5212 tgl                      6555 LBC           0 :                 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
 5212 tgl                      6556 CBC          21 :             else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
 5212 tgl                      6557 UIC           0 :                 appendStringInfoString(buf, "CURRENT ROW ");
 1887 tgl                      6558 GIC          21 :             else if (wc->frameOptions & FRAMEOPTION_END_OFFSET)
                               6559                 :             {
 4804                          6560              21 :                 get_rule_expr(wc->endOffset, context, false);
 1887                          6561              21 :                 if (wc->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
 4804 tgl                      6562 UIC           0 :                     appendStringInfoString(buf, " PRECEDING ");
 1887 tgl                      6563 CBC          21 :                 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
 4804 tgl                      6564 GIC          21 :                     appendStringInfoString(buf, " FOLLOWING ");
                               6565                 :                 else
 4804 tgl                      6566 LBC           0 :                     Assert(false);
 4804 tgl                      6567 ECB             :             }
 5212                          6568                 :             else
 5212 tgl                      6569 UIC           0 :                 Assert(false);
                               6570                 :         }
 1887 tgl                      6571 GIC          21 :         if (wc->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
                               6572               3 :             appendStringInfoString(buf, "EXCLUDE CURRENT ROW ");
                               6573              18 :         else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
                               6574               3 :             appendStringInfoString(buf, "EXCLUDE GROUP ");
 1887 tgl                      6575 CBC          15 :         else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
 1887 tgl                      6576 GIC           3 :             appendStringInfoString(buf, "EXCLUDE TIES ");
                               6577                 :         /* we will now have a trailing space; remove it */
 5212                          6578              21 :         buf->len--;
                               6579                 :     }
 5215                          6580              21 :     appendStringInfoChar(buf, ')');
 5215 tgl                      6581 CBC          21 : }
                               6582                 : 
 8994 bruce                    6583 ECB             : /* ----------
                               6584                 :  * get_insert_query_def         - Parse back an INSERT parsetree
                               6585                 :  * ----------
                               6586                 :  */
 8590 tgl                      6587                 : static void
  323 tgl                      6588 GBC         161 : get_insert_query_def(Query *query, deparse_context *context,
  323 tgl                      6589 ECB             :                      bool colNamesVisible)
                               6590                 : {
 8589 tgl                      6591 GIC         161 :     StringInfo  buf = context->buf;
 8221 tgl                      6592 CBC         161 :     RangeTblEntry *select_rte = NULL;
 6094 mail                     6593 GIC         161 :     RangeTblEntry *values_rte = NULL;
 8244 tgl                      6594 ECB             :     RangeTblEntry *rte;
 8221 tgl                      6595 EUB             :     char       *sep;
 6892 neilc                    6596 ECB             :     ListCell   *l;
                               6597                 :     List       *strippedexprs;
                               6598                 : 
 4559 tgl                      6599                 :     /* Insert the WITH clause if given */
 4559 tgl                      6600 GBC         161 :     get_with_clause(query, context);
                               6601                 : 
                               6602                 :     /*
                               6603                 :      * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
                               6604                 :      * single RTE for the SELECT or VALUES.  Plain VALUES has neither.
 8986 bruce                    6605 ECB             :      */
 8986 bruce                    6606 CBC         625 :     foreach(l, query->rtable)
                               6607                 :     {
                               6608             464 :         rte = (RangeTblEntry *) lfirst(l);
                               6609                 : 
 6094 mail                     6610             464 :         if (rte->rtekind == RTE_SUBQUERY)
 6094 mail                     6611 ECB             :         {
 6094 mail                     6612 GIC          22 :             if (select_rte)
 6094 mail                     6613 LBC           0 :                 elog(ERROR, "too many subquery RTEs in INSERT");
 6094 mail                     6614 GIC          22 :             select_rte = rte;
                               6615                 :         }
                               6616                 : 
 6094 mail                     6617 CBC         464 :         if (rte->rtekind == RTE_VALUES)
                               6618                 :         {
 6094 mail                     6619 GIC          19 :             if (values_rte)
 6094 mail                     6620 LBC           0 :                 elog(ERROR, "too many values RTEs in INSERT");
 6094 mail                     6621 GIC          19 :             values_rte = rte;
                               6622                 :         }
                               6623                 :     }
                               6624             161 :     if (select_rte && values_rte)
 6094 mail                     6625 UIC           0 :         elog(ERROR, "both subquery and values RTEs in INSERT");
 8986 bruce                    6626 ECB             : 
 8053                          6627                 :     /*
 8986                          6628                 :      * Start the query with INSERT INTO relname
                               6629                 :      */
 8561 tgl                      6630 CBC         161 :     rte = rt_fetch(query->resultRelation, query->rtable);
 7646 tgl                      6631 GIC         161 :     Assert(rte->rtekind == RTE_RELATION);
 7193 tgl                      6632 ECB             : 
 7193 tgl                      6633 GIC         161 :     if (PRETTY_INDENT(context))
 7193 tgl                      6634 ECB             :     {
 7188 bruce                    6635 GBC         161 :         context->indentLevel += PRETTYINDENT_STD;
 7188 bruce                    6636 GIC         161 :         appendStringInfoChar(buf, ' ');
 7193 tgl                      6637 ECB             :     }
   51 tgl                      6638 CBC         161 :     appendStringInfo(buf, "INSERT INTO %s",
                               6639                 :                      generate_relation_name(rte->relid, NIL));
                               6640                 : 
                               6641                 :     /* Print the relation alias, if needed; INSERT requires explicit AS */
   51 tgl                      6642 GIC         161 :     get_rte_alias(rte, query->resultRelation, true, context);
                               6643                 : 
   51 tgl                      6644 ECB             :     /* always want a space here */
   51 tgl                      6645 CBC         161 :     appendStringInfoChar(buf, ' ');
 8986 bruce                    6646 ECB             : 
                               6647                 :     /*
                               6648                 :      * Add the insert-column-names list.  Any indirection decoration needed on
                               6649                 :      * the column names can be inferred from the top targetlist.
                               6650                 :      */
 6878 tgl                      6651 GIC         161 :     strippedexprs = NIL;
                               6652             161 :     sep = "";
 3824                          6653             161 :     if (query->targetList)
                               6654             161 :         appendStringInfoChar(buf, '(');
 8986 bruce                    6655             594 :     foreach(l, query->targetList)
                               6656                 :     {
 8244 tgl                      6657 CBC         433 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
 8986 bruce                    6658 ECB             : 
 6577 tgl                      6659 GIC         433 :         if (tle->resjunk)
 8227 tgl                      6660 UIC           0 :             continue;           /* ignore junk entries */
 8227 tgl                      6661 ECB             : 
 6553 neilc                    6662 CBC         433 :         appendStringInfoString(buf, sep);
 8986 bruce                    6663 GIC         433 :         sep = ", ";
 6878 tgl                      6664 ECB             : 
                               6665                 :         /*
 6878 tgl                      6666 EUB             :          * Put out name of target column; look in the catalogs, not at
                               6667                 :          * tle->resname, since resname will fail to track RENAME.
                               6668                 :          */
 7008 neilc                    6669 GBC         433 :         appendStringInfoString(buf,
 1882 alvherre                 6670 GIC         433 :                                quote_identifier(get_attname(rte->relid,
                               6671             433 :                                                             tle->resno,
 1882 alvherre                 6672 ECB             :                                                             false)));
                               6673                 : 
                               6674                 :         /*
 6385 bruce                    6675                 :          * Print any indirection needed (subfields or subscripts), and strip
                               6676                 :          * off the top-level nodes representing the indirection assignments.
                               6677                 :          * Add the stripped expressions to strippedexprs.  (If it's a
                               6678                 :          * single-VALUES statement, the stripped expressions are the VALUES to
                               6679                 :          * print below.  Otherwise they're just Vars and not really
 2440 tgl                      6680                 :          * interesting.)
                               6681                 :          */
 2440 tgl                      6682 GIC         433 :         strippedexprs = lappend(strippedexprs,
 2440 tgl                      6683 CBC         433 :                                 processIndirection((Node *) tle->expr,
                               6684                 :                                                    context));
 8986 bruce                    6685 ECB             :     }
 3824 tgl                      6686 GIC         161 :     if (query->targetList)
 3447 rhaas                    6687             161 :         appendStringInfoString(buf, ") ");
 8986 bruce                    6688 ECB             : 
 2194 peter_e                  6689 GIC         161 :     if (query->override)
 2194 peter_e                  6690 ECB             :     {
 2194 peter_e                  6691 LBC           0 :         if (query->override == OVERRIDING_SYSTEM_VALUE)
 2194 peter_e                  6692 UIC           0 :             appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
                               6693               0 :         else if (query->override == OVERRIDING_USER_VALUE)
                               6694               0 :             appendStringInfoString(buf, "OVERRIDING USER VALUE ");
                               6695                 :     }
 2194 peter_e                  6696 EUB             : 
 6094 mail                     6697 GIC         161 :     if (select_rte)
                               6698                 :     {
                               6699                 :         /* Add the SELECT */
  508 tgl                      6700 CBC          22 :         get_query_def(select_rte->subquery, buf, context->namespaces, NULL,
                               6701                 :                       false,
 3758 tgl                      6702 ECB             :                       context->prettyFlags, context->wrapColumn,
                               6703                 :                       context->indentLevel);
 6094 mail                     6704                 :     }
 6094 mail                     6705 GIC         139 :     else if (values_rte)
 6094 mail                     6706 ECB             :     {
                               6707                 :         /* Add the multi-VALUES expression lists */
 6094 mail                     6708 GIC          19 :         get_values_def(values_rte->values_lists, context);
 6094 mail                     6709 ECB             :     }
 3824 tgl                      6710 CBC         120 :     else if (strippedexprs)
 8986 bruce                    6711 ECB             :     {
                               6712                 :         /* Add the single-VALUES expression list */
 7193 tgl                      6713 GIC         120 :         appendContextKeyword(context, "VALUES (",
 7193 tgl                      6714 ECB             :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
  451 tgl                      6715 GIC         120 :         get_rule_list_toplevel(strippedexprs, context, false);
 8449                          6716             120 :         appendStringInfoChar(buf, ')');
                               6717                 :     }
                               6718                 :     else
                               6719                 :     {
                               6720                 :         /* No expressions, so it must be DEFAULT VALUES */
 3447 rhaas                    6721 UIC           0 :         appendStringInfoString(buf, "DEFAULT VALUES");
                               6722                 :     }
 6084 tgl                      6723 ECB             : 
 2893 andres                   6724                 :     /* Add ON CONFLICT if present */
 2893 andres                   6725 GIC         161 :     if (query->onConflict)
 2893 andres                   6726 ECB             :     {
 2893 andres                   6727 GIC          15 :         OnConflictExpr *confl = query->onConflict;
 2893 andres                   6728 ECB             : 
 2838 heikki.linnakangas       6729 GIC          15 :         appendStringInfoString(buf, " ON CONFLICT");
 2882 andres                   6730 ECB             : 
 2882 andres                   6731 GIC          15 :         if (confl->arbiterElems)
                               6732                 :         {
 2882 andres                   6733 ECB             :             /* Add the single-VALUES expression list */
 2882 andres                   6734 GIC          12 :             appendStringInfoChar(buf, '(');
 2882 andres                   6735 GBC          12 :             get_rule_expr((Node *) confl->arbiterElems, context, false);
 2882 andres                   6736 GIC          12 :             appendStringInfoChar(buf, ')');
 2882 andres                   6737 EUB             : 
                               6738                 :             /* Add a WHERE clause (for partial indexes) if given */
 2882 andres                   6739 GIC          12 :             if (confl->arbiterWhere != NULL)
 2882 andres                   6740 EUB             :             {
                               6741                 :                 bool        save_varprefix;
                               6742                 : 
                               6743                 :                 /*
 2618 tgl                      6744 ECB             :                  * Force non-prefixing of Vars, since parser assumes that they
                               6745                 :                  * belong to target relation.  WHERE clause does not use
                               6746                 :                  * InferenceElem, so this is separately required.
                               6747                 :                  */
 2618 tgl                      6748 GIC           6 :                 save_varprefix = context->varprefix;
                               6749               6 :                 context->varprefix = false;
 2618 tgl                      6750 ECB             : 
 2882 andres                   6751 GIC           6 :                 appendContextKeyword(context, " WHERE ",
 2882 andres                   6752 ECB             :                                      -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
 2882 andres                   6753 GIC           6 :                 get_rule_expr(confl->arbiterWhere, context, false);
                               6754                 : 
 2618 tgl                      6755               6 :                 context->varprefix = save_varprefix;
 2882 andres                   6756 ECB             :             }
                               6757                 :         }
 2524 tgl                      6758 CBC           3 :         else if (OidIsValid(confl->constraint))
                               6759                 :         {
 2878 bruce                    6760 LBC           0 :             char       *constraint = get_constraint_name(confl->constraint);
                               6761                 : 
 2524 tgl                      6762 UIC           0 :             if (!constraint)
                               6763               0 :                 elog(ERROR, "cache lookup failed for constraint %u",
                               6764                 :                      confl->constraint);
 2882 andres                   6765               0 :             appendStringInfo(buf, " ON CONSTRAINT %s",
 2524 tgl                      6766 ECB             :                              quote_identifier(constraint));
                               6767                 :         }
 2882 andres                   6768                 : 
 2893 andres                   6769 GIC          15 :         if (confl->action == ONCONFLICT_NOTHING)
 2893 andres                   6770 ECB             :         {
 2882 andres                   6771 GIC           9 :             appendStringInfoString(buf, " DO NOTHING");
 2893 andres                   6772 ECB             :         }
                               6773                 :         else
                               6774                 :         {
 2882 andres                   6775 GIC           6 :             appendStringInfoString(buf, " DO UPDATE SET ");
                               6776                 :             /* Deparse targetlist */
 2893                          6777               6 :             get_update_query_targetlist_def(query, confl->onConflictSet,
                               6778                 :                                             context, rte);
                               6779                 : 
 2893 andres                   6780 ECB             :             /* Add a WHERE clause if given */
 2893 andres                   6781 GIC           6 :             if (confl->onConflictWhere != NULL)
                               6782                 :             {
 2893 andres                   6783 CBC           6 :                 appendContextKeyword(context, " WHERE ",
                               6784                 :                                      -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
 2893 andres                   6785 GIC           6 :                 get_rule_expr(confl->onConflictWhere, context, false);
                               6786                 :             }
 2893 andres                   6787 ECB             :         }
                               6788                 :     }
                               6789                 : 
                               6790                 :     /* Add RETURNING if present */
 6084 tgl                      6791 GIC         161 :     if (query->returningList)
 6084 tgl                      6792 ECB             :     {
 6084 tgl                      6793 CBC          39 :         appendContextKeyword(context, " RETURNING",
 6084 tgl                      6794 ECB             :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
  323 tgl                      6795 GIC          39 :         get_target_list(query->returningList, context, NULL, colNamesVisible);
 6084 tgl                      6796 ECB             :     }
 8994 bruce                    6797 CBC         161 : }
                               6798                 : 
 8994 bruce                    6799 ECB             : 
                               6800                 : /* ----------
                               6801                 :  * get_update_query_def         - Parse back an UPDATE parsetree
                               6802                 :  * ----------
                               6803                 :  */
 8590 tgl                      6804                 : static void
  323 tgl                      6805 GIC          65 : get_update_query_def(Query *query, deparse_context *context,
  323 tgl                      6806 ECB             :                      bool colNamesVisible)
                               6807                 : {
 6797 bruce                    6808 GIC          65 :     StringInfo  buf = context->buf;
 6797 bruce                    6809 ECB             :     RangeTblEntry *rte;
                               6810                 : 
                               6811                 :     /* Insert the WITH clause if given */
 4559 tgl                      6812 CBC          65 :     get_with_clause(query, context);
                               6813                 : 
                               6814                 :     /*
 8986 bruce                    6815 ECB             :      * Start the query with UPDATE relname SET
                               6816                 :      */
 8561 tgl                      6817 CBC          65 :     rte = rt_fetch(query->resultRelation, query->rtable);
 7646 tgl                      6818 GIC          65 :     Assert(rte->rtekind == RTE_RELATION);
 7193 tgl                      6819 CBC          65 :     if (PRETTY_INDENT(context))
                               6820                 :     {
 7188 bruce                    6821 GIC          65 :         appendStringInfoChar(buf, ' ');
                               6822              65 :         context->indentLevel += PRETTYINDENT_STD;
 7193 tgl                      6823 ECB             :     }
 5454 tgl                      6824 GIC         130 :     appendStringInfo(buf, "UPDATE %s%s",
 8338 tgl                      6825 CBC          65 :                      only_marker(rte),
                               6826                 :                      generate_relation_name(rte->relid, NIL));
   51 tgl                      6827 ECB             : 
                               6828                 :     /* Print the relation alias, if needed */
   51 tgl                      6829 CBC          65 :     get_rte_alias(rte, query->resultRelation, false, context);
                               6830                 : 
 5454 tgl                      6831 GIC          65 :     appendStringInfoString(buf, " SET ");
                               6832                 : 
                               6833                 :     /* Deparse targetlist */
 2893 andres                   6834              65 :     get_update_query_targetlist_def(query, query->targetList, context, rte);
                               6835                 : 
                               6836                 :     /* Add the FROM clause if needed */
 2893 andres                   6837 CBC          65 :     get_from_clause(query, " FROM ", context);
                               6838                 : 
                               6839                 :     /* Add a WHERE clause if given */
                               6840              65 :     if (query->jointree->quals != NULL)
                               6841                 :     {
 2893 andres                   6842 GIC          57 :         appendContextKeyword(context, " WHERE ",
                               6843                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
                               6844              57 :         get_rule_expr(query->jointree->quals, context, false);
                               6845                 :     }
                               6846                 : 
                               6847                 :     /* Add RETURNING if present */
                               6848              65 :     if (query->returningList)
                               6849                 :     {
                               6850              11 :         appendContextKeyword(context, " RETURNING",
                               6851                 :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
  323 tgl                      6852              11 :         get_target_list(query->returningList, context, NULL, colNamesVisible);
 2893 andres                   6853 ECB             :     }
 2893 andres                   6854 CBC          65 : }
                               6855                 : 
 2893 andres                   6856 ECB             : 
                               6857                 : /* ----------
                               6858                 :  * get_update_query_targetlist_def          - Parse back an UPDATE targetlist
                               6859                 :  * ----------
                               6860                 :  */
                               6861                 : static void
 2893 andres                   6862 CBC          71 : get_update_query_targetlist_def(Query *query, List *targetList,
                               6863                 :                                 deparse_context *context, RangeTblEntry *rte)
 2893 andres                   6864 ECB             : {
 2893 andres                   6865 GIC          71 :     StringInfo  buf = context->buf;
 2893 andres                   6866 ECB             :     ListCell   *l;
                               6867                 :     ListCell   *next_ma_cell;
                               6868                 :     int         remaining_ma_columns;
                               6869                 :     const char *sep;
                               6870                 :     SubLink    *cur_ma_sublink;
                               6871                 :     List       *ma_sublinks;
                               6872                 : 
 3217 tgl                      6873                 :     /*
                               6874                 :      * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks
                               6875                 :      * into a list.  We expect them to appear, in ID order, in resjunk tlist
                               6876                 :      * entries.
                               6877                 :      */
 3217 tgl                      6878 CBC          71 :     ma_sublinks = NIL;
 3217 tgl                      6879 GIC          71 :     if (query->hasSubLinks)      /* else there can't be any */
 3217 tgl                      6880 ECB             :     {
 2893 andres                   6881 GIC          15 :         foreach(l, targetList)
                               6882                 :         {
 3217 tgl                      6883 CBC          12 :             TargetEntry *tle = (TargetEntry *) lfirst(l);
 3217 tgl                      6884 ECB             : 
 3217 tgl                      6885 GIC          12 :             if (tle->resjunk && IsA(tle->expr, SubLink))
                               6886                 :             {
 3217 tgl                      6887 CBC           3 :                 SubLink    *sl = (SubLink *) tle->expr;
 3217 tgl                      6888 ECB             : 
 3217 tgl                      6889 GIC           3 :                 if (sl->subLinkType == MULTIEXPR_SUBLINK)
                               6890                 :                 {
                               6891               3 :                     ma_sublinks = lappend(ma_sublinks, sl);
                               6892               3 :                     Assert(sl->subLinkId == list_length(ma_sublinks));
                               6893                 :                 }
 3217 tgl                      6894 ECB             :             }
                               6895                 :         }
                               6896                 :     }
 3217 tgl                      6897 GIC          71 :     next_ma_cell = list_head(ma_sublinks);
                               6898              71 :     cur_ma_sublink = NULL;
                               6899              71 :     remaining_ma_columns = 0;
                               6900                 : 
                               6901                 :     /* Add the comma separated list of 'attname = value' */
 8986 bruce                    6902              71 :     sep = "";
 2893 andres                   6903             193 :     foreach(l, targetList)
                               6904                 :     {
 8227 tgl                      6905 CBC         122 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
 6797 bruce                    6906 ECB             :         Node       *expr;
                               6907                 : 
 6577 tgl                      6908 CBC         122 :         if (tle->resjunk)
 8227 tgl                      6909 GIC           3 :             continue;           /* ignore junk entries */
 8986 bruce                    6910 EUB             : 
                               6911                 :         /* Emit separator (OK whether we're in multiassignment or not) */
 6553 neilc                    6912 GBC         119 :         appendStringInfoString(buf, sep);
 8986 bruce                    6913 GIC         119 :         sep = ", ";
 8053 bruce                    6914 ECB             : 
                               6915                 :         /*
 3217 tgl                      6916                 :          * Check to see if we're starting a multiassignment group: if so,
                               6917                 :          * output a left paren.
                               6918                 :          */
 3217 tgl                      6919 GBC         119 :         if (next_ma_cell != NULL && cur_ma_sublink == NULL)
                               6920                 :         {
 3217 tgl                      6921 ECB             :             /*
                               6922                 :              * We must dig down into the expr to see if it's a PARAM_MULTIEXPR
 1528 alvherre                 6923                 :              * Param.  That could be buried under FieldStores and
                               6924                 :              * SubscriptingRefs and CoerceToDomains (cf processIndirection()),
 1528 alvherre                 6925 EUB             :              * and underneath those there could be an implicit type coercion.
                               6926                 :              * Because we would ignore implicit type coercions anyway, we
                               6927                 :              * don't need to be as careful as processIndirection() is about
                               6928                 :              * descending past implicit CoerceToDomains.
 3217 tgl                      6929                 :              */
 3217 tgl                      6930 GIC           3 :             expr = (Node *) tle->expr;
                               6931               6 :             while (expr)
 3217 tgl                      6932 ECB             :             {
 3217 tgl                      6933 GIC           6 :                 if (IsA(expr, FieldStore))
 3217 tgl                      6934 ECB             :                 {
 3217 tgl                      6935 UIC           0 :                     FieldStore *fstore = (FieldStore *) expr;
 3217 tgl                      6936 ECB             : 
 3217 tgl                      6937 LBC           0 :                     expr = (Node *) linitial(fstore->newvals);
                               6938                 :                 }
 1528 alvherre                 6939 CBC           6 :                 else if (IsA(expr, SubscriptingRef))
 3217 tgl                      6940 ECB             :                 {
 1528 alvherre                 6941 CBC           3 :                     SubscriptingRef *sbsref = (SubscriptingRef *) expr;
 3217 tgl                      6942 ECB             : 
 1528 alvherre                 6943 GIC           3 :                     if (sbsref->refassgnexpr == NULL)
 3217 tgl                      6944 LBC           0 :                         break;
                               6945                 : 
 1528 alvherre                 6946 GIC           3 :                     expr = (Node *) sbsref->refassgnexpr;
                               6947                 :                 }
 2097 tgl                      6948               3 :                 else if (IsA(expr, CoerceToDomain))
                               6949                 :                 {
 2097 tgl                      6950 UIC           0 :                     CoerceToDomain *cdomain = (CoerceToDomain *) expr;
                               6951                 : 
 2097 tgl                      6952 LBC           0 :                     if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
                               6953               0 :                         break;
                               6954               0 :                     expr = (Node *) cdomain->arg;
                               6955                 :                 }
                               6956                 :                 else
 3217 tgl                      6957 GIC           3 :                     break;
                               6958                 :             }
                               6959               3 :             expr = strip_implicit_coercions(expr);
                               6960                 : 
 3217 tgl                      6961 CBC           3 :             if (expr && IsA(expr, Param) &&
 3217 tgl                      6962 GIC           3 :                 ((Param *) expr)->paramkind == PARAM_MULTIEXPR)
                               6963                 :             {
                               6964               3 :                 cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
 1364                          6965               3 :                 next_ma_cell = lnext(ma_sublinks, next_ma_cell);
 1165 alvherre                 6966               3 :                 remaining_ma_columns = count_nonjunk_tlist_entries(((Query *) cur_ma_sublink->subselect)->targetList);
 3217 tgl                      6967               3 :                 Assert(((Param *) expr)->paramid ==
 3217 tgl                      6968 ECB             :                        ((cur_ma_sublink->subLinkId << 16) | 1));
 3217 tgl                      6969 GIC           3 :                 appendStringInfoChar(buf, '(');
 3217 tgl                      6970 ECB             :             }
                               6971                 :         }
                               6972                 : 
 8275                          6973                 :         /*
 6878                          6974                 :          * Put out name of target column; look in the catalogs, not at
                               6975                 :          * tle->resname, since resname will fail to track RENAME.
                               6976                 :          */
 6878 tgl                      6977 CBC         119 :         appendStringInfoString(buf,
 1882 alvherre                 6978 GIC         119 :                                quote_identifier(get_attname(rte->relid,
 1882 alvherre                 6979 CBC         119 :                                                             tle->resno,
                               6980                 :                                                             false)));
 6878 tgl                      6981 ECB             : 
                               6982                 :         /*
                               6983                 :          * Print any indirection needed (subfields or subscripts), and strip
                               6984                 :          * off the top-level nodes representing the indirection assignments.
                               6985                 :          */
 2440 tgl                      6986 GIC         119 :         expr = processIndirection((Node *) tle->expr, context);
                               6987                 : 
                               6988                 :         /*
 3217 tgl                      6989 ECB             :          * If we're in a multiassignment, skip printing anything more, unless
                               6990                 :          * this is the last column; in which case, what we print should be the
                               6991                 :          * sublink, not the Param.
                               6992                 :          */
 3217 tgl                      6993 GIC         119 :         if (cur_ma_sublink != NULL)
                               6994                 :         {
                               6995               9 :             if (--remaining_ma_columns > 0)
 3217 tgl                      6996 CBC           6 :                 continue;       /* not the last column of multiassignment */
 3217 tgl                      6997 GIC           3 :             appendStringInfoChar(buf, ')');
                               6998               3 :             expr = (Node *) cur_ma_sublink;
                               6999               3 :             cur_ma_sublink = NULL;
                               7000                 :         }
 3217 tgl                      7001 ECB             : 
 3447 rhaas                    7002 CBC         113 :         appendStringInfoString(buf, " = ");
 6878 tgl                      7003 ECB             : 
 6878 tgl                      7004 GIC         113 :         get_rule_expr(expr, context, false);
 8986 bruce                    7005 ECB             :     }
 8994 bruce                    7006 CBC          71 : }
                               7007                 : 
 8994 bruce                    7008 ECB             : 
                               7009                 : /* ----------
                               7010                 :  * get_delete_query_def         - Parse back a DELETE parsetree
                               7011                 :  * ----------
                               7012                 :  */
 8590 tgl                      7013                 : static void
  323 tgl                      7014 GIC          38 : get_delete_query_def(Query *query, deparse_context *context,
                               7015                 :                      bool colNamesVisible)
 8994 bruce                    7016 ECB             : {
 8589 tgl                      7017 GIC          38 :     StringInfo  buf = context->buf;
                               7018                 :     RangeTblEntry *rte;
 8986 bruce                    7019 ECB             : 
                               7020                 :     /* Insert the WITH clause if given */
 4559 tgl                      7021 CBC          38 :     get_with_clause(query, context);
                               7022                 : 
 8053 bruce                    7023 ECB             :     /*
                               7024                 :      * Start the query with DELETE FROM relname
                               7025                 :      */
 8561 tgl                      7026 GIC          38 :     rte = rt_fetch(query->resultRelation, query->rtable);
 7646 tgl                      7027 CBC          38 :     Assert(rte->rtekind == RTE_RELATION);
 7193 tgl                      7028 GIC          38 :     if (PRETTY_INDENT(context))
 7193 tgl                      7029 ECB             :     {
 7188 bruce                    7030 GIC          38 :         appendStringInfoChar(buf, ' ');
 5454 tgl                      7031 CBC          38 :         context->indentLevel += PRETTYINDENT_STD;
                               7032                 :     }
 8561                          7033              76 :     appendStringInfo(buf, "DELETE FROM %s%s",
 8338 tgl                      7034 GIC          38 :                      only_marker(rte),
                               7035                 :                      generate_relation_name(rte->relid, NIL));
                               7036                 : 
                               7037                 :     /* Print the relation alias, if needed */
   51                          7038              38 :     get_rte_alias(rte, query->resultRelation, false, context);
                               7039                 : 
                               7040                 :     /* Add the USING clause if given */
 6460 tgl                      7041 CBC          38 :     get_from_clause(query, " USING ", context);
                               7042                 : 
 8986 bruce                    7043 ECB             :     /* Add a WHERE clause if given */
 8227 tgl                      7044 GIC          38 :     if (query->jointree->quals != NULL)
 8986 bruce                    7045 ECB             :     {
 7193 tgl                      7046 CBC          38 :         appendContextKeyword(context, " WHERE ",
 7193 tgl                      7047 ECB             :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
 7507 tgl                      7048 GIC          38 :         get_rule_expr(query->jointree->quals, context, false);
 8986 bruce                    7049 ECB             :     }
                               7050                 : 
 6084 tgl                      7051                 :     /* Add RETURNING if present */
 6084 tgl                      7052 CBC          38 :     if (query->returningList)
 6084 tgl                      7053 ECB             :     {
 6084 tgl                      7054 GIC           8 :         appendContextKeyword(context, " RETURNING",
 6084 tgl                      7055 EUB             :                              -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
  323 tgl                      7056 GBC           8 :         get_target_list(query->returningList, context, NULL, colNamesVisible);
                               7057                 :     }
 8994 bruce                    7058 GIC          38 : }
                               7059                 : 
                               7060                 : 
                               7061                 : /* ----------
 8131 tgl                      7062 EUB             :  * get_utility_query_def            - Parse back a UTILITY parsetree
                               7063                 :  * ----------
 8131 tgl                      7064 ECB             :  */
                               7065                 : static void
 8131 tgl                      7066 GIC           8 : get_utility_query_def(Query *query, deparse_context *context)
                               7067                 : {
                               7068               8 :     StringInfo  buf = context->buf;
                               7069                 : 
                               7070               8 :     if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
                               7071               8 :     {
                               7072               8 :         NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
                               7073                 : 
 7193                          7074               8 :         appendContextKeyword(context, "",
                               7075                 :                              0, PRETTYINDENT_STD, 1);
 7688                          7076               8 :         appendStringInfo(buf, "NOTIFY %s",
 5333                          7077               8 :                          quote_identifier(stmt->conditionname));
 4800                          7078               8 :         if (stmt->payload)
                               7079                 :         {
 4800 tgl                      7080 UIC           0 :             appendStringInfoString(buf, ", ");
                               7081               0 :             simple_quote_literal(buf, stmt->payload);
                               7082                 :         }
                               7083                 :     }
                               7084                 :     else
                               7085                 :     {
 7196 tgl                      7086 ECB             :         /* Currently only NOTIFY utility commands can appear in rules */
 7196 tgl                      7087 UIC           0 :         elog(ERROR, "unexpected utility statement type");
 7196 tgl                      7088 ECB             :     }
 8131 tgl                      7089 GIC           8 : }
                               7090                 : 
                               7091                 : /*
                               7092                 :  * Display a Var appropriately.
                               7093                 :  *
                               7094                 :  * In some cases (currently only when recursing into an unnamed join)
                               7095                 :  * the Var's varlevelsup has to be interpreted with respect to a context
                               7096                 :  * above the current one; levelsup indicates the offset.
                               7097                 :  *
                               7098                 :  * If istoplevel is true, the Var is at the top level of a SELECT's
                               7099                 :  * targetlist, which means we need special treatment of whole-row Vars.
 3999 tgl                      7100 ECB             :  * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a
                               7101                 :  * dirty hack to prevent "tab.*" from being expanded into multiple columns.
 3999 tgl                      7102 EUB             :  * (The parser will strip the useless coercion, so no inefficiency is added in
                               7103                 :  * dump and reload.)  We used to print just "tab" in such cases, but that is
 3999 tgl                      7104 ECB             :  * ambiguous and will yield the wrong result if "tab" is also a plain column
                               7105                 :  * name in the query.
                               7106                 :  *
                               7107                 :  * Returns the attname of the Var, or NULL if the Var has no attname (because
                               7108                 :  * it is a whole-row Var or a subplan output reference).
                               7109                 :  */
                               7110                 : static char *
 3999 tgl                      7111 GIC       64306 : get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
                               7112                 : {
 5889                          7113           64306 :     StringInfo  buf = context->buf;
                               7114                 :     RangeTblEntry *rte;
 5889 tgl                      7115 ECB             :     AttrNumber  attnum;
                               7116                 :     int         netlevelsup;
 8089                          7117                 :     deparse_namespace *dpns;
  571                          7118                 :     int         varno;
                               7119                 :     AttrNumber  varattno;
                               7120                 :     deparse_columns *colinfo;
                               7121                 :     char       *refname;
 5889                          7122                 :     char       *attname;
 6210                          7123                 : 
                               7124                 :     /* Find appropriate nesting depth */
 6660 tgl                      7125 GIC       64306 :     netlevelsup = var->varlevelsup + levelsup;
                               7126           64306 :     if (netlevelsup >= list_length(context->namespaces))
 6660 tgl                      7127 UIC           0 :         elog(ERROR, "bogus varlevelsup: %d offset %d",
                               7128                 :              var->varlevelsup, levelsup);
 6892 tgl                      7129 GIC       64306 :     dpns = (deparse_namespace *) list_nth(context->namespaces,
                               7130                 :                                           netlevelsup);
                               7131                 : 
 1186 tgl                      7132 ECB             :     /*
                               7133                 :      * If we have a syntactic referent for the Var, and we're working from a
                               7134                 :      * parse tree, prefer to use the syntactic referent.  Otherwise, fall back
                               7135                 :      * on the semantic referent.  (Forcing use of the semantic referent when
                               7136                 :      * printing plan trees is a design choice that's perhaps more motivated by
                               7137                 :      * backwards compatibility than anything else.  But it does have the
                               7138                 :      * advantage of making plans more explicit.)
                               7139                 :      */
 1186 tgl                      7140 CBC       64306 :     if (var->varnosyn > 0 && dpns->plan == NULL)
 1186 tgl                      7141 ECB             :     {
 1186 tgl                      7142 CBC       12577 :         varno = var->varnosyn;
 1186 tgl                      7143 GIC       12577 :         varattno = var->varattnosyn;
                               7144                 :     }
 1186 tgl                      7145 ECB             :     else
                               7146                 :     {
 1186 tgl                      7147 CBC       51729 :         varno = var->varno;
 1186 tgl                      7148 GIC       51729 :         varattno = var->varattno;
 1186 tgl                      7149 ECB             :     }
                               7150                 : 
                               7151                 :     /*
 6210                          7152                 :      * Try to find the relevant RTE in this rtable.  In a plan tree, it's
 4198 tgl                      7153 EUB             :      * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
 3751 tgl                      7154 ECB             :      * down into the subplans, or INDEX_VAR, which is resolved similarly. Also
                               7155                 :      * find the aliases previously assigned for this RTE.
 6210 tgl                      7156 EUB             :      */
 1186 tgl                      7157 GIC       64306 :     if (varno >= 1 && varno <= list_length(dpns->rtable))
                               7158                 :     {
 1215 tgl                      7159 ECB             :         /*
                               7160                 :          * We might have been asked to map child Vars to some parent relation.
                               7161                 :          */
 1215 tgl                      7162 GIC       48323 :         if (context->appendparents && dpns->appendrels)
 1215 tgl                      7163 ECB             :         {
  571 tgl                      7164 CBC        1741 :             int         pvarno = varno;
 1215 tgl                      7165 GIC        1741 :             AttrNumber  pvarattno = varattno;
                               7166            1741 :             AppendRelInfo *appinfo = dpns->appendrels[pvarno];
                               7167            1741 :             bool        found = false;
                               7168                 : 
                               7169                 :             /* Only map up to inheritance parents, not UNION ALL appendrels */
                               7170            3539 :             while (appinfo &&
 1215 tgl                      7171 CBC        1935 :                    rt_fetch(appinfo->parent_relid,
 1215 tgl                      7172 GIC        1935 :                             dpns->rtable)->rtekind == RTE_RELATION)
 1215 tgl                      7173 ECB             :             {
 1215 tgl                      7174 CBC        1798 :                 found = false;
 1215 tgl                      7175 GIC        1798 :                 if (pvarattno > 0)   /* system columns stay as-is */
                               7176                 :                 {
                               7177            1661 :                     if (pvarattno > appinfo->num_child_cols)
 1215 tgl                      7178 LBC           0 :                         break;  /* safety check */
 1215 tgl                      7179 CBC        1661 :                     pvarattno = appinfo->parent_colnos[pvarattno - 1];
                               7180            1661 :                     if (pvarattno == 0)
 1215 tgl                      7181 LBC           0 :                         break;  /* Var is local to child */
                               7182                 :                 }
                               7183                 : 
 1215 tgl                      7184 GIC        1798 :                 pvarno = appinfo->parent_relid;
 1215 tgl                      7185 CBC        1798 :                 found = true;
                               7186                 : 
 1215 tgl                      7187 ECB             :                 /* If the parent is itself a child, continue up. */
 1215 tgl                      7188 GIC        1798 :                 Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable));
                               7189            1798 :                 appinfo = dpns->appendrels[pvarno];
                               7190                 :             }
                               7191                 : 
                               7192                 :             /*
                               7193                 :              * If we found an ancestral rel, and that rel is included in
                               7194                 :              * appendparents, print that column not the original one.
                               7195                 :              */
                               7196            1741 :             if (found && bms_is_member(pvarno, context->appendparents))
                               7197                 :             {
                               7198            1439 :                 varno = pvarno;
                               7199            1439 :                 varattno = pvarattno;
                               7200                 :             }
 1215 tgl                      7201 ECB             :         }
                               7202                 : 
 1215 tgl                      7203 CBC       48323 :         rte = rt_fetch(varno, dpns->rtable);
 1215 tgl                      7204 GIC       48323 :         refname = (char *) list_nth(dpns->rtable_names, varno - 1);
                               7205           48323 :         colinfo = deparse_columns_fetch(varno, dpns);
                               7206           48323 :         attnum = varattno;
                               7207                 :     }
 5889 tgl                      7208 ECB             :     else
                               7209                 :     {
 1215 tgl                      7210 GBC       15983 :         resolve_special_varno((Node *) var, context,
                               7211                 :                               get_special_variable, NULL);
 2538 rhaas                    7212 GIC       15983 :         return NULL;
 5889 tgl                      7213 ECB             :     }
                               7214                 : 
                               7215                 :     /*
                               7216                 :      * The planner will sometimes emit Vars referencing resjunk elements of a
                               7217                 :      * subquery's target list (this is currently only possible if it chooses
                               7218                 :      * to generate a "physical tlist" for a SubqueryScan or CteScan node).
                               7219                 :      * Although we prefer to print subquery-referencing Vars using the
 4657                          7220                 :      * subquery's alias, that's not possible for resjunk items since they have
 4657 tgl                      7221 EUB             :      * no alias.  So in that case, drill down to the subplan and print the
 4657 tgl                      7222 ECB             :      * contents of the referenced tlist item.  This works because in a plan
 4382 bruce                    7223                 :      * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
 1215 tgl                      7224 EUB             :      * we'll have set dpns->inner_plan to reference the child plan node.
                               7225                 :      */
 4657 tgl                      7226 CBC       49913 :     if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
                               7227            1590 :         attnum > list_length(rte->eref->colnames) &&
 1215 tgl                      7228 GIC           1 :         dpns->inner_plan)
                               7229                 :     {
                               7230                 :         TargetEntry *tle;
                               7231                 :         deparse_namespace save_dpns;
                               7232                 : 
                               7233               1 :         tle = get_tle_by_resno(dpns->inner_tlist, attnum);
 4657                          7234               1 :         if (!tle)
 2473 tgl                      7235 UIC           0 :             elog(ERROR, "invalid attnum %d for relation \"%s\"",
                               7236                 :                  attnum, rte->eref->aliasname);
                               7237                 : 
 4657 tgl                      7238 GIC           1 :         Assert(netlevelsup == 0);
 1215                          7239               1 :         push_child_plan(dpns, dpns->inner_plan, &save_dpns);
                               7240                 : 
                               7241                 :         /*
 4657 tgl                      7242 ECB             :          * Force parentheses because our caller probably assumed a Var is a
                               7243                 :          * simple expression.
                               7244                 :          */
 4657 tgl                      7245 GBC           1 :         if (!IsA(tle->expr, Var))
 4657 tgl                      7246 LBC           0 :             appendStringInfoChar(buf, '(');
 4657 tgl                      7247 GIC           1 :         get_rule_expr((Node *) tle->expr, context, true);
                               7248               1 :         if (!IsA(tle->expr, Var))
 4657 tgl                      7249 UIC           0 :             appendStringInfoChar(buf, ')');
 4657 tgl                      7250 ECB             : 
 4653 tgl                      7251 GIC           1 :         pop_child_plan(dpns, &save_dpns);
 4657 tgl                      7252 CBC           1 :         return NULL;
                               7253                 :     }
 4657 tgl                      7254 EUB             : 
                               7255                 :     /*
                               7256                 :      * If it's an unnamed join, look at the expansion of the alias variable.
                               7257                 :      * If it's a simple reference to one of the input vars, then recursively
                               7258                 :      * print the name of that var instead.  When it's not a simple reference,
                               7259                 :      * we have to just print the unqualified join column name.  (This can only
                               7260                 :      * happen with "dangerous" merged columns in a JOIN USING; we took pains
                               7261                 :      * previously to make the unqualified column name unique in such cases.)
                               7262                 :      *
                               7263                 :      * This wouldn't work in decompiling plan trees, because we don't store
 3852 tgl                      7264 ECB             :      * joinaliasvars lists after planning; but a plan tree should never
                               7265                 :      * contain a join alias variable.
                               7266                 :      */
 3852 tgl                      7267 CBC       48322 :     if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
 7549 tgl                      7268 ECB             :     {
 3852 tgl                      7269 CBC          48 :         if (rte->joinaliasvars == NIL)
 3852 tgl                      7270 UIC           0 :             elog(ERROR, "cannot decompile join alias var in plan tree");
 3852 tgl                      7271 GIC          48 :         if (attnum > 0)
 7549 tgl                      7272 ECB             :         {
 3852 tgl                      7273 EUB             :             Var        *aliasvar;
                               7274                 : 
 3852 tgl                      7275 CBC          48 :             aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
                               7276                 :             /* we intentionally don't strip implicit coercions here */
 3547 tgl                      7277 GIC          48 :             if (aliasvar && IsA(aliasvar, Var))
                               7278                 :             {
 3852 tgl                      7279 UIC           0 :                 return get_variable(aliasvar, var->varlevelsup + levelsup,
                               7280                 :                                     istoplevel, context);
                               7281                 :             }
                               7282                 :         }
                               7283                 : 
 3852 tgl                      7284 ECB             :         /*
                               7285                 :          * Unnamed join has no refname.  (Note: since it's unnamed, there is
                               7286                 :          * no way the user could have referenced it to create a whole-row Var
                               7287                 :          * for it.  So we don't have to cover that case below.)
                               7288                 :          */
 3852 tgl                      7289 GIC          48 :         Assert(refname == NULL);
 7549 tgl                      7290 ECB             :     }
                               7291                 : 
 6210 tgl                      7292 GIC       48322 :     if (attnum == InvalidAttrNumber)
 5889 tgl                      7293 CBC         379 :         attname = NULL;
 3751 tgl                      7294 GIC       47943 :     else if (attnum > 0)
 3751 tgl                      7295 ECB             :     {
                               7296                 :         /* Get column name to use from the colinfo struct */
 2473 tgl                      7297 GIC       47342 :         if (attnum > colinfo->num_cols)
 2473 tgl                      7298 LBC           0 :             elog(ERROR, "invalid attnum %d for relation \"%s\"",
 2473 tgl                      7299 ECB             :                  attnum, rte->eref->aliasname);
 3751 tgl                      7300 GIC       47342 :         attname = colinfo->colnames[attnum - 1];
                               7301                 : 
  262 tgl                      7302 ECB             :         /*
                               7303                 :          * If we find a Var referencing a dropped column, it seems better to
                               7304                 :          * print something (anything) than to fail.  In general this should
                               7305                 :          * not happen, but it used to be possible for some cases involving
                               7306                 :          * functions returning named composite types, and perhaps there are
                               7307                 :          * still bugs out there.
                               7308                 :          */
  262 tgl                      7309 CBC       47342 :         if (attname == NULL)
  262 tgl                      7310 GIC           3 :             attname = "?dropped?column?";
                               7311                 :     }
                               7312                 :     else
                               7313                 :     {
                               7314                 :         /* System column - name is fixed, get it from the catalog */
 5889                          7315             601 :         attname = get_rte_attribute_name(rte, attnum);
                               7316                 :     }
                               7317                 : 
                               7318           48322 :     if (refname && (context->varprefix || attname == NULL))
                               7319                 :     {
 4903 tgl                      7320 CBC       22198 :         appendStringInfoString(buf, quote_identifier(refname));
 3999 tgl                      7321 GIC       22198 :         appendStringInfoChar(buf, '.');
 5889 tgl                      7322 ECB             :     }
 5889 tgl                      7323 GIC       48322 :     if (attname)
                               7324           47943 :         appendStringInfoString(buf, quote_identifier(attname));
                               7325                 :     else
                               7326                 :     {
                               7327             379 :         appendStringInfoChar(buf, '*');
 3999 tgl                      7328 CBC         379 :         if (istoplevel)
                               7329              36 :             appendStringInfo(buf, "::%s",
 3999 tgl                      7330 ECB             :                              format_type_with_typemod(var->vartype,
                               7331                 :                                                       var->vartypmod));
                               7332                 :     }
 5889                          7333                 : 
 5889 tgl                      7334 GIC       48322 :     return attname;
                               7335                 : }
                               7336                 : 
                               7337                 : /*
                               7338                 :  * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR.  This
                               7339                 :  * routine is actually a callback for resolve_special_varno, which handles
                               7340                 :  * finding the correct TargetEntry.  We get the expression contained in that
 2538 rhaas                    7341 ECB             :  * TargetEntry and just need to deparse it, a job we can throw back on
                               7342                 :  * get_rule_expr.
                               7343                 :  */
                               7344                 : static void
 1215 tgl                      7345 GIC       15983 : get_special_variable(Node *node, deparse_context *context, void *callback_arg)
                               7346                 : {
 2538 rhaas                    7347           15983 :     StringInfo  buf = context->buf;
 2538 rhaas                    7348 ECB             : 
                               7349                 :     /*
                               7350                 :      * For a non-Var referent, force parentheses because our caller probably
 1215 tgl                      7351                 :      * assumed a Var is a simple expression.
                               7352                 :      */
 2538 rhaas                    7353 CBC       15983 :     if (!IsA(node, Var))
                               7354            1506 :         appendStringInfoChar(buf, '(');
 2538 rhaas                    7355 GIC       15983 :     get_rule_expr(node, context, true);
                               7356           15983 :     if (!IsA(node, Var))
                               7357            1506 :         appendStringInfoChar(buf, ')');
 2538 rhaas                    7358 CBC       15983 : }
 2538 rhaas                    7359 ECB             : 
                               7360                 : /*
                               7361                 :  * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR,
                               7362                 :  * INDEX_VAR) until we find a real Var or some kind of non-Var node; then,
                               7363                 :  * invoke the callback provided.
                               7364                 :  */
                               7365                 : static void
 1215 tgl                      7366 CBC       44201 : resolve_special_varno(Node *node, deparse_context *context,
                               7367                 :                       rsv_callback callback, void *callback_arg)
                               7368                 : {
                               7369                 :     Var        *var;
                               7370                 :     deparse_namespace *dpns;
                               7371                 : 
 1215 tgl                      7372 ECB             :     /* This function is recursive, so let's be paranoid. */
 1215 tgl                      7373 CBC       44201 :     check_stack_depth();
 1215 tgl                      7374 EUB             : 
                               7375                 :     /* If it's not a Var, invoke the callback. */
 2538 rhaas                    7376 GIC       44201 :     if (!IsA(node, Var))
                               7377                 :     {
 1215 tgl                      7378            1636 :         (*callback) (node, context, callback_arg);
 2538 rhaas                    7379            1636 :         return;
                               7380                 :     }
 2538 rhaas                    7381 ECB             : 
                               7382                 :     /* Find appropriate nesting depth */
 2538 rhaas                    7383 CBC       42565 :     var = (Var *) node;
                               7384           42565 :     dpns = (deparse_namespace *) list_nth(context->namespaces,
                               7385           42565 :                                           var->varlevelsup);
 2538 rhaas                    7386 ECB             : 
                               7387                 :     /*
 1186 tgl                      7388                 :      * If varno is special, recurse.  (Don't worry about varnosyn; if we're
                               7389                 :      * here, we already decided not to use that.)
 2538 rhaas                    7390                 :      */
 2538 rhaas                    7391 CBC       42565 :     if (var->varno == OUTER_VAR && dpns->outer_tlist)
                               7392                 :     {
 2538 rhaas                    7393 ECB             :         TargetEntry *tle;
                               7394                 :         deparse_namespace save_dpns;
 1215 tgl                      7395                 :         Bitmapset  *save_appendparents;
                               7396                 : 
 2538 rhaas                    7397 CBC       21079 :         tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
 2538 rhaas                    7398 GIC       21079 :         if (!tle)
 2538 rhaas                    7399 UIC           0 :             elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
                               7400                 : 
                               7401                 :         /*
 1215 tgl                      7402 ECB             :          * If we're descending to the first child of an Append or MergeAppend,
                               7403                 :          * update appendparents.  This will affect deparsing of all Vars
 1215 tgl                      7404 EUB             :          * appearing within the eventually-resolved subexpression.
                               7405                 :          */
 1215 tgl                      7406 CBC       21079 :         save_appendparents = context->appendparents;
 1215 tgl                      7407 ECB             : 
 1215 tgl                      7408 GIC       21079 :         if (IsA(dpns->plan, Append))
 1215 tgl                      7409 CBC        1948 :             context->appendparents = bms_union(context->appendparents,
                               7410            1948 :                                                ((Append *) dpns->plan)->apprelids);
 1215 tgl                      7411 GIC       19131 :         else if (IsA(dpns->plan, MergeAppend))
 1215 tgl                      7412 CBC         243 :             context->appendparents = bms_union(context->appendparents,
 1215 tgl                      7413 GIC         243 :                                                ((MergeAppend *) dpns->plan)->apprelids);
                               7414                 : 
                               7415           21079 :         push_child_plan(dpns, dpns->outer_plan, &save_dpns);
 1215 tgl                      7416 CBC       21079 :         resolve_special_varno((Node *) tle->expr, context,
 1215 tgl                      7417 ECB             :                               callback, callback_arg);
 2538 rhaas                    7418 GBC       21079 :         pop_child_plan(dpns, &save_dpns);
 1215 tgl                      7419 GIC       21079 :         context->appendparents = save_appendparents;
 2538 rhaas                    7420 CBC       21079 :         return;
                               7421                 :     }
                               7422           21486 :     else if (var->varno == INNER_VAR && dpns->inner_tlist)
                               7423                 :     {
 2538 rhaas                    7424 ECB             :         TargetEntry *tle;
 2538 rhaas                    7425 EUB             :         deparse_namespace save_dpns;
                               7426                 : 
 2538 rhaas                    7427 GIC        5083 :         tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
 2538 rhaas                    7428 CBC        5083 :         if (!tle)
 2538 rhaas                    7429 UIC           0 :             elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
                               7430                 : 
 1215 tgl                      7431 GIC        5083 :         push_child_plan(dpns, dpns->inner_plan, &save_dpns);
                               7432            5083 :         resolve_special_varno((Node *) tle->expr, context,
                               7433                 :                               callback, callback_arg);
 2538 rhaas                    7434            5083 :         pop_child_plan(dpns, &save_dpns);
                               7435            5083 :         return;
                               7436                 :     }
                               7437           16403 :     else if (var->varno == INDEX_VAR && dpns->index_tlist)
                               7438                 :     {
                               7439                 :         TargetEntry *tle;
                               7440                 : 
                               7441            1926 :         tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
                               7442            1926 :         if (!tle)
 2538 rhaas                    7443 UIC           0 :             elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
                               7444                 : 
 1215 tgl                      7445 GIC        1926 :         resolve_special_varno((Node *) tle->expr, context,
                               7446                 :                               callback, callback_arg);
 2538 rhaas                    7447            1926 :         return;
                               7448                 :     }
 2538 rhaas                    7449 CBC       14477 :     else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
 2538 rhaas                    7450 UIC           0 :         elog(ERROR, "bogus varno: %d", var->varno);
                               7451                 : 
                               7452                 :     /* Not special.  Just invoke the callback. */
 1215 tgl                      7453 GIC       14477 :     (*callback) (node, context, callback_arg);
                               7454                 : }
                               7455                 : 
                               7456                 : /*
                               7457                 :  * Get the name of a field of an expression of composite type.  The
                               7458                 :  * expression is usually a Var, but we handle other cases too.
                               7459                 :  *
                               7460                 :  * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
                               7461                 :  *
                               7462                 :  * This is fairly straightforward when the expression has a named composite
                               7463                 :  * type; we need only look up the type in the catalogs.  However, the type
                               7464                 :  * could also be RECORD.  Since no actual table or view column is allowed to
                               7465                 :  * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
 4232 tgl                      7466 ECB             :  * or to a subquery output.  We drill down to find the ultimate defining
                               7467                 :  * expression and attempt to infer the field name from it.  We ereport if we
                               7468                 :  * can't determine the name.
                               7469                 :  *
                               7470                 :  * Similarly, a PARAM of type RECORD has to refer to some expression of
                               7471                 :  * a determinable composite type.
                               7472                 :  */
                               7473                 : static const char *
 6522 tgl                      7474 GIC         376 : get_name_for_var_field(Var *var, int fieldno,
                               7475                 :                        int levelsup, deparse_context *context)
                               7476                 : {
 6522 tgl                      7477 ECB             :     RangeTblEntry *rte;
                               7478                 :     AttrNumber  attnum;
 5889                          7479                 :     int         netlevelsup;
                               7480                 :     deparse_namespace *dpns;
                               7481                 :     int         varno;
 1186                          7482                 :     AttrNumber  varattno;
 6522                          7483                 :     TupleDesc   tupleDesc;
                               7484                 :     Node       *expr;
                               7485                 : 
                               7486                 :     /*
                               7487                 :      * If it's a RowExpr that was expanded from a whole-row Var, use the
                               7488                 :      * column names attached to it.  (We could let get_expr_result_tupdesc()
  175                          7489                 :      * handle this, but it's much cheaper to just pull out the name we need.)
 5298                          7490                 :      */
 5298 tgl                      7491 GIC         376 :     if (IsA(var, RowExpr))
 5298 tgl                      7492 ECB             :     {
 5050 bruce                    7493 CBC          18 :         RowExpr    *r = (RowExpr *) var;
                               7494                 : 
 5298 tgl                      7495 GIC          18 :         if (fieldno > 0 && fieldno <= list_length(r->colnames))
                               7496              18 :             return strVal(list_nth(r->colnames, fieldno - 1));
                               7497                 :     }
                               7498                 : 
                               7499                 :     /*
                               7500                 :      * If it's a Param of type RECORD, try to find what the Param refers to.
 4232 tgl                      7501 ECB             :      */
 4232 tgl                      7502 CBC         358 :     if (IsA(var, Param))
                               7503                 :     {
                               7504               6 :         Param      *param = (Param *) var;
                               7505                 :         ListCell   *ancestor_cell;
 4232 tgl                      7506 ECB             : 
 4232 tgl                      7507 CBC           6 :         expr = find_param_referent(param, context, &dpns, &ancestor_cell);
 4232 tgl                      7508 GIC           6 :         if (expr)
                               7509                 :         {
                               7510                 :             /* Found a match, so recurse to decipher the field name */
 4232 tgl                      7511 ECB             :             deparse_namespace save_dpns;
                               7512                 :             const char *result;
 4232 tgl                      7513 EUB             : 
 4232 tgl                      7514 GIC           6 :             push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
 4232 tgl                      7515 CBC           6 :             result = get_name_for_var_field((Var *) expr, fieldno,
                               7516                 :                                             0, context);
 4232 tgl                      7517 GIC           6 :             pop_ancestor_plan(dpns, &save_dpns);
                               7518               6 :             return result;
                               7519                 :         }
                               7520                 :     }
                               7521                 : 
                               7522                 :     /*
 5889 tgl                      7523 ECB             :      * If it's a Var of type RECORD, we have to find what the Var refers to;
                               7524                 :      * if not, we can use get_expr_result_tupdesc().
                               7525                 :      */
 5889 tgl                      7526 CBC         352 :     if (!IsA(var, Var) ||
 5889 tgl                      7527 GIC         324 :         var->vartype != RECORDOID)
                               7528                 :     {
 1991                          7529             271 :         tupleDesc = get_expr_result_tupdesc((Node *) var, false);
 5889 tgl                      7530 ECB             :         /* Got the tupdesc, so we can extract the field name */
 5889 tgl                      7531 CBC         271 :         Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
 2058 andres                   7532 GIC         271 :         return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
                               7533                 :     }
                               7534                 : 
                               7535                 :     /* Find appropriate nesting depth */
 5889 tgl                      7536              81 :     netlevelsup = var->varlevelsup + levelsup;
                               7537              81 :     if (netlevelsup >= list_length(context->namespaces))
 5889 tgl                      7538 UIC           0 :         elog(ERROR, "bogus varlevelsup: %d offset %d",
                               7539                 :              var->varlevelsup, levelsup);
 5889 tgl                      7540 GIC          81 :     dpns = (deparse_namespace *) list_nth(context->namespaces,
                               7541                 :                                           netlevelsup);
                               7542                 : 
 1186 tgl                      7543 ECB             :     /*
                               7544                 :      * If we have a syntactic referent for the Var, and we're working from a
                               7545                 :      * parse tree, prefer to use the syntactic referent.  Otherwise, fall back
                               7546                 :      * on the semantic referent.  (See comments in get_variable().)
                               7547                 :      */
 1186 tgl                      7548 CBC          81 :     if (var->varnosyn > 0 && dpns->plan == NULL)
                               7549                 :     {
 1186 tgl                      7550 GIC          27 :         varno = var->varnosyn;
                               7551              27 :         varattno = var->varattnosyn;
                               7552                 :     }
                               7553                 :     else
 1186 tgl                      7554 ECB             :     {
 1186 tgl                      7555 CBC          54 :         varno = var->varno;
 1186 tgl                      7556 GBC          54 :         varattno = var->varattno;
                               7557                 :     }
 1186 tgl                      7558 ECB             : 
 5889                          7559                 :     /*
                               7560                 :      * Try to find the relevant RTE in this rtable.  In a plan tree, it's
 4198                          7561                 :      * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
                               7562                 :      * down into the subplans, or INDEX_VAR, which is resolved similarly.
                               7563                 :      *
 1215                          7564                 :      * Note: unlike get_variable and resolve_special_varno, we need not worry
                               7565                 :      * about inheritance mapping: a child Var should have the same datatype as
                               7566                 :      * its parent, and here we're really only interested in the Var's type.
 5889                          7567                 :      */
 1186 tgl                      7568 GIC          81 :     if (varno >= 1 && varno <= list_length(dpns->rtable))
                               7569                 :     {
                               7570              42 :         rte = rt_fetch(varno, dpns->rtable);
                               7571              42 :         attnum = varattno;
                               7572                 :     }
 1186 tgl                      7573 CBC          39 :     else if (varno == OUTER_VAR && dpns->outer_tlist)
 5889 tgl                      7574 ECB             :     {
 5889 tgl                      7575 EUB             :         TargetEntry *tle;
                               7576                 :         deparse_namespace save_dpns;
 5889 tgl                      7577 ECB             :         const char *result;
                               7578                 : 
 1186 tgl                      7579 GIC          30 :         tle = get_tle_by_resno(dpns->outer_tlist, varattno);
 5889 tgl                      7580 CBC          30 :         if (!tle)
 1186 tgl                      7581 UIC           0 :             elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
                               7582                 : 
 5889 tgl                      7583 CBC          30 :         Assert(netlevelsup == 0);
 1215                          7584              30 :         push_child_plan(dpns, dpns->outer_plan, &save_dpns);
                               7585                 : 
 5889 tgl                      7586 GBC          30 :         result = get_name_for_var_field((Var *) tle->expr, fieldno,
                               7587                 :                                         levelsup, context);
                               7588                 : 
 4653 tgl                      7589 GIC          30 :         pop_child_plan(dpns, &save_dpns);
 5889                          7590              30 :         return result;
 5889 tgl                      7591 EUB             :     }
 1186 tgl                      7592 GBC           9 :     else if (varno == INNER_VAR && dpns->inner_tlist)
 5889 tgl                      7593 EUB             :     {
                               7594                 :         TargetEntry *tle;
 4653                          7595                 :         deparse_namespace save_dpns;
                               7596                 :         const char *result;
 5889                          7597                 : 
 1186 tgl                      7598 GIC           9 :         tle = get_tle_by_resno(dpns->inner_tlist, varattno);
 5889                          7599               9 :         if (!tle)
 1186 tgl                      7600 UBC           0 :             elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
                               7601                 : 
 5889 tgl                      7602 GIC           9 :         Assert(netlevelsup == 0);
 1215                          7603               9 :         push_child_plan(dpns, dpns->inner_plan, &save_dpns);
 5889 tgl                      7604 EUB             : 
 5889 tgl                      7605 GIC           9 :         result = get_name_for_var_field((Var *) tle->expr, fieldno,
                               7606                 :                                         levelsup, context);
                               7607                 : 
 4653 tgl                      7608 CBC           9 :         pop_child_plan(dpns, &save_dpns);
 5889 tgl                      7609 GIC           9 :         return result;
                               7610                 :     }
 1186 tgl                      7611 LBC           0 :     else if (varno == INDEX_VAR && dpns->index_tlist)
                               7612                 :     {
                               7613                 :         TargetEntry *tle;
                               7614                 :         const char *result;
                               7615                 : 
 1186 tgl                      7616 UIC           0 :         tle = get_tle_by_resno(dpns->index_tlist, varattno);
 4198                          7617               0 :         if (!tle)
 1186                          7618               0 :             elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
                               7619                 : 
 4198                          7620               0 :         Assert(netlevelsup == 0);
 4198 tgl                      7621 ECB             : 
 4198 tgl                      7622 UIC           0 :         result = get_name_for_var_field((Var *) tle->expr, fieldno,
 4198 tgl                      7623 ECB             :                                         levelsup, context);
                               7624                 : 
 4198 tgl                      7625 UBC           0 :         return result;
                               7626                 :     }
                               7627                 :     else
                               7628                 :     {
 1186 tgl                      7629 UIC           0 :         elog(ERROR, "bogus varno: %d", varno);
                               7630                 :         return NULL;            /* keep compiler quiet */
                               7631                 :     }
                               7632                 : 
 6522 tgl                      7633 GIC          42 :     if (attnum == InvalidAttrNumber)
                               7634                 :     {
 6522 tgl                      7635 EUB             :         /* Var is whole-row reference to RTE, so select the right field */
 6522 tgl                      7636 CBC          12 :         return get_rte_attribute_name(rte, fieldno);
                               7637                 :     }
                               7638                 : 
 5889 tgl                      7639 ECB             :     /*
                               7640                 :      * This part has essentially the same logic as the parser's
                               7641                 :      * expandRecordVariable() function, but we are dealing with a different
                               7642                 :      * representation of the input context, and we only need one field name
                               7643                 :      * not a TupleDesc.  Also, we need special cases for finding subquery and
 5050 bruce                    7644                 :      * CTE subplans when deparsing Plan trees.
 5889 tgl                      7645 EUB             :      */
 6522 tgl                      7646 GIC          30 :     expr = (Node *) var;        /* default if we can't drill down */
 6522 tgl                      7647 ECB             : 
 6522 tgl                      7648 CBC          30 :     switch (rte->rtekind)
                               7649                 :     {
 6522 tgl                      7650 UIC           0 :         case RTE_RELATION:
                               7651                 :         case RTE_VALUES:
                               7652                 :         case RTE_NAMEDTUPLESTORE:
                               7653                 :         case RTE_RESULT:
                               7654                 : 
                               7655                 :             /*
                               7656                 :              * This case should not occur: a column of a table, values list,
                               7657                 :              * or ENR shouldn't have type RECORD.  Fall through and fail (most
                               7658                 :              * likely) at the bottom.
 6522 tgl                      7659 ECB             :              */
 6522 tgl                      7660 UIC           0 :             break;
 6522 tgl                      7661 GIC           9 :         case RTE_SUBQUERY:
 5298 tgl                      7662 ECB             :             /* Subselect-in-FROM: examine sub-select's output expr */
                               7663                 :             {
 5889 tgl                      7664 GIC           9 :                 if (rte->subquery)
 6522 tgl                      7665 ECB             :                 {
 5889 tgl                      7666 GIC           6 :                     TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
                               7667                 :                                                         attnum);
 5889 tgl                      7668 ECB             : 
 5889 tgl                      7669 CBC           6 :                     if (ste == NULL || ste->resjunk)
 5889 tgl                      7670 UIC           0 :                         elog(ERROR, "subquery %s does not have attribute %d",
 5889 tgl                      7671 ECB             :                              rte->eref->aliasname, attnum);
 5889 tgl                      7672 GIC           6 :                     expr = (Node *) ste->expr;
                               7673               6 :                     if (IsA(expr, Var))
                               7674                 :                     {
                               7675                 :                         /*
                               7676                 :                          * Recurse into the sub-select to see what its Var
                               7677                 :                          * refers to. We have to build an additional level of
                               7678                 :                          * namespace to keep in step with varlevelsup in the
                               7679                 :                          * subselect.
                               7680                 :                          */
                               7681                 :                         deparse_namespace mydpns;
                               7682                 :                         const char *result;
                               7683                 : 
 3751                          7684               6 :                         set_deparse_for_query(&mydpns, rte->subquery,
                               7685                 :                                               context->namespaces);
                               7686                 : 
 5889                          7687               6 :                         context->namespaces = lcons(&mydpns,
 5889 tgl                      7688 ECB             :                                                     context->namespaces);
 6522 tgl                      7689 EUB             : 
 5889 tgl                      7690 GIC           6 :                         result = get_name_for_var_field((Var *) expr, fieldno,
 5889 tgl                      7691 ECB             :                                                         0, context);
 6522                          7692                 : 
 5889 tgl                      7693 GBC           6 :                         context->namespaces =
 5889 tgl                      7694 GIC           6 :                             list_delete_first(context->namespaces);
 6522 tgl                      7695 ECB             : 
 5889 tgl                      7696 CBC           6 :                         return result;
                               7697                 :                     }
 5889 tgl                      7698 ECB             :                     /* else fall through to inspect the expression */
                               7699                 :                 }
                               7700                 :                 else
                               7701                 :                 {
                               7702                 :                     /*
                               7703                 :                      * We're deparsing a Plan tree so we don't have complete
                               7704                 :                      * RTE entries (in particular, rte->subquery is NULL). But
 5050 bruce                    7705 EUB             :                      * the only place we'd see a Var directly referencing a
                               7706                 :                      * SUBQUERY RTE is in a SubqueryScan plan node, and we can
                               7707                 :                      * look into the child plan's tlist instead.
 5889 tgl                      7708                 :                      */
                               7709                 :                     TargetEntry *tle;
 4653                          7710                 :                     deparse_namespace save_dpns;
 5889                          7711                 :                     const char *result;
                               7712                 : 
 1215 tgl                      7713 GIC           3 :                     if (!dpns->inner_plan)
 5889 tgl                      7714 UBC           0 :                         elog(ERROR, "failed to find plan for subquery %s",
 5889 tgl                      7715 EUB             :                              rte->eref->aliasname);
 4198 tgl                      7716 GBC           3 :                     tle = get_tle_by_resno(dpns->inner_tlist, attnum);
 5889 tgl                      7717 GIC           3 :                     if (!tle)
 5889 tgl                      7718 UIC           0 :                         elog(ERROR, "bogus varattno for subquery var: %d",
 5889 tgl                      7719 EUB             :                              attnum);
 5889 tgl                      7720 GBC           3 :                     Assert(netlevelsup == 0);
 1215 tgl                      7721 GIC           3 :                     push_child_plan(dpns, dpns->inner_plan, &save_dpns);
                               7722                 : 
 5889                          7723               3 :                     result = get_name_for_var_field((Var *) tle->expr, fieldno,
                               7724                 :                                                     levelsup, context);
                               7725                 : 
 4653                          7726               3 :                     pop_child_plan(dpns, &save_dpns);
 6522 tgl                      7727 GBC           3 :                     return result;
 6522 tgl                      7728 ECB             :                 }
                               7729                 :             }
 6522 tgl                      7730 UIC           0 :             break;
 6522 tgl                      7731 LBC           0 :         case RTE_JOIN:
                               7732                 :             /* Join RTE --- recursively inspect the alias variable */
 5799 tgl                      7733 UIC           0 :             if (rte->joinaliasvars == NIL)
                               7734               0 :                 elog(ERROR, "cannot decompile join alias var in plan tree");
 6522                          7735               0 :             Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
                               7736               0 :             expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
 3547                          7737               0 :             Assert(expr != NULL);
 3547 tgl                      7738 ECB             :             /* we intentionally don't strip implicit coercions here */
 6522 tgl                      7739 LBC           0 :             if (IsA(expr, Var))
                               7740               0 :                 return get_name_for_var_field((Var *) expr, fieldno,
 6522 tgl                      7741 UIC           0 :                                               var->varlevelsup + levelsup,
                               7742                 :                                               context);
                               7743                 :             /* else fall through to inspect the expression */
                               7744               0 :             break;
                               7745               0 :         case RTE_FUNCTION:
 2223 alvherre                 7746 ECB             :         case RTE_TABLEFUNC:
 6385 bruce                    7747                 : 
                               7748                 :             /*
                               7749                 :              * We couldn't get here unless a function is declared with one of
                               7750                 :              * its result columns as RECORD, which is not allowed.
 6522 tgl                      7751                 :              */
 6522 tgl                      7752 UIC           0 :             break;
 5300 tgl                      7753 GIC          21 :         case RTE_CTE:
 5298 tgl                      7754 ECB             :             /* CTE reference: examine subquery's output expr */
                               7755                 :             {
 5298 tgl                      7756 CBC          21 :                 CommonTableExpr *cte = NULL;
 5298 tgl                      7757 ECB             :                 Index       ctelevelsup;
                               7758                 :                 ListCell   *lc;
                               7759                 : 
                               7760                 :                 /*
 5298 tgl                      7761 EUB             :                  * Try to find the referenced CTE using the namespace stack.
                               7762                 :                  */
 5298 tgl                      7763 CBC          21 :                 ctelevelsup = rte->ctelevelsup + netlevelsup;
                               7764              21 :                 if (ctelevelsup >= list_length(context->namespaces))
 5298 tgl                      7765 GIC           6 :                     lc = NULL;
                               7766                 :                 else
                               7767                 :                 {
                               7768                 :                     deparse_namespace *ctedpns;
                               7769                 : 
                               7770                 :                     ctedpns = (deparse_namespace *)
                               7771              15 :                         list_nth(context->namespaces, ctelevelsup);
                               7772              15 :                     foreach(lc, ctedpns->ctes)
 5298 tgl                      7773 ECB             :                     {
 5298 tgl                      7774 GIC           9 :                         cte = (CommonTableExpr *) lfirst(lc);
                               7775               9 :                         if (strcmp(cte->ctename, rte->ctename) == 0)
                               7776               9 :                             break;
                               7777                 :                     }
 5298 tgl                      7778 ECB             :                 }
 5298 tgl                      7779 GIC          21 :                 if (lc != NULL)
                               7780                 :                 {
 5298 tgl                      7781 CBC           9 :                     Query      *ctequery = (Query *) cte->ctequery;
 4382 bruce                    7782 GIC           9 :                     TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte),
 5298 tgl                      7783 ECB             :                                                         attnum);
                               7784                 : 
 5298 tgl                      7785 CBC           9 :                     if (ste == NULL || ste->resjunk)
 5298 tgl                      7786 UIC           0 :                         elog(ERROR, "subquery %s does not have attribute %d",
                               7787                 :                              rte->eref->aliasname, attnum);
 5298 tgl                      7788 CBC           9 :                     expr = (Node *) ste->expr;
 5298 tgl                      7789 GIC           9 :                     if (IsA(expr, Var))
 5298 tgl                      7790 ECB             :                     {
                               7791                 :                         /*
                               7792                 :                          * Recurse into the CTE to see what its Var refers to.
                               7793                 :                          * We have to build an additional level of namespace
                               7794                 :                          * to keep in step with varlevelsup in the CTE.
                               7795                 :                          * Furthermore it could be an outer CTE, so we may
                               7796                 :                          * have to delete some levels of namespace.
                               7797                 :                          */
 5298 tgl                      7798 GIC           6 :                         List       *save_nslist = context->namespaces;
                               7799                 :                         List       *new_nslist;
                               7800                 :                         deparse_namespace mydpns;
                               7801                 :                         const char *result;
                               7802                 : 
 3751                          7803               6 :                         set_deparse_for_query(&mydpns, ctequery,
                               7804                 :                                               context->namespaces);
                               7805                 : 
 5298                          7806               6 :                         new_nslist = list_copy_tail(context->namespaces,
                               7807                 :                                                     ctelevelsup);
                               7808               6 :                         context->namespaces = lcons(&mydpns, new_nslist);
 5298 tgl                      7809 ECB             : 
 5298 tgl                      7810 GBC           6 :                         result = get_name_for_var_field((Var *) expr, fieldno,
                               7811                 :                                                         0, context);
 5298 tgl                      7812 ECB             : 
 5298 tgl                      7813 CBC           6 :                         context->namespaces = save_nslist;
 5298 tgl                      7814 EUB             : 
 5298 tgl                      7815 GIC           6 :                         return result;
 5298 tgl                      7816 ECB             :                     }
                               7817                 :                     /* else fall through to inspect the expression */
                               7818                 :                 }
                               7819                 :                 else
                               7820                 :                 {
                               7821                 :                     /*
                               7822                 :                      * We're deparsing a Plan tree so we don't have a CTE
  570                          7823                 :                      * list.  But the only places we'd see a Var directly
                               7824                 :                      * referencing a CTE RTE are in CteScan or WorkTableScan
                               7825                 :                      * plan nodes.  For those cases, set_deparse_plan arranged
                               7826                 :                      * for dpns->inner_plan to be the plan node that emits the
                               7827                 :                      * CTE or RecursiveUnion result, and we can look at its
                               7828                 :                      * tlist instead.
                               7829                 :                      */
                               7830                 :                     TargetEntry *tle;
                               7831                 :                     deparse_namespace save_dpns;
                               7832                 :                     const char *result;
 5298                          7833                 : 
 1215 tgl                      7834 GIC          12 :                     if (!dpns->inner_plan)
 5298 tgl                      7835 LBC           0 :                         elog(ERROR, "failed to find plan for CTE %s",
 5298 tgl                      7836 ECB             :                              rte->eref->aliasname);
 4198 tgl                      7837 GIC          12 :                     tle = get_tle_by_resno(dpns->inner_tlist, attnum);
 5298                          7838              12 :                     if (!tle)
 5298 tgl                      7839 UIC           0 :                         elog(ERROR, "bogus varattno for subquery var: %d",
                               7840                 :                              attnum);
 5298 tgl                      7841 GIC          12 :                     Assert(netlevelsup == 0);
 1215                          7842              12 :                     push_child_plan(dpns, dpns->inner_plan, &save_dpns);
                               7843                 : 
 5298                          7844              12 :                     result = get_name_for_var_field((Var *) tle->expr, fieldno,
                               7845                 :                                                     levelsup, context);
                               7846                 : 
 4653                          7847              12 :                     pop_child_plan(dpns, &save_dpns);
 5298 tgl                      7848 CBC          12 :                     return result;
                               7849                 :                 }
                               7850                 :             }
 5300 tgl                      7851 GIC           3 :             break;
 6522 tgl                      7852 ECB             :     }
                               7853                 : 
                               7854                 :     /*
                               7855                 :      * We now have an expression we can't expand any more, so see if
                               7856                 :      * get_expr_result_tupdesc() can do anything with it.
                               7857                 :      */
 1991 tgl                      7858 GIC           3 :     tupleDesc = get_expr_result_tupdesc(expr, false);
                               7859                 :     /* Got the tupdesc, so we can extract the field name */
 6522 tgl                      7860 CBC           3 :     Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
 2058 andres                   7861 GIC           3 :     return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
                               7862                 : }
                               7863                 : 
                               7864                 : /*
                               7865                 :  * Try to find the referenced expression for a PARAM_EXEC Param that might
 4232 tgl                      7866 ECB             :  * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
                               7867                 :  *
                               7868                 :  * If successful, return the expression and set *dpns_p and *ancestor_cell_p
 3260 bruce                    7869                 :  * appropriately for calling push_ancestor_plan().  If no referent can be
                               7870                 :  * found, return NULL.
 4653 tgl                      7871                 :  */
                               7872                 : static Node *
 4232 tgl                      7873 GIC        2425 : find_param_referent(Param *param, deparse_context *context,
                               7874                 :                     deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
                               7875                 : {
                               7876                 :     /* Initialize output parameters to prevent compiler warnings */
 4232 tgl                      7877 CBC        2425 :     *dpns_p = NULL;
                               7878            2425 :     *ancestor_cell_p = NULL;
                               7879                 : 
 4653 tgl                      7880 ECB             :     /*
                               7881                 :      * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
 4232                          7882                 :      * SubPlan argument.  This will necessarily be in some ancestor of the
                               7883                 :      * current expression's Plan node.
 4653                          7884                 :      */
 4653 tgl                      7885 GIC        2425 :     if (param->paramkind == PARAM_EXEC)
 4653 tgl                      7886 ECB             :     {
                               7887                 :         deparse_namespace *dpns;
                               7888                 :         Plan       *child_plan;
                               7889                 :         ListCell   *lc;
                               7890                 : 
 4653 tgl                      7891 GIC        2012 :         dpns = (deparse_namespace *) linitial(context->namespaces);
 1215                          7892            2012 :         child_plan = dpns->plan;
                               7893                 : 
 4653                          7894            3811 :         foreach(lc, dpns->ancestors)
                               7895                 :         {
 1215                          7896            3195 :             Node       *ancestor = (Node *) lfirst(lc);
 4653 tgl                      7897 ECB             :             ListCell   *lc2;
                               7898                 : 
                               7899                 :             /*
                               7900                 :              * NestLoops transmit params to their inner child only.
                               7901                 :              */
 1215 tgl                      7902 GIC        3195 :             if (IsA(ancestor, NestLoop) &&
  144 tgl                      7903 GNC        1287 :                 child_plan == innerPlan(ancestor))
                               7904                 :             {
 1215 tgl                      7905 CBC        1248 :                 NestLoop   *nl = (NestLoop *) ancestor;
                               7906                 : 
 4653 tgl                      7907 GIC        1528 :                 foreach(lc2, nl->nestParams)
                               7908                 :                 {
 4382 bruce                    7909            1483 :                     NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
                               7910                 : 
 4653 tgl                      7911            1483 :                     if (nlp->paramno == param->paramid)
                               7912                 :                     {
                               7913                 :                         /* Found a match, so return it */
 4232                          7914            1203 :                         *dpns_p = dpns;
 4232 tgl                      7915 CBC        1203 :                         *ancestor_cell_p = lc;
 4232 tgl                      7916 GIC        1203 :                         return (Node *) nlp->paramval;
                               7917                 :                     }
 4653 tgl                      7918 ECB             :                 }
                               7919                 :             }
                               7920                 : 
                               7921                 :             /*
 1215                          7922                 :              * If ancestor is a SubPlan, check the arguments it provides.
 4653                          7923                 :              */
 1215 tgl                      7924 CBC        1992 :             if (IsA(ancestor, SubPlan))
 4653 tgl                      7925 GIC          33 :             {
 1215                          7926             226 :                 SubPlan    *subplan = (SubPlan *) ancestor;
 4653 tgl                      7927 EUB             :                 ListCell   *lc3;
                               7928                 :                 ListCell   *lc4;
                               7929                 : 
 4653 tgl                      7930 GIC         254 :                 forboth(lc3, subplan->parParam, lc4, subplan->args)
                               7931                 :                 {
 4382 bruce                    7932 CBC         221 :                     int         paramid = lfirst_int(lc3);
 4382 bruce                    7933 GIC         221 :                     Node       *arg = (Node *) lfirst(lc4);
                               7934                 : 
 4653 tgl                      7935             221 :                     if (paramid == param->paramid)
                               7936                 :                     {
                               7937                 :                         /*
                               7938                 :                          * Found a match, so return it.  But, since Vars in
                               7939                 :                          * the arg are to be evaluated in the surrounding
                               7940                 :                          * context, we have to point to the next ancestor item
 1215 tgl                      7941 ECB             :                          * that is *not* a SubPlan.
                               7942                 :                          */
                               7943                 :                         ListCell   *rest;
                               7944                 : 
 1215 tgl                      7945 GIC         193 :                         for_each_cell(rest, dpns->ancestors,
 1215 tgl                      7946 ECB             :                                       lnext(dpns->ancestors, lc))
                               7947                 :                         {
 1215 tgl                      7948 GIC         193 :                             Node       *ancestor2 = (Node *) lfirst(rest);
                               7949                 : 
                               7950             193 :                             if (!IsA(ancestor2, SubPlan))
                               7951                 :                             {
                               7952             193 :                                 *dpns_p = dpns;
 1215 tgl                      7953 CBC         193 :                                 *ancestor_cell_p = rest;
 1215 tgl                      7954 GIC         193 :                                 return arg;
                               7955                 :                             }
                               7956                 :                         }
 1215 tgl                      7957 UIC           0 :                         elog(ERROR, "SubPlan cannot be outermost ancestor");
                               7958                 :                     }
                               7959                 :                 }
                               7960                 : 
                               7961                 :                 /* SubPlan isn't a kind of Plan, so skip the rest */
 1215 tgl                      7962 CBC          33 :                 continue;
 4653 tgl                      7963 ECB             :             }
                               7964                 : 
                               7965                 :             /*
                               7966                 :              * We need not consider the ancestor's initPlan list, since
                               7967                 :              * initplans never have any parParams.
                               7968                 :              */
                               7969                 : 
                               7970                 :             /* No luck, crawl up to next ancestor */
 1215 tgl                      7971 GBC        1766 :             child_plan = (Plan *) ancestor;
 4653 tgl                      7972 ECB             :         }
 4653 tgl                      7973 EUB             :     }
                               7974                 : 
 4232 tgl                      7975 ECB             :     /* No referent found */
 4232 tgl                      7976 GIC        1029 :     return NULL;
 4653 tgl                      7977 ECB             : }
 4653 tgl                      7978 EUB             : 
                               7979                 : /*
 4232 tgl                      7980 ECB             :  * Display a Param appropriately.
                               7981                 :  */
 4653                          7982                 : static void
 4232 tgl                      7983 GIC        2419 : get_parameter(Param *param, deparse_context *context)
 4653 tgl                      7984 ECB             : {
                               7985                 :     Node       *expr;
                               7986                 :     deparse_namespace *dpns;
                               7987                 :     ListCell   *ancestor_cell;
                               7988                 : 
                               7989                 :     /*
                               7990                 :      * If it's a PARAM_EXEC parameter, try to locate the expression from which
 3260 bruce                    7991                 :      * the parameter was computed.  Note that failing to find a referent isn't
                               7992                 :      * an error, since the Param might well be a subplan output rather than an
 4232 tgl                      7993                 :      * input.
 4653                          7994                 :      */
 4232 tgl                      7995 CBC        2419 :     expr = find_param_referent(param, context, &dpns, &ancestor_cell);
                               7996            2419 :     if (expr)
                               7997                 :     {
 4232 tgl                      7998 ECB             :         /* Found a match, so print it */
                               7999                 :         deparse_namespace save_dpns;
                               8000                 :         bool        save_varprefix;
                               8001                 :         bool        need_paren;
 4653                          8002                 : 
                               8003                 :         /* Switch attention to the ancestor plan node */
 4232 tgl                      8004 GIC        1390 :         push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
                               8005                 : 
                               8006                 :         /*
                               8007                 :          * Force prefixing of Vars, since they won't belong to the relation
                               8008                 :          * being scanned in the original plan node.
                               8009                 :          */
                               8010            1390 :         save_varprefix = context->varprefix;
 4232 tgl                      8011 CBC        1390 :         context->varprefix = true;
                               8012                 : 
 4232 tgl                      8013 ECB             :         /*
                               8014                 :          * A Param's expansion is typically a Var, Aggref, GroupingFunc, or
  384                          8015                 :          * upper-level Param, which wouldn't need extra parentheses.
                               8016                 :          * Otherwise, insert parens to ensure the expression looks atomic.
 4232                          8017                 :          */
 4232 tgl                      8018 CBC        1393 :         need_paren = !(IsA(expr, Var) ||
 4232 tgl                      8019 GIC           3 :                        IsA(expr, Aggref) ||
  384                          8020               3 :                        IsA(expr, GroupingFunc) ||
 4232 tgl                      8021 LBC           0 :                        IsA(expr, Param));
 4232 tgl                      8022 GIC        1390 :         if (need_paren)
 4232 tgl                      8023 LBC           0 :             appendStringInfoChar(context->buf, '(');
 4653 tgl                      8024 ECB             : 
 4232 tgl                      8025 GIC        1390 :         get_rule_expr(expr, context, false);
                               8026                 : 
 4232 tgl                      8027 CBC        1390 :         if (need_paren)
 4232 tgl                      8028 LBC           0 :             appendStringInfoChar(context->buf, ')');
                               8029                 : 
 4232 tgl                      8030 GIC        1390 :         context->varprefix = save_varprefix;
                               8031                 : 
                               8032            1390 :         pop_ancestor_plan(dpns, &save_dpns);
                               8033                 : 
                               8034            1390 :         return;
                               8035                 :     }
 4232 tgl                      8036 ECB             : 
                               8037                 :     /*
                               8038                 :      * If it's an external parameter, see if the outermost namespace provides
                               8039                 :      * function argument names.
                               8040                 :      */
  508 tgl                      8041 GIC        1029 :     if (param->paramkind == PARAM_EXTERN && context->namespaces != NIL)
                               8042                 :     {
                               8043             413 :         dpns = llast(context->namespaces);
                               8044             413 :         if (dpns->argnames &&
                               8045              33 :             param->paramid > 0 &&
  508 tgl                      8046 CBC          33 :             param->paramid <= dpns->numargs)
                               8047                 :         {
  732 peter                    8048              33 :             char       *argname = dpns->argnames[param->paramid - 1];
                               8049                 : 
                               8050              33 :             if (argname)
                               8051                 :             {
  732 peter                    8052 GIC          33 :                 bool        should_qualify = false;
  732 peter                    8053 ECB             :                 ListCell   *lc;
                               8054                 : 
                               8055                 :                 /*
                               8056                 :                  * Qualify the parameter name if there are any other deparse
                               8057                 :                  * namespaces with range tables.  This avoids qualifying in
                               8058                 :                  * trivial cases like "RETURN a + b", but makes it safe in all
                               8059                 :                  * other cases.
                               8060                 :                  */
  732 peter                    8061 GBC          75 :                 foreach(lc, context->namespaces)
                               8062                 :                 {
  186 drowley                  8063 GNC          57 :                     deparse_namespace *depns = lfirst(lc);
                               8064                 : 
                               8065              57 :                     if (depns->rtable_names != NIL)
                               8066                 :                     {
  732 peter                    8067 GIC          15 :                         should_qualify = true;
                               8068              15 :                         break;
                               8069                 :                     }
                               8070                 :                 }
                               8071              33 :                 if (should_qualify)
  732 peter                    8072 ECB             :                 {
  732 peter                    8073 GIC          15 :                     appendStringInfoString(context->buf, quote_identifier(dpns->funcname));
  732 peter                    8074 CBC          15 :                     appendStringInfoChar(context->buf, '.');
  732 peter                    8075 EUB             :                 }
                               8076                 : 
  732 peter                    8077 CBC          33 :                 appendStringInfoString(context->buf, quote_identifier(argname));
  732 peter                    8078 GIC          33 :                 return;
  732 peter                    8079 ECB             :             }
                               8080                 :         }
                               8081                 :     }
                               8082                 : 
                               8083                 :     /*
                               8084                 :      * Not PARAM_EXEC, or couldn't find referent: just print $N.
                               8085                 :      */
 4232 tgl                      8086 CBC         996 :     appendStringInfo(context->buf, "$%d", param->paramid);
                               8087                 : }
 7549 tgl                      8088 ECB             : 
                               8089                 : /*
                               8090                 :  * get_simple_binary_op_name
                               8091                 :  *
                               8092                 :  * helper function for isSimpleNode
                               8093                 :  * will return single char binary operator name, or NULL if it's not
                               8094                 :  */
                               8095                 : static const char *
 7184 bruce                    8096 GIC          57 : get_simple_binary_op_name(OpExpr *expr)
                               8097                 : {
 7193 tgl                      8098              57 :     List       *args = expr->args;
                               8099                 : 
 6888 neilc                    8100              57 :     if (list_length(args) == 2)
                               8101                 :     {
 7193 tgl                      8102 ECB             :         /* binary operator */
 6892 neilc                    8103 GIC          57 :         Node       *arg1 = (Node *) linitial(args);
 7193 tgl                      8104              57 :         Node       *arg2 = (Node *) lsecond(args);
 7193 tgl                      8105 EUB             :         const char *op;
                               8106                 : 
 7193 tgl                      8107 GIC          57 :         op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
 7193 tgl                      8108 CBC          57 :         if (strlen(op) == 1)
 7188 bruce                    8109 GIC          57 :             return op;
                               8110                 :     }
 7193 tgl                      8111 UIC           0 :     return NULL;
                               8112                 : }
                               8113                 : 
 7193 tgl                      8114 ECB             : 
                               8115                 : /*
 7193 tgl                      8116 EUB             :  * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
                               8117                 :  *
                               8118                 :  *  true   : simple in the context of parent node's type
                               8119                 :  *  false  : not simple
                               8120                 :  */
                               8121                 : static bool
 7193 tgl                      8122 GIC        2212 : isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
 7193 tgl                      8123 EUB             : {
 7188 bruce                    8124 GIC        2212 :     if (!node)
 7193 tgl                      8125 UBC           0 :         return false;
                               8126                 : 
 7188 bruce                    8127 CBC        2212 :     switch (nodeTag(node))
 7188 bruce                    8128 ECB             :     {
 7193 tgl                      8129 GIC        1852 :         case T_Var:
 7193 tgl                      8130 EUB             :         case T_Const:
                               8131                 :         case T_Param:
                               8132                 :         case T_CoerceToDomainValue:
                               8133                 :         case T_SetToDefault:
 5781                          8134                 :         case T_CurrentOfExpr:
                               8135                 :             /* single words: always simple */
 7193 tgl                      8136 GBC        1852 :             return true;
 7193 tgl                      8137 EUB             : 
 1528 alvherre                 8138 GIC         186 :         case T_SubscriptingRef:
                               8139                 :         case T_ArrayExpr:
 6908 tgl                      8140 ECB             :         case T_RowExpr:
                               8141                 :         case T_CoalesceExpr:
                               8142                 :         case T_MinMaxExpr:
                               8143                 :         case T_XmlExpr:
                               8144                 :         case T_NextValueExpr:
                               8145                 :         case T_NullIfExpr:
                               8146                 :         case T_Aggref:
                               8147                 :         case T_GroupingFunc:
                               8148                 :         case T_WindowFunc:
                               8149                 :         case T_FuncExpr:
                               8150                 :         case T_JsonConstructorExpr:
                               8151                 :             /* function-like: name(..) or name[..] */
 7193 tgl                      8152 CBC         186 :             return true;
 7193 tgl                      8153 ECB             : 
 7188 bruce                    8154 EUB             :             /* CASE keywords act as parentheses */
 7193 tgl                      8155 UIC           0 :         case T_CaseExpr:
                               8156               0 :             return true;
 7193 tgl                      8157 ECB             : 
 7193 tgl                      8158 CBC          24 :         case T_FieldSelect:
 7188 bruce                    8159 ECB             : 
 7193 tgl                      8160                 :             /*
                               8161                 :              * appears simple since . has top precedence, unless parent is
                               8162                 :              * T_FieldSelect itself!
                               8163                 :              */
  578 michael                  8164 GBC          24 :             return !IsA(parentNode, FieldSelect);
                               8165                 : 
 6878 tgl                      8166 LBC           0 :         case T_FieldStore:
 6878 tgl                      8167 ECB             : 
                               8168                 :             /*
 6878 tgl                      8169 EUB             :              * treat like FieldSelect (probably doesn't matter)
                               8170                 :              */
  578 michael                  8171 LBC           0 :             return !IsA(parentNode, FieldStore);
 6878 tgl                      8172 ECB             : 
 7193 tgl                      8173 UIC           0 :         case T_CoerceToDomain:
 7193 tgl                      8174 ECB             :             /* maybe simple, check args */
 7188 bruce                    8175 LBC           0 :             return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
                               8176                 :                                 node, prettyFlags);
 7193 tgl                      8177 GIC           3 :         case T_RelabelType:
 7188 bruce                    8178               3 :             return isSimpleNode((Node *) ((RelabelType *) node)->arg,
                               8179                 :                                 node, prettyFlags);
 5787 tgl                      8180 UIC           0 :         case T_CoerceViaIO:
 5787 tgl                      8181 LBC           0 :             return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
 5787 tgl                      8182 ECB             :                                 node, prettyFlags);
 5857 tgl                      8183 UIC           0 :         case T_ArrayCoerceExpr:
 5857 tgl                      8184 LBC           0 :             return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
                               8185                 :                                 node, prettyFlags);
 6693 tgl                      8186 UIC           0 :         case T_ConvertRowtypeExpr:
                               8187               0 :             return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
                               8188                 :                                 node, prettyFlags);
                               8189                 : 
 7193 tgl                      8190 GIC         126 :         case T_OpExpr:
                               8191                 :             {
                               8192                 :                 /* depends on parent node type; needs further checking */
 7188 bruce                    8193             126 :                 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
                               8194                 :                 {
 7188 bruce                    8195 ECB             :                     const char *op;
                               8196                 :                     const char *parentOp;
                               8197                 :                     bool        is_lopriop;
                               8198                 :                     bool        is_hipriop;
                               8199                 :                     bool        is_lopriparent;
                               8200                 :                     bool        is_hipriparent;
                               8201                 : 
 7188 bruce                    8202 CBC          30 :                     op = get_simple_binary_op_name((OpExpr *) node);
                               8203              30 :                     if (!op)
 7188 bruce                    8204 UIC           0 :                         return false;
 7193 tgl                      8205 ECB             : 
 7188 bruce                    8206 EUB             :                     /* We know only the basic operators + - and * / % */
 7188 bruce                    8207 GIC          30 :                     is_lopriop = (strchr("+-", *op) != NULL);
 7188 bruce                    8208 CBC          30 :                     is_hipriop = (strchr("*/%", *op) != NULL);
 7188 bruce                    8209 GIC          30 :                     if (!(is_lopriop || is_hipriop))
                               8210               3 :                         return false;
                               8211                 : 
                               8212              27 :                     parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
                               8213              27 :                     if (!parentOp)
 7188 bruce                    8214 UIC           0 :                         return false;
                               8215                 : 
 7188 bruce                    8216 GIC          27 :                     is_lopriparent = (strchr("+-", *parentOp) != NULL);
                               8217              27 :                     is_hipriparent = (strchr("*/%", *parentOp) != NULL);
                               8218              27 :                     if (!(is_lopriparent || is_hipriparent))
 7188 bruce                    8219 UIC           0 :                         return false;
 7193 tgl                      8220 ECB             : 
 7188 bruce                    8221 CBC          27 :                     if (is_hipriop && is_lopriparent)
                               8222               6 :                         return true;    /* op binds tighter than parent */
                               8223                 : 
 7188 bruce                    8224 GIC          21 :                     if (is_lopriop && is_hipriparent)
 7188 bruce                    8225 CBC          15 :                         return false;
 7193 tgl                      8226 ECB             : 
                               8227                 :                     /*
 6385 bruce                    8228                 :                      * Operators are same priority --- can skip parens only if
                               8229                 :                      * we have (a - b) - c, not a - (b - c).
                               8230                 :                      */
 6892 neilc                    8231 GIC           6 :                     if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
 7188 bruce                    8232               3 :                         return true;
                               8233                 : 
 7188 bruce                    8234 CBC           3 :                     return false;
 7188 bruce                    8235 ECB             :                 }
                               8236                 :                 /* else do the same stuff as for T_SubLink et al. */
                               8237                 :             }
 1804 tgl                      8238                 :             /* FALLTHROUGH */
                               8239                 : 
 7193                          8240                 :         case T_SubLink:
                               8241                 :         case T_NullTest:
 7193 tgl                      8242 EUB             :         case T_BooleanTest:
 7193 tgl                      8243 ECB             :         case T_DistinctExpr:
                               8244                 :         case T_JsonIsPredicate:
 7193 tgl                      8245 CBC         108 :             switch (nodeTag(parentNode))
 7193 tgl                      8246 EUB             :             {
 7193 tgl                      8247 CBC          15 :                 case T_FuncExpr:
                               8248                 :                     {
                               8249                 :                         /* special handling for casts and COERCE_SQL_SYNTAX */
 7188 bruce                    8250              15 :                         CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
 7193 tgl                      8251 EUB             : 
 7188 bruce                    8252 GIC          15 :                         if (type == COERCE_EXPLICIT_CAST ||
  129 tgl                      8253               3 :                             type == COERCE_IMPLICIT_CAST ||
  129 tgl                      8254 EUB             :                             type == COERCE_SQL_SYNTAX)
 7188 bruce                    8255 GIC          15 :                             return false;
 7188 bruce                    8256 UBC           0 :                         return true;    /* own parentheses */
 7188 bruce                    8257 EUB             :                     }
 2118 tgl                      8258 GIC          81 :                 case T_BoolExpr:    /* lower precedence */
 1528 alvherre                 8259 EUB             :                 case T_SubscriptingRef: /* other separators */
 2118 tgl                      8260                 :                 case T_ArrayExpr:   /* other separators */
                               8261                 :                 case T_RowExpr: /* other separators */
 7188 bruce                    8262                 :                 case T_CoalesceExpr:    /* own parentheses */
                               8263                 :                 case T_MinMaxExpr:  /* own parentheses */
                               8264                 :                 case T_XmlExpr: /* own parentheses */
                               8265                 :                 case T_NullIfExpr:  /* other separators */
                               8266                 :                 case T_Aggref:  /* own parentheses */
                               8267                 :                 case T_GroupingFunc:    /* own parentheses */
                               8268                 :                 case T_WindowFunc:  /* own parentheses */
                               8269                 :                 case T_CaseExpr:    /* other separators */
 7193 tgl                      8270 GIC          81 :                     return true;
                               8271              12 :                 default:
                               8272              12 :                     return false;
 7193 tgl                      8273 EUB             :             }
                               8274                 : 
 7193 tgl                      8275 GBC           9 :         case T_BoolExpr:
 7193 tgl                      8276 GIC           9 :             switch (nodeTag(parentNode))
                               8277                 :             {
 7193 tgl                      8278 GBC           9 :                 case T_BoolExpr:
 7193 tgl                      8279 GIC           9 :                     if (prettyFlags & PRETTYFLAG_PAREN)
 7193 tgl                      8280 EUB             :                     {
                               8281                 :                         BoolExprType type;
                               8282                 :                         BoolExprType parentType;
                               8283                 : 
 7188 bruce                    8284 GBC           9 :                         type = ((BoolExpr *) node)->boolop;
 7188 bruce                    8285 GIC           9 :                         parentType = ((BoolExpr *) parentNode)->boolop;
                               8286                 :                         switch (type)
 7193 tgl                      8287 EUB             :                         {
 7193 tgl                      8288 GIC           6 :                             case NOT_EXPR:
                               8289                 :                             case AND_EXPR:
                               8290               6 :                                 if (parentType == AND_EXPR || parentType == OR_EXPR)
                               8291               6 :                                     return true;
 7193 tgl                      8292 UIC           0 :                                 break;
 7193 tgl                      8293 GIC           3 :                             case OR_EXPR:
                               8294               3 :                                 if (parentType == OR_EXPR)
 7193 tgl                      8295 UIC           0 :                                     return true;
 7193 tgl                      8296 GIC           3 :                                 break;
                               8297                 :                         }
 7193 tgl                      8298 ECB             :                     }
 7193 tgl                      8299 GIC           3 :                     return false;
 7193 tgl                      8300 UIC           0 :                 case T_FuncExpr:
 7188 bruce                    8301 ECB             :                     {
                               8302                 :                         /* special handling for casts and COERCE_SQL_SYNTAX */
 7188 bruce                    8303 LBC           0 :                         CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
                               8304                 : 
 7188 bruce                    8305 UIC           0 :                         if (type == COERCE_EXPLICIT_CAST ||
  129 tgl                      8306               0 :                             type == COERCE_IMPLICIT_CAST ||
  129 tgl                      8307 ECB             :                             type == COERCE_SQL_SYNTAX)
 7188 bruce                    8308 UIC           0 :                             return false;
                               8309               0 :                         return true;    /* own parentheses */
 7188 bruce                    8310 ECB             :                     }
 1528 alvherre                 8311 UIC           0 :                 case T_SubscriptingRef: /* other separators */
 2118 tgl                      8312 ECB             :                 case T_ArrayExpr:   /* other separators */
                               8313                 :                 case T_RowExpr: /* other separators */
 7188 bruce                    8314                 :                 case T_CoalesceExpr:    /* own parentheses */
 2118 tgl                      8315                 :                 case T_MinMaxExpr:  /* own parentheses */
                               8316                 :                 case T_XmlExpr: /* own parentheses */
                               8317                 :                 case T_NullIfExpr:  /* other separators */
                               8318                 :                 case T_Aggref:  /* own parentheses */
                               8319                 :                 case T_GroupingFunc:    /* own parentheses */
                               8320                 :                 case T_WindowFunc:  /* own parentheses */
                               8321                 :                 case T_CaseExpr:    /* other separators */
 7193 tgl                      8322 UIC           0 :                     return true;
                               8323               0 :                 default:
                               8324               0 :                     return false;
                               8325                 :             }
                               8326                 : 
   11 alvherre                 8327 UNC           0 :         case T_JsonValueExpr:
                               8328                 :             /* maybe simple, check args */
                               8329               0 :             return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
                               8330                 :                                 node, prettyFlags);
                               8331                 : 
 7193 tgl                      8332 UBC           0 :         default:
                               8333               0 :             break;
                               8334                 :     }
 7188 bruce                    8335 EUB             :     /* those we don't know: in dubio complexo */
 7188 bruce                    8336 UIC           0 :     return false;
 7193 tgl                      8337 EUB             : }
                               8338                 : 
 7193 tgl                      8339 ECB             : 
                               8340                 : /*
                               8341                 :  * appendContextKeyword - append a keyword to buffer
                               8342                 :  *
                               8343                 :  * If prettyPrint is enabled, perform a line break, and adjust indentation.
                               8344                 :  * Otherwise, just append the keyword.
 7193 tgl                      8345 EUB             :  */
                               8346                 : static void
 7193 tgl                      8347 GIC        8815 : appendContextKeyword(deparse_context *context, const char *str,
 7193 tgl                      8348 ECB             :                      int indentBefore, int indentAfter, int indentPlus)
                               8349                 : {
 3436 tgl                      8350 GIC        8815 :     StringInfo  buf = context->buf;
                               8351                 : 
 7188 bruce                    8352            8815 :     if (PRETTY_INDENT(context))
                               8353                 :     {
                               8354                 :         int         indentAmount;
                               8355                 : 
 7193 tgl                      8356            8666 :         context->indentLevel += indentBefore;
 7193 tgl                      8357 ECB             : 
                               8358                 :         /* remove any trailing spaces currently in the buffer ... */
 3436 tgl                      8359 CBC        8666 :         removeStringInfoSpaces(buf);
 3436 tgl                      8360 ECB             :         /* ... then add a newline and some spaces */
 3436 tgl                      8361 CBC        8666 :         appendStringInfoChar(buf, '\n');
                               8362                 : 
 3266 tgl                      8363 GIC        8666 :         if (context->indentLevel < PRETTYINDENT_LIMIT)
                               8364            8666 :             indentAmount = Max(context->indentLevel, 0) + indentPlus;
                               8365                 :         else
                               8366                 :         {
                               8367                 :             /*
                               8368                 :              * If we're indented more than PRETTYINDENT_LIMIT characters, try
                               8369                 :              * to conserve horizontal space by reducing the per-level
                               8370                 :              * indentation.  For best results the scale factor here should
                               8371                 :              * divide all the indent amounts that get added to indentLevel
                               8372                 :              * (PRETTYINDENT_STD, etc).  It's important that the indentation
                               8373                 :              * not grow unboundedly, else deeply-nested trees use O(N^2)
                               8374                 :              * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
                               8375                 :              */
 3266 tgl                      8376 LBC           0 :             indentAmount = PRETTYINDENT_LIMIT +
 3266 tgl                      8377 UIC           0 :                 (context->indentLevel - PRETTYINDENT_LIMIT) /
                               8378                 :                 (PRETTYINDENT_STD / 2);
                               8379               0 :             indentAmount %= PRETTYINDENT_LIMIT;
                               8380                 :             /* scale/wrap logic affects indentLevel, but not indentPlus */
 3266 tgl                      8381 LBC           0 :             indentAmount += indentPlus;
 3266 tgl                      8382 ECB             :         }
 3266 tgl                      8383 GIC        8666 :         appendStringInfoSpaces(buf, indentAmount);
 3436 tgl                      8384 ECB             : 
 3436 tgl                      8385 CBC        8666 :         appendStringInfoString(buf, str);
                               8386                 : 
 7193                          8387            8666 :         context->indentLevel += indentAfter;
 7193 tgl                      8388 GIC        8666 :         if (context->indentLevel < 0)
 7193 tgl                      8389 LBC           0 :             context->indentLevel = 0;
 7188 bruce                    8390 ECB             :     }
 6794 tgl                      8391                 :     else
 3436 tgl                      8392 GIC         149 :         appendStringInfoString(buf, str);
 7193                          8393            8815 : }
                               8394                 : 
                               8395                 : /*
                               8396                 :  * removeStringInfoSpaces - delete trailing spaces from a buffer.
                               8397                 :  *
                               8398                 :  * Possibly this should move to stringinfo.c at some point.
                               8399                 :  */
                               8400                 : static void
 3436                          8401            8777 : removeStringInfoSpaces(StringInfo str)
                               8402                 : {
                               8403           13554 :     while (str->len > 0 && str->data[str->len - 1] == ' ')
                               8404            4777 :         str->data[--(str->len)] = '\0';
                               8405            8777 : }
                               8406                 : 
                               8407                 : 
 7193 tgl                      8408 ECB             : /*
                               8409                 :  * get_rule_expr_paren  - deparse expr using get_rule_expr,
                               8410                 :  * embracing the string with parentheses if necessary for prettyPrint.
                               8411                 :  *
                               8412                 :  * Never embrace if prettyFlags=0, because it's done in the calling node.
                               8413                 :  *
                               8414                 :  * Any node that does *not* embrace its argument node by sql syntax (with
                               8415                 :  * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
                               8416                 :  * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
                               8417                 :  * added.
                               8418                 :  */
                               8419                 : static void
 7188 bruce                    8420 GIC       66059 : get_rule_expr_paren(Node *node, deparse_context *context,
                               8421                 :                     bool showimplicit, Node *parentNode)
                               8422                 : {
                               8423                 :     bool        need_paren;
                               8424                 : 
 7193 tgl                      8425           68268 :     need_paren = PRETTY_PAREN(context) &&
                               8426            2209 :         !isSimpleNode(node, parentNode, context->prettyFlags);
 7193 tgl                      8427 ECB             : 
 7193 tgl                      8428 GIC       66059 :     if (need_paren)
 7188 bruce                    8429 CBC          51 :         appendStringInfoChar(context->buf, '(');
 7193 tgl                      8430 ECB             : 
 7193 tgl                      8431 CBC       66059 :     get_rule_expr(node, context, showimplicit);
                               8432                 : 
                               8433           66059 :     if (need_paren)
 7188 bruce                    8434              51 :         appendStringInfoChar(context->buf, ')');
 7193 tgl                      8435           66059 : }
                               8436                 : 
  402 andrew                   8437 ECB             : 
 8994 bruce                    8438                 : /* ----------
                               8439                 :  * get_rule_expr            - Parse back an expression
                               8440                 :  *
 7507 tgl                      8441                 :  * Note: showimplicit determines whether we display any implicit cast that
                               8442                 :  * is present at the top of the expression tree.  It is a passed argument,
                               8443                 :  * not a field of the context struct, because we change the value as we
                               8444                 :  * recurse down into the expression.  In general we suppress implicit casts
                               8445                 :  * when the result type is known with certainty (eg, the arguments of an
                               8446                 :  * OR must be boolean).  We display implicit casts for arguments of functions
                               8447                 :  * and operators, since this is needed to be certain that the same function
                               8448                 :  * or operator will be chosen when the expression is re-parsed.
 8994 bruce                    8449                 :  * ----------
                               8450                 :  */
 8590 tgl                      8451                 : static void
 7507 tgl                      8452 GIC      131463 : get_rule_expr(Node *node, deparse_context *context,
 7507 tgl                      8453 ECB             :               bool showimplicit)
                               8454                 : {
 8589 tgl                      8455 CBC      131463 :     StringInfo  buf = context->buf;
 8589 tgl                      8456 ECB             : 
 8986 bruce                    8457 CBC      131463 :     if (node == NULL)
 8590 tgl                      8458 GIC          48 :         return;
 8994 bruce                    8459 ECB             : 
                               8460                 :     /* Guard against excessively long or deeply-nested queries */
 3266 tgl                      8461 CBC      131415 :     CHECK_FOR_INTERRUPTS();
 3266 tgl                      8462 GIC      131415 :     check_stack_depth();
                               8463                 : 
                               8464                 :     /*
                               8465                 :      * Each level of get_rule_expr must emit an indivisible term
                               8466                 :      * (parenthesized if necessary) to ensure result is reparsed into the same
                               8467                 :      * expression tree.  The only exception is that when the input is a List,
                               8468                 :      * we emit the component items comma-separated with no surrounding
                               8469                 :      * decoration; this is convenient for most callers.
                               8470                 :      */
 8986 bruce                    8471          131415 :     switch (nodeTag(node))
 8986 bruce                    8472 ECB             :     {
 8625 tgl                      8473 GIC       58979 :         case T_Var:
 3999 tgl                      8474 GBC       58979 :             (void) get_variable((Var *) node, 0, false, context);
 8986 bruce                    8475           58979 :             break;
                               8476                 : 
 7423 tgl                      8477           25743 :         case T_Const:
 5572 tgl                      8478 GIC       25743 :             get_const_expr((Const *) node, context, 0);
 7423                          8479           25743 :             break;
                               8480                 : 
                               8481            2419 :         case T_Param:
 4653                          8482            2419 :             get_parameter((Param *) node, context);
 8986 bruce                    8483            2419 :             break;
                               8484                 : 
 8625 tgl                      8485             762 :         case T_Aggref:
 2538 rhaas                    8486 CBC         762 :             get_agg_expr((Aggref *) node, context, (Aggref *) node);
 8625 tgl                      8487             762 :             break;
 8955 bruce                    8488 ECB             : 
 2885 andres                   8489 CBC          26 :         case T_GroupingFunc:
 2885 andres                   8490 ECB             :             {
 2885 andres                   8491 CBC          26 :                 GroupingFunc *gexpr = (GroupingFunc *) node;
 2885 andres                   8492 ECB             : 
 2885 andres                   8493 GIC          26 :                 appendStringInfoString(buf, "GROUPING(");
                               8494              26 :                 get_rule_expr((Node *) gexpr->args, context, true);
                               8495              26 :                 appendStringInfoChar(buf, ')');
                               8496                 :             }
                               8497              26 :             break;
                               8498                 : 
 5215 tgl                      8499             117 :         case T_WindowFunc:
                               8500             117 :             get_windowfunc_expr((WindowFunc *) node, context);
                               8501             117 :             break;
                               8502                 : 
 1528 alvherre                 8503 CBC          98 :         case T_SubscriptingRef:
                               8504                 :             {
 1528 alvherre                 8505 GIC          98 :                 SubscriptingRef *sbsref = (SubscriptingRef *) node;
                               8506                 :                 bool        need_parens;
                               8507                 : 
                               8508                 :                 /*
                               8509                 :                  * If the argument is a CaseTestExpr, we must be inside a
                               8510                 :                  * FieldStore, ie, we are assigning to an element of an array
                               8511                 :                  * within a composite column.  Since we already punted on
                               8512                 :                  * displaying the FieldStore's target information, just punt
 4790 bruce                    8513 ECB             :                  * here too, and display only the assignment source
 4798 tgl                      8514                 :                  * expression.
                               8515                 :                  */
 1528 alvherre                 8516 GIC          98 :                 if (IsA(sbsref->refexpr, CaseTestExpr))
                               8517                 :                 {
 1528 alvherre                 8518 UIC           0 :                     Assert(sbsref->refassgnexpr);
                               8519               0 :                     get_rule_expr((Node *) sbsref->refassgnexpr,
 4798 tgl                      8520 ECB             :                                   context, showimplicit);
 4798 tgl                      8521 UIC           0 :                     break;
                               8522                 :                 }
 4798 tgl                      8523 ECB             : 
                               8524                 :                 /*
 6797 bruce                    8525                 :                  * Parenthesize the argument unless it's a simple Var or a
 1528 alvherre                 8526                 :                  * FieldSelect.  (In particular, if it's another
                               8527                 :                  * SubscriptingRef, we *must* parenthesize to avoid
                               8528                 :                  * confusion.)
 8275 tgl                      8529                 :                  */
 1528 alvherre                 8530 GIC         154 :                 need_parens = !IsA(sbsref->refexpr, Var) &&
 1528 alvherre                 8531 CBC          56 :                     !IsA(sbsref->refexpr, FieldSelect);
 7306 tgl                      8532 GIC          98 :                 if (need_parens)
 7306 tgl                      8533 CBC          41 :                     appendStringInfoChar(buf, '(');
 1528 alvherre                 8534              98 :                 get_rule_expr((Node *) sbsref->refexpr, context, showimplicit);
 7306 tgl                      8535 GIC          98 :                 if (need_parens)
 7306 tgl                      8536 CBC          41 :                     appendStringInfoChar(buf, ')');
                               8537                 : 
 6878 tgl                      8538 ECB             :                 /*
 4790 bruce                    8539                 :                  * If there's a refassgnexpr, we want to print the node in the
 1528 alvherre                 8540                 :                  * format "container[subscripts] := refassgnexpr".  This is
                               8541                 :                  * not legal SQL, so decompilation of INSERT or UPDATE
                               8542                 :                  * statements should always use processIndirection as part of
                               8543                 :                  * the statement-level syntax.  We should only see this when
 4790 bruce                    8544                 :                  * EXPLAIN tries to print the targetlist of a plan resulting
                               8545                 :                  * from such a statement.
 6878 tgl                      8546                 :                  */
 1528 alvherre                 8547 CBC          98 :                 if (sbsref->refassgnexpr)
                               8548                 :                 {
 4790 bruce                    8549 ECB             :                     Node       *refassgnexpr;
 4798 tgl                      8550                 : 
                               8551                 :                     /*
 4790 bruce                    8552                 :                      * Use processIndirection to print this node's subscripts
                               8553                 :                      * as well as any additional field selections or
                               8554                 :                      * subscripting in immediate descendants.  It returns the
                               8555                 :                      * RHS expr that is actually being "assigned".
                               8556                 :                      */
 2440 tgl                      8557 CBC           6 :                     refassgnexpr = processIndirection(node, context);
 4798 tgl                      8558 GIC           6 :                     appendStringInfoString(buf, " := ");
 4798 tgl                      8559 CBC           6 :                     get_rule_expr(refassgnexpr, context, showimplicit);
                               8560                 :                 }
 4798 tgl                      8561 ECB             :                 else
                               8562                 :                 {
 1528 alvherre                 8563                 :                     /* Just an ordinary container fetch, so print subscripts */
 1528 alvherre                 8564 CBC          92 :                     printSubscripts(sbsref, context);
 4798 tgl                      8565 ECB             :                 }
                               8566                 :             }
 7423 tgl                      8567 CBC          98 :             break;
                               8568                 : 
                               8569            5662 :         case T_FuncExpr:
 7423 tgl                      8570 GIC        5662 :             get_func_expr((FuncExpr *) node, context, showimplicit);
 7423 tgl                      8571 CBC        5662 :             break;
 7423 tgl                      8572 ECB             : 
 4931 tgl                      8573 CBC           9 :         case T_NamedArgExpr:
 4931 tgl                      8574 ECB             :             {
 4931 tgl                      8575 GIC           9 :                 NamedArgExpr *na = (NamedArgExpr *) node;
 4931 tgl                      8576 ECB             : 
 2900 rhaas                    8577 CBC           9 :                 appendStringInfo(buf, "%s => ", quote_identifier(na->name));
 4931 tgl                      8578               9 :                 get_rule_expr((Node *) na->arg, context, showimplicit);
 4931 tgl                      8579 ECB             :             }
 4931 tgl                      8580 GIC           9 :             break;
                               8581                 : 
 7423                          8582           24672 :         case T_OpExpr:
 7423 tgl                      8583 CBC       24672 :             get_oper_expr((OpExpr *) node, context);
                               8584           24672 :             break;
                               8585                 : 
 7423 tgl                      8586 GIC           9 :         case T_DistinctExpr:
                               8587                 :             {
                               8588               9 :                 DistinctExpr *expr = (DistinctExpr *) node;
                               8589               9 :                 List       *args = expr->args;
 6892 neilc                    8590               9 :                 Node       *arg1 = (Node *) linitial(args);
 7224 tgl                      8591               9 :                 Node       *arg2 = (Node *) lsecond(args);
                               8592                 : 
 7193                          8593               9 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    8594               6 :                     appendStringInfoChar(buf, '(');
 7193 tgl                      8595               9 :                 get_rule_expr_paren(arg1, context, true, node);
 3447 rhaas                    8596               9 :                 appendStringInfoString(buf, " IS DISTINCT FROM ");
 7193 tgl                      8597               9 :                 get_rule_expr_paren(arg2, context, true, node);
 7193 tgl                      8598 CBC           9 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    8599               6 :                     appendStringInfoChar(buf, ')');
 7224 tgl                      8600 ECB             :             }
 7224 tgl                      8601 GIC           9 :             break;
                               8602                 : 
 4404 tgl                      8603 CBC          10 :         case T_NullIfExpr:
 4404 tgl                      8604 ECB             :             {
 4404 tgl                      8605 CBC          10 :                 NullIfExpr *nullifexpr = (NullIfExpr *) node;
                               8606                 : 
 3447 rhaas                    8607              10 :                 appendStringInfoString(buf, "NULLIF(");
 4404 tgl                      8608 GIC          10 :                 get_rule_expr((Node *) nullifexpr->args, context, true);
 4404 tgl                      8609 CBC          10 :                 appendStringInfoChar(buf, ')');
                               8610                 :             }
                               8611              10 :             break;
 4404 tgl                      8612 ECB             : 
 7224 tgl                      8613 GIC        1186 :         case T_ScalarArrayOpExpr:
                               8614                 :             {
 7224 tgl                      8615 CBC        1186 :                 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
 7224 tgl                      8616 GIC        1186 :                 List       *args = expr->args;
 6892 neilc                    8617 CBC        1186 :                 Node       *arg1 = (Node *) linitial(args);
 7224 tgl                      8618            1186 :                 Node       *arg2 = (Node *) lsecond(args);
 7224 tgl                      8619 ECB             : 
 7193 tgl                      8620 CBC        1186 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    8621 GIC        1180 :                     appendStringInfoChar(buf, '(');
 7193 tgl                      8622 CBC        1186 :                 get_rule_expr_paren(arg1, context, true, node);
 7224 tgl                      8623 GIC        1186 :                 appendStringInfo(buf, " %s %s (",
 7224 tgl                      8624 ECB             :                                  generate_operator_name(expr->opno,
                               8625                 :                                                         exprType(arg1),
                               8626                 :                                                         get_base_element_type(exprType(arg2))),
 7224 tgl                      8627 GIC        1186 :                                  expr->useOr ? "ANY" : "ALL");
 7193 tgl                      8628 CBC        1186 :                 get_rule_expr_paren(arg2, context, true, node);
 2544 tgl                      8629 ECB             : 
                               8630                 :                 /*
                               8631                 :                  * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
                               8632                 :                  * a bare sub-SELECT.  Since we're here, the sub-SELECT must
                               8633                 :                  * be meant as a scalar sub-SELECT yielding an array value to
                               8634                 :                  * be used in ScalarArrayOpExpr; but the grammar will
                               8635                 :                  * preferentially interpret such a construct as an ANY/ALL
                               8636                 :                  * SubLink.  To prevent misparsing the output that way, insert
                               8637                 :                  * a dummy coercion (which will be stripped by parse analysis,
                               8638                 :                  * so no inefficiency is added in dump and reload).  This is
                               8639                 :                  * indeed most likely what the user wrote to get the construct
                               8640                 :                  * accepted in the first place.
                               8641                 :                  */
 2544 tgl                      8642 GIC        1186 :                 if (IsA(arg2, SubLink) &&
 2544 tgl                      8643 CBC           3 :                     ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
                               8644               3 :                     appendStringInfo(buf, "::%s",
 2544 tgl                      8645 ECB             :                                      format_type_with_typemod(exprType(arg2),
                               8646                 :                                                               exprTypmod(arg2)));
 7193 tgl                      8647 CBC        1186 :                 appendStringInfoChar(buf, ')');
                               8648            1186 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    8649            1180 :                     appendStringInfoChar(buf, ')');
 8986 bruce                    8650 ECB             :             }
 8986 bruce                    8651 CBC        1186 :             break;
                               8652                 : 
 7423 tgl                      8653            4632 :         case T_BoolExpr:
 7423 tgl                      8654 ECB             :             {
 7423 tgl                      8655 CBC        4632 :                 BoolExpr   *expr = (BoolExpr *) node;
 6892 neilc                    8656 GIC        4632 :                 Node       *first_arg = linitial(expr->args);
  923 tgl                      8657 EUB             :                 ListCell   *arg;
 7423                          8658                 : 
 7423 tgl                      8659 GIC        4632 :                 switch (expr->boolop)
                               8660                 :                 {
                               8661            3772 :                     case AND_EXPR:
 7193 tgl                      8662 CBC        3772 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8663 GIC        3739 :                             appendStringInfoChar(buf, '(');
 6892 neilc                    8664 CBC        3772 :                         get_rule_expr_paren(first_arg, context,
 7193 tgl                      8665 ECB             :                                             false, node);
  923 tgl                      8666 CBC        8553 :                         for_each_from(arg, expr->args, 1)
                               8667                 :                         {
 3447 rhaas                    8668            4781 :                             appendStringInfoString(buf, " AND ");
 6892 neilc                    8669 GIC        4781 :                             get_rule_expr_paren((Node *) lfirst(arg), context,
 7193 tgl                      8670 ECB             :                                                 false, node);
                               8671                 :                         }
 7193 tgl                      8672 GIC        3772 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8673            3739 :                             appendStringInfoChar(buf, ')');
 7423 tgl                      8674            3772 :                         break;
                               8675                 : 
                               8676             737 :                     case OR_EXPR:
 7193                          8677             737 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8678 CBC         731 :                             appendStringInfoChar(buf, '(');
 6892 neilc                    8679             737 :                         get_rule_expr_paren(first_arg, context,
                               8680                 :                                             false, node);
  923 tgl                      8681            1759 :                         for_each_from(arg, expr->args, 1)
                               8682                 :                         {
 3447 rhaas                    8683            1022 :                             appendStringInfoString(buf, " OR ");
 6892 neilc                    8684 GIC        1022 :                             get_rule_expr_paren((Node *) lfirst(arg), context,
 7193 tgl                      8685 EUB             :                                                 false, node);
                               8686                 :                         }
 7193 tgl                      8687 GBC         737 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8688 GIC         731 :                             appendStringInfoChar(buf, ')');
 7423 tgl                      8689             737 :                         break;
                               8690                 : 
                               8691             123 :                     case NOT_EXPR:
 7193                          8692             123 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8693             117 :                             appendStringInfoChar(buf, '(');
 3447 rhaas                    8694             123 :                         appendStringInfoString(buf, "NOT ");
 6892 neilc                    8695             123 :                         get_rule_expr_paren(first_arg, context,
 7193 tgl                      8696 EUB             :                                             false, node);
 7193 tgl                      8697 GBC         123 :                         if (!PRETTY_PAREN(context))
 7188 bruce                    8698 GIC         117 :                             appendStringInfoChar(buf, ')');
 7423 tgl                      8699 GBC         123 :                         break;
                               8700                 : 
 7423 tgl                      8701 UBC           0 :                     default:
 7196                          8702               0 :                         elog(ERROR, "unrecognized boolop: %d",
                               8703                 :                              (int) expr->boolop);
 7423 tgl                      8704 EUB             :                 }
                               8705                 :             }
 7423 tgl                      8706 GBC        4632 :             break;
                               8707                 : 
                               8708             191 :         case T_SubLink:
 7423 tgl                      8709 GIC         191 :             get_sublink_expr((SubLink *) node, context);
 7423 tgl                      8710 GBC         191 :             break;
                               8711                 : 
 7421 tgl                      8712 CBC         230 :         case T_SubPlan:
                               8713                 :             {
 5050 bruce                    8714             230 :                 SubPlan    *subplan = (SubPlan *) node;
 5117 tgl                      8715 ECB             : 
 7423                          8716                 :                 /*
                               8717                 :                  * We cannot see an already-planned subplan in rule deparsing,
                               8718                 :                  * only while EXPLAINing a query plan.  We don't try to
                               8719                 :                  * reconstruct the original SQL, just reference the subplan
                               8720                 :                  * that appears elsewhere in EXPLAIN's result.
                               8721                 :                  */
 5117 tgl                      8722 GIC         230 :                 if (subplan->useHashTable)
                               8723              58 :                     appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
                               8724                 :                 else
                               8725             172 :                     appendStringInfo(buf, "(%s)", subplan->plan_name);
 7423 tgl                      8726 ECB             :             }
 7423 tgl                      8727 CBC         230 :             break;
 7423 tgl                      8728 ECB             : 
 5343 tgl                      8729 LBC           0 :         case T_AlternativeSubPlan:
 5117 tgl                      8730 ECB             :             {
 5117 tgl                      8731 LBC           0 :                 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
 5117 tgl                      8732 ECB             :                 ListCell   *lc;
                               8733                 : 
                               8734                 :                 /*
                               8735                 :                  * This case cannot be reached in normal usage, since no
                               8736                 :                  * AlternativeSubPlan can appear either in parsetrees or
  924                          8737                 :                  * finished plan trees.  We keep it just in case somebody
                               8738                 :                  * wants to use this code to print planner data structures.
                               8739                 :                  */
 3447 rhaas                    8740 UIC           0 :                 appendStringInfoString(buf, "(alternatives: ");
 5117 tgl                      8741 LBC           0 :                 foreach(lc, asplan->subplans)
                               8742                 :                 {
 2190                          8743               0 :                     SubPlan    *splan = lfirst_node(SubPlan, lc);
                               8744                 : 
 5117                          8745               0 :                     if (splan->useHashTable)
 5117 tgl                      8746 UIC           0 :                         appendStringInfo(buf, "hashed %s", splan->plan_name);
                               8747                 :                     else
 3447 rhaas                    8748               0 :                         appendStringInfoString(buf, splan->plan_name);
 1364 tgl                      8749               0 :                     if (lnext(asplan->subplans, lc))
 3447 rhaas                    8750               0 :                         appendStringInfoString(buf, " or ");
                               8751                 :                 }
                               8752               0 :                 appendStringInfoChar(buf, ')');
                               8753                 :             }
 5343 tgl                      8754               0 :             break;
                               8755                 : 
 8279 tgl                      8756 GIC         304 :         case T_FieldSelect:
                               8757                 :             {
                               8758             304 :                 FieldSelect *fselect = (FieldSelect *) node;
 6522                          8759             304 :                 Node       *arg = (Node *) fselect->arg;
                               8760             304 :                 int         fno = fselect->fieldnum;
                               8761                 :                 const char *fieldname;
                               8762                 :                 bool        need_parens;
                               8763                 : 
                               8764                 :                 /*
                               8765                 :                  * Parenthesize the argument unless it's an SubscriptingRef or
                               8766                 :                  * another FieldSelect.  Note in particular that it would be
 6385 bruce                    8767 ECB             :                  * WRONG to not parenthesize a Var argument; simplicity is not
                               8768                 :                  * the issue here, having the right number of names is.
 7804 tgl                      8769                 :                  */
 1528 alvherre                 8770 CBC         590 :                 need_parens = !IsA(arg, SubscriptingRef) &&
                               8771             286 :                     !IsA(arg, FieldSelect);
 6878 tgl                      8772             304 :                 if (need_parens)
 6878 tgl                      8773 GIC         286 :                     appendStringInfoChar(buf, '(');
 6522 tgl                      8774 CBC         304 :                 get_rule_expr(arg, context, true);
 6878 tgl                      8775 GIC         304 :                 if (need_parens)
 6878 tgl                      8776 CBC         286 :                     appendStringInfoChar(buf, ')');
                               8777                 : 
 6522 tgl                      8778 ECB             :                 /*
 5889                          8779                 :                  * Get and print the field name.
                               8780                 :                  */
 5889 tgl                      8781 CBC         304 :                 fieldname = get_name_for_var_field((Var *) arg, fno,
 5889 tgl                      8782 ECB             :                                                    0, context);
 7193 tgl                      8783 GIC         304 :                 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
                               8784                 :             }
 8279 tgl                      8785 CBC         304 :             break;
                               8786                 : 
 6878 tgl                      8787 GIC           3 :         case T_FieldStore:
                               8788                 :             {
 4798 tgl                      8789 CBC           3 :                 FieldStore *fstore = (FieldStore *) node;
                               8790                 :                 bool        need_parens;
                               8791                 : 
                               8792                 :                 /*
                               8793                 :                  * There is no good way to represent a FieldStore as real SQL,
                               8794                 :                  * so decompilation of INSERT or UPDATE statements should
 4798 tgl                      8795 ECB             :                  * always use processIndirection as part of the
                               8796                 :                  * statement-level syntax.  We should only get here when
                               8797                 :                  * EXPLAIN tries to print the targetlist of a plan resulting
                               8798                 :                  * from such a statement.  The plan case is even harder than
                               8799                 :                  * ordinary rules would be, because the planner tries to
                               8800                 :                  * collapse multiple assignments to the same field or subfield
                               8801                 :                  * into one FieldStore; so we can see a list of target fields
                               8802                 :                  * not just one, and the arguments could be FieldStores
 3260 bruce                    8803                 :                  * themselves.  We don't bother to try to print the target
                               8804                 :                  * field names; we just print the source arguments, with a
                               8805                 :                  * ROW() around them if there's more than one.  This isn't
 4798 tgl                      8806                 :                  * terribly complete, but it's probably good enough for
                               8807                 :                  * EXPLAIN's purposes; especially since anything more would be
                               8808                 :                  * either hopelessly confusing or an even poorer
                               8809                 :                  * representation of what the plan is actually doing.
                               8810                 :                  */
 4798 tgl                      8811 GIC           3 :                 need_parens = (list_length(fstore->newvals) != 1);
                               8812               3 :                 if (need_parens)
                               8813               3 :                     appendStringInfoString(buf, "ROW(");
                               8814               3 :                 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
                               8815               3 :                 if (need_parens)
 4798 tgl                      8816 CBC           3 :                     appendStringInfoChar(buf, ')');
                               8817                 :             }
 6878                          8818               3 :             break;
                               8819                 : 
 8449                          8820            1064 :         case T_RelabelType:
 8449 tgl                      8821 ECB             :             {
 8449 tgl                      8822 GIC        1064 :                 RelabelType *relabel = (RelabelType *) node;
 7188 bruce                    8823 CBC        1064 :                 Node       *arg = (Node *) relabel->arg;
 8449 tgl                      8824 ECB             : 
 7507 tgl                      8825 GIC        1064 :                 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
                               8826            1001 :                     !showimplicit)
 7508 tgl                      8827 EUB             :                 {
                               8828                 :                     /* don't show the implicit cast */
 6871 tgl                      8829 GIC          30 :                     get_rule_expr_paren(arg, context, false, node);
                               8830                 :                 }
 7508 tgl                      8831 ECB             :                 else
                               8832                 :                 {
 5867 tgl                      8833 GIC        1034 :                     get_coercion_expr(arg, context,
                               8834                 :                                       relabel->resulttype,
                               8835                 :                                       relabel->resulttypmod,
                               8836                 :                                       node);
 7508 tgl                      8837 ECB             :                 }
                               8838                 :             }
 8449 tgl                      8839 CBC        1064 :             break;
                               8840                 : 
 5787                          8841             262 :         case T_CoerceViaIO:
 5787 tgl                      8842 ECB             :             {
 5787 tgl                      8843 GIC         262 :                 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
 5787 tgl                      8844 CBC         262 :                 Node       *arg = (Node *) iocoerce->arg;
 5787 tgl                      8845 ECB             : 
 5787 tgl                      8846 GIC         262 :                 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
                               8847               6 :                     !showimplicit)
 5787 tgl                      8848 ECB             :                 {
                               8849                 :                     /* don't show the implicit cast */
 5787 tgl                      8850 GIC           6 :                     get_rule_expr_paren(arg, context, false, node);
                               8851                 :                 }
 5787 tgl                      8852 ECB             :                 else
                               8853                 :                 {
 5787 tgl                      8854 GIC         256 :                     get_coercion_expr(arg, context,
                               8855                 :                                       iocoerce->resulttype,
                               8856                 :                                       -1,
 5787 tgl                      8857 ECB             :                                       node);
                               8858                 :                 }
                               8859                 :             }
 5787 tgl                      8860 GIC         262 :             break;
 5787 tgl                      8861 ECB             : 
 5857 tgl                      8862 CBC          15 :         case T_ArrayCoerceExpr:
                               8863                 :             {
                               8864              15 :                 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
                               8865              15 :                 Node       *arg = (Node *) acoerce->arg;
 5857 tgl                      8866 ECB             : 
 5857 tgl                      8867 CBC          15 :                 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
 5857 tgl                      8868 GIC          15 :                     !showimplicit)
 5857 tgl                      8869 ECB             :                 {
                               8870                 :                     /* don't show the implicit cast */
 5857 tgl                      8871 UIC           0 :                     get_rule_expr_paren(arg, context, false, node);
 5857 tgl                      8872 ECB             :                 }
                               8873                 :                 else
                               8874                 :                 {
 5857 tgl                      8875 GIC          15 :                     get_coercion_expr(arg, context,
 5857 tgl                      8876 ECB             :                                       acoerce->resulttype,
                               8877                 :                                       acoerce->resulttypmod,
                               8878                 :                                       node);
                               8879                 :                 }
                               8880                 :             }
 5857 tgl                      8881 CBC          15 :             break;
                               8882                 : 
 6693                          8883              45 :         case T_ConvertRowtypeExpr:
 6693 tgl                      8884 ECB             :             {
 6693 tgl                      8885 GIC          45 :                 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
 6693 tgl                      8886 CBC          45 :                 Node       *arg = (Node *) convert->arg;
                               8887                 : 
                               8888              45 :                 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
                               8889              42 :                     !showimplicit)
                               8890                 :                 {
 6693 tgl                      8891 ECB             :                     /* don't show the implicit cast */
 6693 tgl                      8892 GIC          12 :                     get_rule_expr_paren(arg, context, false, node);
                               8893                 :                 }
                               8894                 :                 else
                               8895                 :                 {
 5867                          8896              33 :                     get_coercion_expr(arg, context,
                               8897                 :                                       convert->resulttype, -1,
                               8898                 :                                       node);
                               8899                 :                 }
                               8900                 :             }
 6693                          8901              45 :             break;
                               8902                 : 
 4412                          8903              48 :         case T_CollateExpr:
                               8904                 :             {
 4412 tgl                      8905 CBC          48 :                 CollateExpr *collate = (CollateExpr *) node;
 4412 tgl                      8906 GIC          48 :                 Node       *arg = (Node *) collate->arg;
 4412 tgl                      8907 ECB             : 
 4412 tgl                      8908 GIC          48 :                 if (!PRETTY_PAREN(context))
 4412 tgl                      8909 CBC          48 :                     appendStringInfoChar(buf, '(');
                               8910              48 :                 get_rule_expr_paren(arg, context, showimplicit, node);
 4412 tgl                      8911 GIC          48 :                 appendStringInfo(buf, " COLLATE %s",
 4412 tgl                      8912 ECB             :                                  generate_collation_name(collate->collOid));
 4412 tgl                      8913 GIC          48 :                 if (!PRETTY_PAREN(context))
                               8914              48 :                     appendStringInfoChar(buf, ')');
                               8915                 :             }
 4412 tgl                      8916 CBC          48 :             break;
 4412 tgl                      8917 ECB             : 
 8625 tgl                      8918 CBC         153 :         case T_CaseExpr:
                               8919                 :             {
                               8920             153 :                 CaseExpr   *caseexpr = (CaseExpr *) node;
 6892 neilc                    8921 ECB             :                 ListCell   *temp;
 8625 tgl                      8922                 : 
 7193 tgl                      8923 GIC         153 :                 appendContextKeyword(context, "CASE",
 7193 tgl                      8924 ECB             :                                      0, PRETTYINDENT_VAR, 0);
 6962 tgl                      8925 CBC         153 :                 if (caseexpr->arg)
 6962 tgl                      8926 ECB             :                 {
 6962 tgl                      8927 GIC          51 :                     appendStringInfoChar(buf, ' ');
 6962 tgl                      8928 CBC          51 :                     get_rule_expr((Node *) caseexpr->arg, context, true);
 6962 tgl                      8929 ECB             :                 }
 8625 tgl                      8930 CBC         632 :                 foreach(temp, caseexpr->args)
 8625 tgl                      8931 ECB             :                 {
 8625 tgl                      8932 GIC         479 :                     CaseWhen   *when = (CaseWhen *) lfirst(temp);
 6329                          8933             479 :                     Node       *w = (Node *) when->expr;
 8625 tgl                      8934 ECB             : 
 6962 tgl                      8935 GIC         479 :                     if (caseexpr->arg)
 6962 tgl                      8936 EUB             :                     {
                               8937                 :                         /*
                               8938                 :                          * The parser should have produced WHEN clauses of the
                               8939                 :                          * form "CaseTestExpr = RHS", possibly with an
                               8940                 :                          * implicit coercion inserted above the CaseTestExpr.
                               8941                 :                          * For accurate decompilation of rules it's essential
                               8942                 :                          * that we show just the RHS.  However in an
                               8943                 :                          * expression that's been through the optimizer, the
                               8944                 :                          * WHEN clause could be almost anything (since the
 4336                          8945                 :                          * equality operator could have been expanded into an
                               8946                 :                          * inline function).  If we don't recognize the form
                               8947                 :                          * of the WHEN clause, just punt and display it as-is.
                               8948                 :                          */
 6329 tgl                      8949 CBC         197 :                         if (IsA(w, OpExpr))
                               8950                 :                         {
 5156                          8951             197 :                             List       *args = ((OpExpr *) w)->args;
                               8952                 : 
 4336                          8953             197 :                             if (list_length(args) == 2 &&
                               8954             197 :                                 IsA(strip_implicit_coercions(linitial(args)),
 4336 tgl                      8955 ECB             :                                     CaseTestExpr))
 4336 tgl                      8956 GIC         197 :                                 w = (Node *) lsecond(args);
                               8957                 :                         }
                               8958                 :                     }
                               8959                 : 
                               8960             479 :                     if (!PRETTY_INDENT(context))
                               8961              41 :                         appendStringInfoChar(buf, ' ');
 4336 tgl                      8962 CBC         479 :                     appendContextKeyword(context, "WHEN ",
 4336 tgl                      8963 ECB             :                                          0, 0, 0);
 4336 tgl                      8964 GIC         479 :                     get_rule_expr(w, context, false);
 3447 rhaas                    8965             479 :                     appendStringInfoString(buf, " THEN ");
 7423 tgl                      8966 CBC         479 :                     get_rule_expr((Node *) when->result, context, true);
                               8967                 :                 }
 7193                          8968             153 :                 if (!PRETTY_INDENT(context))
 7188 bruce                    8969 GIC          36 :                     appendStringInfoChar(buf, ' ');
 7193 tgl                      8970 CBC         153 :                 appendContextKeyword(context, "ELSE ",
 7193 tgl                      8971 ECB             :                                      0, 0, 0);
 7423 tgl                      8972 GIC         153 :                 get_rule_expr((Node *) caseexpr->defresult, context, true);
 7193                          8973             153 :                 if (!PRETTY_INDENT(context))
 7188 bruce                    8974              36 :                     appendStringInfoChar(buf, ' ');
 7193 tgl                      8975             153 :                 appendContextKeyword(context, "END",
                               8976                 :                                      -PRETTYINDENT_VAR, 0, 0);
                               8977                 :             }
 8986 bruce                    8978             153 :             break;
                               8979                 : 
 4336 tgl                      8980 UIC           0 :         case T_CaseTestExpr:
 4336 tgl                      8981 ECB             :             {
                               8982                 :                 /*
                               8983                 :                  * Normally we should never get here, since for expressions
                               8984                 :                  * that can contain this node type we attempt to avoid
                               8985                 :                  * recursing to it.  But in an optimized expression we might
                               8986                 :                  * be unable to avoid that (see comments for CaseExpr).  If we
                               8987                 :                  * do see one, print it as CASE_TEST_EXPR.
                               8988                 :                  */
 3447 rhaas                    8989 UIC           0 :                 appendStringInfoString(buf, "CASE_TEST_EXPR");
                               8990                 :             }
 4336 tgl                      8991 LBC           0 :             break;
 4336 tgl                      8992 ECB             : 
 7306 tgl                      8993 CBC         181 :         case T_ArrayExpr:
 7306 tgl                      8994 ECB             :             {
 7188 bruce                    8995 GIC         181 :                 ArrayExpr  *arrayexpr = (ArrayExpr *) node;
 7306 tgl                      8996 ECB             : 
 3447 rhaas                    8997 GIC         181 :                 appendStringInfoString(buf, "ARRAY[");
 6758 tgl                      8998 CBC         181 :                 get_rule_expr((Node *) arrayexpr->elements, context, true);
                               8999             181 :                 appendStringInfoChar(buf, ']');
                               9000                 : 
 5224 tgl                      9001 ECB             :                 /*
                               9002                 :                  * If the array isn't empty, we assume its elements are
                               9003                 :                  * coerced to the desired type.  If it's empty, though, we
                               9004                 :                  * need an explicit coercion to the array type.
                               9005                 :                  */
 5224 tgl                      9006 CBC         181 :                 if (arrayexpr->elements == NIL)
 5224 tgl                      9007 GIC           3 :                     appendStringInfo(buf, "::%s",
 2118 tgl                      9008 ECB             :                                      format_type_with_typemod(arrayexpr->array_typeid, -1));
                               9009                 :             }
 7306 tgl                      9010 CBC         181 :             break;
                               9011                 : 
 6908 tgl                      9012 GBC          90 :         case T_RowExpr:
                               9013                 :             {
 6797 bruce                    9014              90 :                 RowExpr    *rowexpr = (RowExpr *) node;
 6809 tgl                      9015              90 :                 TupleDesc   tupdesc = NULL;
 6892 neilc                    9016 EUB             :                 ListCell   *arg;
                               9017                 :                 int         i;
 6908 tgl                      9018                 :                 char       *sep;
                               9019                 : 
                               9020                 :                 /*
 6385 bruce                    9021 ECB             :                  * If it's a named type and not RECORD, we may have to skip
                               9022                 :                  * dropped columns and/or claim there are NULLs for added
                               9023                 :                  * columns.
 6809 tgl                      9024                 :                  */
 6809 tgl                      9025 CBC          90 :                 if (rowexpr->row_typeid != RECORDOID)
                               9026                 :                 {
 6809 tgl                      9027 GIC          24 :                     tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
 6809 tgl                      9028 CBC          24 :                     Assert(list_length(rowexpr->args) <= tupdesc->natts);
                               9029                 :                 }
 6809 tgl                      9030 ECB             : 
                               9031                 :                 /*
 6385 bruce                    9032                 :                  * SQL99 allows "ROW" to be omitted when there is more than
                               9033                 :                  * one column, but for simplicity we always print it.
                               9034                 :                  */
 3447 rhaas                    9035 GIC          90 :                 appendStringInfoString(buf, "ROW(");
 6908 tgl                      9036              90 :                 sep = "";
 6809                          9037              90 :                 i = 0;
 6908                          9038             258 :                 foreach(arg, rowexpr->args)
                               9039                 :                 {
 6908 tgl                      9040 CBC         168 :                     Node       *e = (Node *) lfirst(arg);
 6908 tgl                      9041 ECB             : 
 6809 tgl                      9042 GIC         168 :                     if (tupdesc == NULL ||
 2058 andres                   9043              45 :                         !TupleDescAttr(tupdesc, i)->attisdropped)
                               9044                 :                     {
 6553 neilc                    9045             168 :                         appendStringInfoString(buf, sep);
                               9046                 :                         /* Whole-row Vars need special treatment here */
 2702 tgl                      9047             168 :                         get_rule_expr_toplevel(e, context, true);
 6809                          9048             168 :                         sep = ", ";
                               9049                 :                     }
 6809 tgl                      9050 CBC         168 :                     i++;
 6809 tgl                      9051 ECB             :                 }
 6809 tgl                      9052 CBC          90 :                 if (tupdesc != NULL)
 6809 tgl                      9053 ECB             :                 {
 6809 tgl                      9054 CBC          24 :                     while (i < tupdesc->natts)
 6809 tgl                      9055 ECB             :                     {
 2058 andres                   9056 UIC           0 :                         if (!TupleDescAttr(tupdesc, i)->attisdropped)
 6809 tgl                      9057 ECB             :                         {
 6553 neilc                    9058 UIC           0 :                             appendStringInfoString(buf, sep);
 3447 rhaas                    9059 LBC           0 :                             appendStringInfoString(buf, "NULL");
 6809 tgl                      9060 UIC           0 :                             sep = ", ";
 6809 tgl                      9061 ECB             :                         }
 6809 tgl                      9062 UIC           0 :                         i++;
 6809 tgl                      9063 ECB             :                     }
 6141                          9064                 : 
 6141 tgl                      9065 CBC          24 :                     ReleaseTupleDesc(tupdesc);
                               9066                 :                 }
 3447 rhaas                    9067              90 :                 appendStringInfoChar(buf, ')');
 6908 tgl                      9068 GIC          90 :                 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
 6908 tgl                      9069 CBC          18 :                     appendStringInfo(buf, "::%s",
                               9070                 :                                      format_type_with_typemod(rowexpr->row_typeid, -1));
 6908 tgl                      9071 ECB             :             }
 6908 tgl                      9072 GIC          90 :             break;
 6908 tgl                      9073 ECB             : 
 6311 tgl                      9074 GIC          33 :         case T_RowCompareExpr:
 6311 tgl                      9075 ECB             :             {
 6311 tgl                      9076 CBC          33 :                 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
 6311 tgl                      9077 ECB             : 
                               9078                 :                 /*
                               9079                 :                  * SQL99 allows "ROW" to be omitted when there is more than
  451                          9080                 :                  * one column, but for simplicity we always print it.  Within
                               9081                 :                  * a ROW expression, whole-row Vars need special treatment, so
                               9082                 :                  * use get_rule_list_toplevel.
 6311                          9083                 :                  */
 3447 rhaas                    9084 GIC          33 :                 appendStringInfoString(buf, "(ROW(");
  451 tgl                      9085 CBC          33 :                 get_rule_list_toplevel(rcexpr->largs, context, true);
                               9086                 : 
 6311 tgl                      9087 ECB             :                 /*
                               9088                 :                  * We assume that the name of the first-column operator will
 6031 bruce                    9089                 :                  * do for all the rest too.  This is definitely open to
                               9090                 :                  * failure, eg if some but not all operators were renamed
                               9091                 :                  * since the construct was parsed, but there seems no way to
                               9092                 :                  * be perfect.
                               9093                 :                  */
 6311 tgl                      9094 GIC          33 :                 appendStringInfo(buf, ") %s ROW(",
 2118 tgl                      9095 CBC          33 :                                  generate_operator_name(linitial_oid(rcexpr->opnos),
 2118 tgl                      9096 GIC          33 :                                                         exprType(linitial(rcexpr->largs)),
 2118 tgl                      9097 CBC          33 :                                                         exprType(linitial(rcexpr->rargs))));
  451                          9098              33 :                 get_rule_list_toplevel(rcexpr->rargs, context, true);
 3447 rhaas                    9099              33 :                 appendStringInfoString(buf, "))");
 6311 tgl                      9100 ECB             :             }
 6311 tgl                      9101 CBC          33 :             break;
 6311 tgl                      9102 ECB             : 
 7357 tgl                      9103 CBC         489 :         case T_CoalesceExpr:
 7357 tgl                      9104 ECB             :             {
 7357 tgl                      9105 CBC         489 :                 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
 7357 tgl                      9106 ECB             : 
 3447 rhaas                    9107 CBC         489 :                 appendStringInfoString(buf, "COALESCE(");
 6758 tgl                      9108             489 :                 get_rule_expr((Node *) coalesceexpr->args, context, true);
                               9109             489 :                 appendStringInfoChar(buf, ')');
 7357 tgl                      9110 ECB             :             }
 7357 tgl                      9111 CBC         489 :             break;
 7188 bruce                    9112 ECB             : 
 6496 tgl                      9113 CBC          18 :         case T_MinMaxExpr:
 6496 tgl                      9114 ECB             :             {
 6496 tgl                      9115 CBC          18 :                 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
 6496 tgl                      9116 ECB             : 
 6496 tgl                      9117 CBC          18 :                 switch (minmaxexpr->op)
 6496 tgl                      9118 EUB             :                 {
 6496 tgl                      9119 GBC           3 :                     case IS_GREATEST:
 3447 rhaas                    9120 GIC           3 :                         appendStringInfoString(buf, "GREATEST(");
 6496 tgl                      9121 CBC           3 :                         break;
 6496 tgl                      9122 GIC          15 :                     case IS_LEAST:
 3447 rhaas                    9123 CBC          15 :                         appendStringInfoString(buf, "LEAST(");
 6496 tgl                      9124 GBC          15 :                         break;
                               9125                 :                 }
 6496 tgl                      9126 CBC          18 :                 get_rule_expr((Node *) minmaxexpr->args, context, true);
 6496 tgl                      9127 GIC          18 :                 appendStringInfoChar(buf, ')');
 6496 tgl                      9128 ECB             :             }
 6496 tgl                      9129 GIC          18 :             break;
 6496 tgl                      9130 ECB             : 
 5950 tgl                      9131 GIC          72 :         case T_XmlExpr:
 5950 tgl                      9132 ECB             :             {
 5624 bruce                    9133 CBC          72 :                 XmlExpr    *xexpr = (XmlExpr *) node;
                               9134              72 :                 bool        needcomma = false;
 5950 tgl                      9135 ECB             :                 ListCell   *arg;
                               9136                 :                 ListCell   *narg;
                               9137                 :                 Const      *con;
 5950 tgl                      9138 EUB             : 
 5950 tgl                      9139 GIC          72 :                 switch (xexpr->op)
 5950 tgl                      9140 ECB             :                 {
 5950 tgl                      9141 CBC           8 :                     case IS_XMLCONCAT:
 5950 tgl                      9142 GIC           8 :                         appendStringInfoString(buf, "XMLCONCAT(");
                               9143               8 :                         break;
                               9144              16 :                     case IS_XMLELEMENT:
 5950 tgl                      9145 CBC          16 :                         appendStringInfoString(buf, "XMLELEMENT(");
 5950 tgl                      9146 GIC          16 :                         break;
 5950 tgl                      9147 CBC           8 :                     case IS_XMLFOREST:
                               9148               8 :                         appendStringInfoString(buf, "XMLFOREST(");
 5950 tgl                      9149 GIC           8 :                         break;
 5950 tgl                      9150 CBC           8 :                     case IS_XMLPARSE:
 5950 tgl                      9151 GBC           8 :                         appendStringInfoString(buf, "XMLPARSE(");
                               9152               8 :                         break;
 5950 tgl                      9153 GIC           8 :                     case IS_XMLPI:
 5950 tgl                      9154 GBC           8 :                         appendStringInfoString(buf, "XMLPI(");
                               9155               8 :                         break;
                               9156               8 :                     case IS_XMLROOT:
 5950 tgl                      9157 GIC           8 :                         appendStringInfoString(buf, "XMLROOT(");
 5950 tgl                      9158 GBC           8 :                         break;
 5909 peter_e                  9159              16 :                     case IS_XMLSERIALIZE:
                               9160              16 :                         appendStringInfoString(buf, "XMLSERIALIZE(");
 5909 peter_e                  9161 GIC          16 :                         break;
 5929 peter_e                  9162 UIC           0 :                     case IS_DOCUMENT:
 5929 peter_e                  9163 LBC           0 :                         break;
 5950 tgl                      9164 EUB             :                 }
 5909 peter_e                  9165 GBC          72 :                 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
 5909 peter_e                  9166 EUB             :                 {
 5909 peter_e                  9167 GIC          24 :                     if (xexpr->xmloption == XMLOPTION_DOCUMENT)
 5909 peter_e                  9168 UIC           0 :                         appendStringInfoString(buf, "DOCUMENT ");
 5909 peter_e                  9169 ECB             :                     else
 5909 peter_e                  9170 CBC          24 :                         appendStringInfoString(buf, "CONTENT ");
                               9171                 :                 }
 5950 tgl                      9172 GIC          72 :                 if (xexpr->name)
 5950 tgl                      9173 ECB             :                 {
 5950 tgl                      9174 GBC          24 :                     appendStringInfo(buf, "NAME %s",
 5945 peter_e                  9175 GIC          24 :                                      quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
 5950 tgl                      9176 CBC          24 :                     needcomma = true;
                               9177                 :                 }
                               9178              72 :                 if (xexpr->named_args)
                               9179                 :                 {
                               9180              16 :                     if (xexpr->op != IS_XMLFOREST)
                               9181                 :                     {
                               9182               8 :                         if (needcomma)
 5950 tgl                      9183 GIC           8 :                             appendStringInfoString(buf, ", ");
 5950 tgl                      9184 CBC           8 :                         appendStringInfoString(buf, "XMLATTRIBUTES(");
                               9185               8 :                         needcomma = false;
 5950 tgl                      9186 ECB             :                     }
 5950 tgl                      9187 GIC          56 :                     forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
                               9188                 :                     {
 5624 bruce                    9189              40 :                         Node       *e = (Node *) lfirst(arg);
                               9190              40 :                         char       *argname = strVal(lfirst(narg));
                               9191                 : 
 5950 tgl                      9192              40 :                         if (needcomma)
                               9193              24 :                             appendStringInfoString(buf, ", ");
 5950 tgl                      9194 CBC          40 :                         get_rule_expr((Node *) e, context, true);
                               9195              40 :                         appendStringInfo(buf, " AS %s",
 5945 peter_e                  9196 GIC          40 :                                          quote_identifier(map_xml_name_to_sql_identifier(argname)));
 5950 tgl                      9197 CBC          40 :                         needcomma = true;
                               9198                 :                     }
                               9199              16 :                     if (xexpr->op != IS_XMLFOREST)
                               9200               8 :                         appendStringInfoChar(buf, ')');
 5950 tgl                      9201 ECB             :                 }
 5950 tgl                      9202 CBC          72 :                 if (xexpr->args)
 5950 tgl                      9203 ECB             :                 {
 5950 tgl                      9204 CBC          64 :                     if (needcomma)
 5950 tgl                      9205 GBC          24 :                         appendStringInfoString(buf, ", ");
                               9206              64 :                     switch (xexpr->op)
                               9207                 :                     {
 5950 tgl                      9208 GIC          48 :                         case IS_XMLCONCAT:
                               9209                 :                         case IS_XMLELEMENT:
                               9210                 :                         case IS_XMLFOREST:
                               9211                 :                         case IS_XMLPI:
 5909 peter_e                  9212 ECB             :                         case IS_XMLSERIALIZE:
                               9213                 :                             /* no extra decoration needed */
 5950 tgl                      9214 CBC          48 :                             get_rule_expr((Node *) xexpr->args, context, true);
                               9215              48 :                             break;
                               9216               8 :                         case IS_XMLPARSE:
 5909 peter_e                  9217               8 :                             Assert(list_length(xexpr->args) == 2);
 5950 tgl                      9218 ECB             : 
 5950 tgl                      9219 CBC           8 :                             get_rule_expr((Node *) linitial(xexpr->args),
 5950 tgl                      9220 EUB             :                                           context, true);
                               9221                 : 
 2190 tgl                      9222 GIC           8 :                             con = lsecond_node(Const, xexpr->args);
 5950                          9223               8 :                             Assert(!con->constisnull);
                               9224               8 :                             if (DatumGetBool(con->constvalue))
 5950 tgl                      9225 LBC           0 :                                 appendStringInfoString(buf,
 2118 tgl                      9226 ECB             :                                                        " PRESERVE WHITESPACE");
                               9227                 :                             else
 5950 tgl                      9228 CBC           8 :                                 appendStringInfoString(buf,
                               9229                 :                                                        " STRIP WHITESPACE");
                               9230               8 :                             break;
 5950 tgl                      9231 GIC           8 :                         case IS_XMLROOT:
 5950 tgl                      9232 CBC           8 :                             Assert(list_length(xexpr->args) == 3);
                               9233                 : 
                               9234               8 :                             get_rule_expr((Node *) linitial(xexpr->args),
 5950 tgl                      9235 ECB             :                                           context, true);
                               9236                 : 
 5950 tgl                      9237 CBC           8 :                             appendStringInfoString(buf, ", VERSION ");
 5950 tgl                      9238 GIC           8 :                             con = (Const *) lsecond(xexpr->args);
 5950 tgl                      9239 CBC           8 :                             if (IsA(con, Const) &&
                               9240               8 :                                 con->constisnull)
                               9241               8 :                                 appendStringInfoString(buf, "NO VALUE");
 5950 tgl                      9242 ECB             :                             else
 5950 tgl                      9243 LBC           0 :                                 get_rule_expr((Node *) con, context, false);
 5950 tgl                      9244 ECB             : 
 2190 tgl                      9245 GBC           8 :                             con = lthird_node(Const, xexpr->args);
 5950                          9246               8 :                             if (con->constisnull)
 5624 bruce                    9247 EUB             :                                  /* suppress STANDALONE NO VALUE */ ;
 5950 tgl                      9248                 :                             else
 5909 peter_e                  9249                 :                             {
 5909 peter_e                  9250 GBC           8 :                                 switch (DatumGetInt32(con->constvalue))
 5909 peter_e                  9251 ECB             :                                 {
 5909 peter_e                  9252 CBC           8 :                                     case XML_STANDALONE_YES:
                               9253               8 :                                         appendStringInfoString(buf,
 2118 tgl                      9254 ECB             :                                                                ", STANDALONE YES");
 5909 peter_e                  9255 CBC           8 :                                         break;
 5909 peter_e                  9256 LBC           0 :                                     case XML_STANDALONE_NO:
 5909 peter_e                  9257 UBC           0 :                                         appendStringInfoString(buf,
 2118 tgl                      9258 EUB             :                                                                ", STANDALONE NO");
 5909 peter_e                  9259 UIC           0 :                                         break;
                               9260               0 :                                     case XML_STANDALONE_NO_VALUE:
 5909 peter_e                  9261 LBC           0 :                                         appendStringInfoString(buf,
 2118 tgl                      9262 ECB             :                                                                ", STANDALONE NO VALUE");
 5909 peter_e                  9263 UIC           0 :                                         break;
 5909 peter_e                  9264 LBC           0 :                                     default:
 5909 peter_e                  9265 UIC           0 :                                         break;
 5909 peter_e                  9266 ECB             :                                 }
                               9267                 :                             }
 5950 tgl                      9268 CBC           8 :                             break;
 5929 peter_e                  9269 LBC           0 :                         case IS_DOCUMENT:
 5929 peter_e                  9270 UIC           0 :                             get_rule_expr_paren((Node *) xexpr->args, context, false, node);
 5929 peter_e                  9271 LBC           0 :                             break;
 5950 tgl                      9272 ECB             :                     }
                               9273                 :                 }
 5909 peter_e                  9274 GIC          72 :                 if (xexpr->op == IS_XMLSERIALIZE)
 4404 tgl                      9275 CBC          16 :                     appendStringInfo(buf, " AS %s",
                               9276                 :                                      format_type_with_typemod(xexpr->type,
                               9277                 :                                                               xexpr->typmod));
 5929 peter_e                  9278 GIC          72 :                 if (xexpr->op == IS_DOCUMENT)
 5929 peter_e                  9279 LBC           0 :                     appendStringInfoString(buf, " IS DOCUMENT");
                               9280                 :                 else
 5929 peter_e                  9281 GIC          72 :                     appendStringInfoChar(buf, ')');
                               9282                 :             }
 5950 tgl                      9283              72 :             break;
                               9284                 : 
 7964 tgl                      9285 CBC         897 :         case T_NullTest:
                               9286                 :             {
 7836 bruce                    9287             897 :                 NullTest   *ntest = (NullTest *) node;
 7964 tgl                      9288 ECB             : 
 7193 tgl                      9289 CBC         897 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    9290 GIC         873 :                     appendStringInfoChar(buf, '(');
 7193 tgl                      9291 CBC         897 :                 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
 2446 tgl                      9292 ECB             : 
                               9293                 :                 /*
                               9294                 :                  * For scalar inputs, we prefer to print as IS [NOT] NULL,
                               9295                 :                  * which is shorter and traditional.  If it's a rowtype input
                               9296                 :                  * but we're applying a scalar test, must print IS [NOT]
                               9297                 :                  * DISTINCT FROM NULL to be semantically correct.
                               9298                 :                  */
 2446 tgl                      9299 CBC         897 :                 if (ntest->argisrow ||
                               9300             888 :                     !type_is_rowtype(exprType((Node *) ntest->arg)))
 7836 bruce                    9301 ECB             :                 {
 2446 tgl                      9302 GIC        1776 :                     switch (ntest->nulltesttype)
 2446 tgl                      9303 EUB             :                     {
 2446 tgl                      9304 GIC         264 :                         case IS_NULL:
                               9305             264 :                             appendStringInfoString(buf, " IS NULL");
 2446 tgl                      9306 CBC         264 :                             break;
 2446 tgl                      9307 GIC         624 :                         case IS_NOT_NULL:
 2446 tgl                      9308 GBC         624 :                             appendStringInfoString(buf, " IS NOT NULL");
 2446 tgl                      9309 GIC         624 :                             break;
 2446 tgl                      9310 UBC           0 :                         default:
 2446 tgl                      9311 UIC           0 :                             elog(ERROR, "unrecognized nulltesttype: %d",
                               9312                 :                                  (int) ntest->nulltesttype);
                               9313                 :                     }
                               9314                 :                 }
                               9315                 :                 else
 2446 tgl                      9316 EUB             :                 {
 2446 tgl                      9317 GBC           9 :                     switch (ntest->nulltesttype)
 2446 tgl                      9318 EUB             :                     {
 2446 tgl                      9319 GIC           3 :                         case IS_NULL:
 2446 tgl                      9320 GBC           3 :                             appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL");
 2446 tgl                      9321 GIC           3 :                             break;
 2446 tgl                      9322 GBC           6 :                         case IS_NOT_NULL:
 2446 tgl                      9323 GIC           6 :                             appendStringInfoString(buf, " IS DISTINCT FROM NULL");
 2446 tgl                      9324 CBC           6 :                             break;
 2446 tgl                      9325 UIC           0 :                         default:
 2446 tgl                      9326 LBC           0 :                             elog(ERROR, "unrecognized nulltesttype: %d",
                               9327                 :                                  (int) ntest->nulltesttype);
                               9328                 :                     }
                               9329                 :                 }
 7193 tgl                      9330 GIC         897 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    9331             873 :                     appendStringInfoChar(buf, ')');
                               9332                 :             }
 7964 tgl                      9333             897 :             break;
 7964 tgl                      9334 ECB             : 
 7964 tgl                      9335 CBC          36 :         case T_BooleanTest:
                               9336                 :             {
 7836 bruce                    9337 GIC          36 :                 BooleanTest *btest = (BooleanTest *) node;
                               9338                 : 
 7193 tgl                      9339              36 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    9340              36 :                     appendStringInfoChar(buf, '(');
 7193 tgl                      9341 CBC          36 :                 get_rule_expr_paren((Node *) btest->arg, context, false, node);
 7836 bruce                    9342              36 :                 switch (btest->booltesttype)
 7836 bruce                    9343 EUB             :                 {
 7836 bruce                    9344 GIC           6 :                     case IS_TRUE:
 3447 rhaas                    9345 GBC           6 :                         appendStringInfoString(buf, " IS TRUE");
 7964 tgl                      9346 GIC           6 :                         break;
 7836 bruce                    9347 CBC          12 :                     case IS_NOT_TRUE:
 3447 rhaas                    9348 GBC          12 :                         appendStringInfoString(buf, " IS NOT TRUE");
 7964 tgl                      9349 CBC          12 :                         break;
 7836 bruce                    9350 UIC           0 :                     case IS_FALSE:
 3447 rhaas                    9351 LBC           0 :                         appendStringInfoString(buf, " IS FALSE");
 7964 tgl                      9352 UBC           0 :                         break;
 7836 bruce                    9353 UIC           0 :                     case IS_NOT_FALSE:
 3447 rhaas                    9354 LBC           0 :                         appendStringInfoString(buf, " IS NOT FALSE");
 7964 tgl                      9355 UIC           0 :                         break;
 7836 bruce                    9356 CBC           9 :                     case IS_UNKNOWN:
 3447 rhaas                    9357               9 :                         appendStringInfoString(buf, " IS UNKNOWN");
 7964 tgl                      9358 GIC           9 :                         break;
 7836 bruce                    9359               9 :                     case IS_NOT_UNKNOWN:
 3447 rhaas                    9360               9 :                         appendStringInfoString(buf, " IS NOT UNKNOWN");
 7964 tgl                      9361 CBC           9 :                         break;
 7836 bruce                    9362 UIC           0 :                     default:
 7196 tgl                      9363 LBC           0 :                         elog(ERROR, "unrecognized booltesttype: %d",
 7836 bruce                    9364 ECB             :                              (int) btest->booltesttype);
                               9365                 :                 }
 7193 tgl                      9366 CBC          36 :                 if (!PRETTY_PAREN(context))
 7188 bruce                    9367 GIC          36 :                     appendStringInfoChar(buf, ')');
                               9368                 :             }
 7964 tgl                      9369 CBC          36 :             break;
                               9370                 : 
 7370                          9371              16 :         case T_CoerceToDomain:
                               9372                 :             {
                               9373              16 :                 CoerceToDomain *ctest = (CoerceToDomain *) node;
 7188 bruce                    9374 GIC          16 :                 Node       *arg = (Node *) ctest->arg;
                               9375                 : 
 7370 tgl                      9376              16 :                 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
 7370 tgl                      9377 CBC          11 :                     !showimplicit)
                               9378                 :                 {
 7370 tgl                      9379 ECB             :                     /* don't show the implicit cast */
 7370 tgl                      9380 CBC          11 :                     get_rule_expr(arg, context, false);
                               9381                 :                 }
                               9382                 :                 else
 7370 tgl                      9383 ECB             :                 {
 5867 tgl                      9384 GIC           5 :                     get_coercion_expr(arg, context,
 5867 tgl                      9385 ECB             :                                       ctest->resulttype,
                               9386                 :                                       ctest->resulttypmod,
                               9387                 :                                       node);
                               9388                 :                 }
 7526                          9389                 :             }
 7526 tgl                      9390 CBC          16 :             break;
                               9391                 : 
 7370                          9392             140 :         case T_CoerceToDomainValue:
 3447 rhaas                    9393 GIC         140 :             appendStringInfoString(buf, "VALUE");
 7698 tgl                      9394 CBC         140 :             break;
 7698 tgl                      9395 ECB             : 
 7220 tgl                      9396 GIC          32 :         case T_SetToDefault:
 3447 rhaas                    9397 CBC          32 :             appendStringInfoString(buf, "DEFAULT");
 7220 tgl                      9398              32 :             break;
 7220 tgl                      9399 ECB             : 
 5781 tgl                      9400 GIC           9 :         case T_CurrentOfExpr:
 5781 tgl                      9401 ECB             :             {
 5781 tgl                      9402 GIC           9 :                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
 5781 tgl                      9403 ECB             : 
 5781 tgl                      9404 CBC           9 :                 if (cexpr->cursor_name)
                               9405               9 :                     appendStringInfo(buf, "CURRENT OF %s",
 5781 tgl                      9406 GIC           9 :                                      quote_identifier(cexpr->cursor_name));
                               9407                 :                 else
 5781 tgl                      9408 LBC           0 :                     appendStringInfo(buf, "CURRENT OF $%d",
 5781 tgl                      9409 ECB             :                                      cexpr->cursor_param);
                               9410                 :             }
 5781 tgl                      9411 CBC           9 :             break;
 5781 tgl                      9412 ECB             : 
 2095 tgl                      9413 UIC           0 :         case T_NextValueExpr:
                               9414                 :             {
                               9415               0 :                 NextValueExpr *nvexpr = (NextValueExpr *) node;
                               9416                 : 
 2095 tgl                      9417 ECB             :                 /*
                               9418                 :                  * This isn't exactly nextval(), but that seems close enough
                               9419                 :                  * for EXPLAIN's purposes.
                               9420                 :                  */
 2095 tgl                      9421 UIC           0 :                 appendStringInfoString(buf, "nextval(");
 2095 tgl                      9422 UBC           0 :                 simple_quote_literal(buf,
                               9423               0 :                                      generate_relation_name(nvexpr->seqid,
                               9424                 :                                                             NIL));
 2095 tgl                      9425 UIC           0 :                 appendStringInfoChar(buf, ')');
                               9426                 :             }
                               9427               0 :             break;
 2095 tgl                      9428 ECB             : 
 2882 andres                   9429 GIC          12 :         case T_InferenceElem:
 2882 andres                   9430 ECB             :             {
 2878 bruce                    9431 GIC          12 :                 InferenceElem *iexpr = (InferenceElem *) node;
 2618 tgl                      9432 ECB             :                 bool        save_varprefix;
                               9433                 :                 bool        need_parens;
 2882 andres                   9434                 : 
                               9435                 :                 /*
                               9436                 :                  * InferenceElem can only refer to target relation, so a
 2618 tgl                      9437                 :                  * prefix is not useful, and indeed would cause parse errors.
                               9438                 :                  */
 2618 tgl                      9439 CBC          12 :                 save_varprefix = context->varprefix;
 2882 andres                   9440              12 :                 context->varprefix = false;
 2882 andres                   9441 ECB             : 
                               9442                 :                 /*
                               9443                 :                  * Parenthesize the element unless it's a simple Var or a bare
                               9444                 :                  * function call.  Follows pg_get_indexdef_worker().
                               9445                 :                  */
 2882 andres                   9446 GIC          12 :                 need_parens = !IsA(iexpr->expr, Var);
 2882 andres                   9447 CBC          12 :                 if (IsA(iexpr->expr, FuncExpr) &&
 2882 andres                   9448 LBC           0 :                     ((FuncExpr *) iexpr->expr)->funcformat ==
                               9449                 :                     COERCE_EXPLICIT_CALL)
                               9450               0 :                     need_parens = false;
                               9451                 : 
 2882 andres                   9452 CBC          12 :                 if (need_parens)
 2882 andres                   9453 UIC           0 :                     appendStringInfoChar(buf, '(');
 2882 andres                   9454 GIC          12 :                 get_rule_expr((Node *) iexpr->expr,
                               9455                 :                               context, false);
 2882 andres                   9456 CBC          12 :                 if (need_parens)
 2882 andres                   9457 UIC           0 :                     appendStringInfoChar(buf, ')');
 2882 andres                   9458 ECB             : 
 2618 tgl                      9459 CBC          12 :                 context->varprefix = save_varprefix;
 2882 andres                   9460 ECB             : 
 2882 andres                   9461 CBC          12 :                 if (iexpr->infercollid)
                               9462               6 :                     appendStringInfo(buf, " COLLATE %s",
 2118 tgl                      9463 ECB             :                                      generate_collation_name(iexpr->infercollid));
 2882 andres                   9464                 : 
                               9465                 :                 /* Add the operator class name, if not default */
 2882 andres                   9466 CBC          12 :                 if (iexpr->inferopclass)
 2882 andres                   9467 ECB             :                 {
 2878 bruce                    9468 CBC           6 :                     Oid         inferopclass = iexpr->inferopclass;
 2878 bruce                    9469 GIC           6 :                     Oid         inferopcinputtype = get_opclass_input_type(iexpr->inferopclass);
                               9470                 : 
 2882 andres                   9471 CBC           6 :                     get_opclass_name(inferopclass, inferopcinputtype, buf);
 2882 andres                   9472 ECB             :                 }
                               9473                 :             }
 2882 andres                   9474 CBC          12 :             break;
 2882 andres                   9475 ECB             : 
 2314 rhaas                    9476 GIC        1715 :         case T_PartitionBoundSpec:
 2314 rhaas                    9477 ECB             :             {
 2314 rhaas                    9478 GIC        1715 :                 PartitionBoundSpec *spec = (PartitionBoundSpec *) node;
 2266 rhaas                    9479 ECB             :                 ListCell   *cell;
                               9480                 :                 char       *sep;
                               9481                 : 
 2039 rhaas                    9482 GIC        1715 :                 if (spec->is_default)
                               9483                 :                 {
 2039 rhaas                    9484 CBC          76 :                     appendStringInfoString(buf, "DEFAULT");
                               9485              76 :                     break;
                               9486                 :                 }
 2039 rhaas                    9487 ECB             : 
 2314 rhaas                    9488 CBC        1639 :                 switch (spec->strategy)
 2314 rhaas                    9489 ECB             :                 {
 1977 rhaas                    9490 GIC          91 :                     case PARTITION_STRATEGY_HASH:
                               9491              91 :                         Assert(spec->modulus > 0 && spec->remainder >= 0);
 1977 rhaas                    9492 CBC          91 :                         Assert(spec->modulus > spec->remainder);
                               9493                 : 
                               9494              91 :                         appendStringInfoString(buf, "FOR VALUES");
                               9495              91 :                         appendStringInfo(buf, " WITH (modulus %d, remainder %d)",
 1977 rhaas                    9496 ECB             :                                          spec->modulus, spec->remainder);
 1977 rhaas                    9497 GIC          91 :                         break;
 1977 rhaas                    9498 EUB             : 
 2314 rhaas                    9499 GBC         537 :                     case PARTITION_STRATEGY_LIST:
 2314 rhaas                    9500 GIC         537 :                         Assert(spec->listdatums != NIL);
                               9501                 : 
 2142 tgl                      9502             537 :                         appendStringInfoString(buf, "FOR VALUES IN (");
 2314 rhaas                    9503             537 :                         sep = "";
 2266                          9504            1483 :                         foreach(cell, spec->listdatums)
                               9505                 :                         {
  629 peter                    9506             946 :                             Const      *val = lfirst_node(Const, cell);
                               9507                 : 
 2314 rhaas                    9508             946 :                             appendStringInfoString(buf, sep);
                               9509             946 :                             get_const_expr(val, context, -1);
                               9510             946 :                             sep = ", ";
                               9511                 :                         }
                               9512                 : 
 2063 peter_e                  9513             537 :                         appendStringInfoChar(buf, ')');
 2314 rhaas                    9514             537 :                         break;
                               9515                 : 
 2314 rhaas                    9516 CBC        1011 :                     case PARTITION_STRATEGY_RANGE:
 2314 rhaas                    9517 GIC        1011 :                         Assert(spec->lowerdatums != NIL &&
                               9518                 :                                spec->upperdatums != NIL &&
 2314 rhaas                    9519 ECB             :                                list_length(spec->lowerdatums) ==
                               9520                 :                                list_length(spec->upperdatums));
                               9521                 : 
 2068 rhaas                    9522 CBC        1011 :                         appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
 2064 tgl                      9523 ECB             :                                          get_range_partbound_string(spec->lowerdatums),
                               9524                 :                                          get_range_partbound_string(spec->upperdatums));
 2314 rhaas                    9525 GIC        1011 :                         break;
                               9526                 : 
 2314 rhaas                    9527 UIC           0 :                     default:
                               9528               0 :                         elog(ERROR, "unrecognized partition strategy: %d",
                               9529                 :                              (int) spec->strategy);
                               9530                 :                         break;
                               9531                 :                 }
                               9532                 :             }
 2314 rhaas                    9533 GIC        1639 :             break;
 2314 rhaas                    9534 ECB             : 
   11 alvherre                 9535 GNC          24 :         case T_JsonValueExpr:
                               9536                 :             {
                               9537              24 :                 JsonValueExpr *jve = (JsonValueExpr *) node;
                               9538                 : 
                               9539              24 :                 get_rule_expr((Node *) jve->raw_expr, context, false);
                               9540              24 :                 get_json_format(jve->format, context->buf);
                               9541                 :             }
                               9542              24 :             break;
                               9543                 : 
                               9544              36 :         case T_JsonConstructorExpr:
                               9545              36 :             get_json_constructor((JsonConstructorExpr *) node, context, false);
                               9546              36 :             break;
                               9547                 : 
    9                          9548              24 :         case T_JsonIsPredicate:
                               9549                 :             {
                               9550              24 :                 JsonIsPredicate *pred = (JsonIsPredicate *) node;
                               9551                 : 
                               9552              24 :                 if (!PRETTY_PAREN(context))
                               9553              12 :                     appendStringInfoChar(context->buf, '(');
                               9554                 : 
                               9555              24 :                 get_rule_expr_paren(pred->expr, context, true, node);
                               9556                 : 
                               9557              24 :                 appendStringInfoString(context->buf, " IS JSON");
                               9558                 : 
                               9559                 :                 /* TODO: handle FORMAT clause */
                               9560                 : 
                               9561              24 :                 switch (pred->item_type)
                               9562                 :                 {
                               9563               6 :                     case JS_TYPE_SCALAR:
                               9564               6 :                         appendStringInfoString(context->buf, " SCALAR");
                               9565               6 :                         break;
                               9566               6 :                     case JS_TYPE_ARRAY:
                               9567               6 :                         appendStringInfoString(context->buf, " ARRAY");
                               9568               6 :                         break;
                               9569               6 :                     case JS_TYPE_OBJECT:
                               9570               6 :                         appendStringInfoString(context->buf, " OBJECT");
                               9571               6 :                         break;
                               9572               6 :                     default:
                               9573               6 :                         break;
                               9574                 :                 }
                               9575                 : 
                               9576              24 :                 if (pred->unique_keys)
                               9577               6 :                     appendStringInfoString(context->buf, " WITH UNIQUE KEYS");
                               9578                 : 
                               9579              24 :                 if (!PRETTY_PAREN(context))
                               9580              12 :                     appendStringInfoChar(context->buf, ')');
                               9581                 :             }
                               9582              24 :             break;
                               9583                 : 
 6758 tgl                      9584 GIC         940 :         case T_List:
                               9585                 :             {
                               9586                 :                 char       *sep;
                               9587                 :                 ListCell   *l;
                               9588                 : 
 6758 tgl                      9589 CBC         940 :                 sep = "";
                               9590            2658 :                 foreach(l, (List *) node)
                               9591                 :                 {
 6553 neilc                    9592            1718 :                     appendStringInfoString(buf, sep);
 6758 tgl                      9593 GIC        1718 :                     get_rule_expr((Node *) lfirst(l), context, showimplicit);
 6758 tgl                      9594 CBC        1718 :                     sep = ", ";
 6758 tgl                      9595 ECB             :                 }
                               9596                 :             }
 6758 tgl                      9597 GIC         940 :             break;
 6758 tgl                      9598 ECB             : 
 2223 alvherre                 9599 GIC          12 :         case T_TableFunc:
                               9600              12 :             get_tablefunc((TableFunc *) node, context, showimplicit);
                               9601              12 :             break;
                               9602                 : 
 8986 bruce                    9603 UIC           0 :         default:
 7196 tgl                      9604               0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
                               9605                 :             break;
                               9606                 :     }
                               9607                 : }
                               9608                 : 
                               9609                 : /*
                               9610                 :  * get_rule_expr_toplevel       - Parse back a toplevel expression
                               9611                 :  *
                               9612                 :  * Same as get_rule_expr(), except that if the expr is just a Var, we pass
 2702 tgl                      9613 ECB             :  * istoplevel = true not false to get_variable().  This causes whole-row Vars
                               9614                 :  * to get printed with decoration that will prevent expansion of "*".
                               9615                 :  * We need to use this in contexts such as ROW() and VALUES(), where the
                               9616                 :  * parser would expand "foo.*" appearing at top level.  (In principle we'd
                               9617                 :  * use this in get_target_list() too, but that has additional worries about
                               9618                 :  * whether to print AS, so it needs to invoke get_variable() directly anyway.)
                               9619                 :  */
                               9620                 : static void
 2702 tgl                      9621 GIC        1351 : get_rule_expr_toplevel(Node *node, deparse_context *context,
 2702 tgl                      9622 ECB             :                        bool showimplicit)
                               9623                 : {
 2702 tgl                      9624 CBC        1351 :     if (node && IsA(node, Var))
                               9625             514 :         (void) get_variable((Var *) node, 0, true, context);
                               9626                 :     else
 2702 tgl                      9627 GIC         837 :         get_rule_expr(node, context, showimplicit);
                               9628            1351 : }
 2702 tgl                      9629 ECB             : 
                               9630                 : /*
                               9631                 :  * get_rule_list_toplevel       - Parse back a list of toplevel expressions
                               9632                 :  *
                               9633                 :  * Apply get_rule_expr_toplevel() to each element of a List.
                               9634                 :  *
                               9635                 :  * This adds commas between the expressions, but caller is responsible
  451                          9636                 :  * for printing surrounding decoration.
                               9637                 :  */
                               9638                 : static void
  451 tgl                      9639 GBC         186 : get_rule_list_toplevel(List *lst, deparse_context *context,
  451 tgl                      9640 ECB             :                        bool showimplicit)
                               9641                 : {
                               9642                 :     const char *sep;
                               9643                 :     ListCell   *lc;
                               9644                 : 
  451 tgl                      9645 CBC         186 :     sep = "";
                               9646             658 :     foreach(lc, lst)
                               9647                 :     {
  451 tgl                      9648 GIC         472 :         Node       *e = (Node *) lfirst(lc);
                               9649                 : 
                               9650             472 :         appendStringInfoString(context->buf, sep);
  451 tgl                      9651 CBC         472 :         get_rule_expr_toplevel(e, context, showimplicit);
                               9652             472 :         sep = ", ";
  451 tgl                      9653 ECB             :     }
  451 tgl                      9654 GIC         186 : }
  451 tgl                      9655 ECB             : 
                               9656                 : /*
                               9657                 :  * get_rule_expr_funccall       - Parse back a function-call expression
                               9658                 :  *
                               9659                 :  * Same as get_rule_expr(), except that we guarantee that the output will
                               9660                 :  * look like a function call, or like one of the things the grammar treats as
                               9661                 :  * equivalent to a function call (see the func_expr_windowless production).
                               9662                 :  * This is needed in places where the grammar uses func_expr_windowless and
 2096                          9663                 :  * you can't substitute a parenthesized a_expr.  If what we have isn't going
                               9664                 :  * to look like a function call, wrap it in a dummy CAST() expression, which
                               9665                 :  * will satisfy the grammar --- and, indeed, is likely what the user wrote to
                               9666                 :  * produce such a thing.
                               9667                 :  */
                               9668                 : static void
 2096 tgl                      9669 CBC         276 : get_rule_expr_funccall(Node *node, deparse_context *context,
 2096 tgl                      9670 ECB             :                        bool showimplicit)
                               9671                 : {
 2096 tgl                      9672 GIC         276 :     if (looks_like_function(node))
                               9673             270 :         get_rule_expr(node, context, showimplicit);
 2096 tgl                      9674 ECB             :     else
                               9675                 :     {
 2096 tgl                      9676 GIC           6 :         StringInfo  buf = context->buf;
 2096 tgl                      9677 ECB             : 
 2096 tgl                      9678 CBC           6 :         appendStringInfoString(buf, "CAST(");
                               9679                 :         /* no point in showing any top-level implicit cast */
 2096 tgl                      9680 GIC           6 :         get_rule_expr(node, context, false);
                               9681               6 :         appendStringInfo(buf, " AS %s)",
 2096 tgl                      9682 ECB             :                          format_type_with_typemod(exprType(node),
                               9683                 :                                                   exprTypmod(node)));
                               9684                 :     }
 2096 tgl                      9685 GIC         276 : }
                               9686                 : 
 2096 tgl                      9687 ECB             : /*
                               9688                 :  * Helper function to identify node types that satisfy func_expr_windowless.
                               9689                 :  * If in doubt, "false" is always a safe answer.
                               9690                 :  */
                               9691                 : static bool
 2096 tgl                      9692 GIC         818 : looks_like_function(Node *node)
 2096 tgl                      9693 ECB             : {
 2096 tgl                      9694 GIC         818 :     if (node == NULL)
 2096 tgl                      9695 LBC           0 :         return false;           /* probably shouldn't happen */
 2096 tgl                      9696 CBC         818 :     switch (nodeTag(node))
 2096 tgl                      9697 ECB             :     {
 2096 tgl                      9698 GIC         341 :         case T_FuncExpr:
                               9699                 :             /* OK, unless it's going to deparse as a cast */
  886                          9700             401 :             return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL ||
                               9701              60 :                     ((FuncExpr *) node)->funcformat == COERCE_SQL_SYNTAX);
 2096                          9702               3 :         case T_NullIfExpr:
 2096 tgl                      9703 ECB             :         case T_CoalesceExpr:
                               9704                 :         case T_MinMaxExpr:
                               9705                 :         case T_XmlExpr:
                               9706                 :             /* these are all accepted by func_expr_common_subexpr */
 2096 tgl                      9707 GIC           3 :             return true;
                               9708             474 :         default:
                               9709             474 :             break;
                               9710                 :     }
                               9711             474 :     return false;
                               9712                 : }
                               9713                 : 
                               9714                 : 
                               9715                 : /*
                               9716                 :  * get_oper_expr            - Parse back an OpExpr node
 7646 tgl                      9717 ECB             :  */
                               9718                 : static void
 7184 bruce                    9719 CBC       24672 : get_oper_expr(OpExpr *expr, deparse_context *context)
                               9720                 : {
 7646 tgl                      9721           24672 :     StringInfo  buf = context->buf;
 7423 tgl                      9722 GIC       24672 :     Oid         opno = expr->opno;
 7646                          9723           24672 :     List       *args = expr->args;
                               9724                 : 
 7193                          9725           24672 :     if (!PRETTY_PAREN(context))
 7188 bruce                    9726           23770 :         appendStringInfoChar(buf, '(');
 6888 neilc                    9727           24672 :     if (list_length(args) == 2)
 7646 tgl                      9728 ECB             :     {
                               9729                 :         /* binary operator */
 6892 neilc                    9730 GIC       24657 :         Node       *arg1 = (Node *) linitial(args);
 7522 bruce                    9731 CBC       24657 :         Node       *arg2 = (Node *) lsecond(args);
 7188 bruce                    9732 ECB             : 
 7188 bruce                    9733 GIC       24657 :         get_rule_expr_paren(arg1, context, true, (Node *) expr);
 7646 tgl                      9734           24657 :         appendStringInfo(buf, " %s ",
                               9735                 :                          generate_operator_name(opno,
 7646 tgl                      9736 ECB             :                                                 exprType(arg1),
                               9737                 :                                                 exprType(arg2)));
 7188 bruce                    9738 CBC       24657 :         get_rule_expr_paren(arg2, context, true, (Node *) expr);
                               9739                 :     }
                               9740                 :     else
                               9741                 :     {
  934 tgl                      9742 ECB             :         /* prefix operator */
 6892 neilc                    9743 GIC          15 :         Node       *arg = (Node *) linitial(args);
                               9744                 : 
  934 tgl                      9745              15 :         appendStringInfo(buf, "%s ",
                               9746                 :                          generate_operator_name(opno,
                               9747                 :                                                 InvalidOid,
                               9748                 :                                                 exprType(arg)));
                               9749              15 :         get_rule_expr_paren(arg, context, true, (Node *) expr);
 7646 tgl                      9750 ECB             :     }
 7193 tgl                      9751 GIC       24672 :     if (!PRETTY_PAREN(context))
 7188 bruce                    9752 CBC       23770 :         appendStringInfoChar(buf, ')');
 7646 tgl                      9753           24672 : }
                               9754                 : 
                               9755                 : /*
                               9756                 :  * get_func_expr            - Parse back a FuncExpr node
                               9757                 :  */
                               9758                 : static void
 7184 bruce                    9759 GIC        5662 : get_func_expr(FuncExpr *expr, deparse_context *context,
 7507 tgl                      9760 ECB             :               bool showimplicit)
 8994 bruce                    9761 EUB             : {
 8589 tgl                      9762 GIC        5662 :     StringInfo  buf = context->buf;
 7423                          9763            5662 :     Oid         funcoid = expr->funcid;
 7646 tgl                      9764 ECB             :     Oid         argtypes[FUNC_MAX_ARGS];
                               9765                 :     int         nargs;
 4931                          9766                 :     List       *argnames;
                               9767                 :     bool        use_variadic;
 6892 neilc                    9768                 :     ListCell   *l;
                               9769                 : 
 8443 tgl                      9770                 :     /*
 6385 bruce                    9771                 :      * If the function call came from an implicit coercion, then just show the
                               9772                 :      * first argument --- unless caller wants to see implicit coercions.
 7508 tgl                      9773                 :      */
 7423 tgl                      9774 GIC        5662 :     if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
                               9775                 :     {
 6892 neilc                    9776 CBC         847 :         get_rule_expr_paren((Node *) linitial(expr->args), context,
                               9777                 :                             false, (Node *) expr);
 7508 tgl                      9778 GIC        2125 :         return;
 7508 tgl                      9779 ECB             :     }
                               9780                 : 
                               9781                 :     /*
 7188 bruce                    9782                 :      * If the function call came from a cast, then show the first argument
                               9783                 :      * plus an explicit cast operation.
                               9784                 :      */
 7423 tgl                      9785 CBC        4815 :     if (expr->funcformat == COERCE_EXPLICIT_CAST ||
                               9786            4560 :         expr->funcformat == COERCE_IMPLICIT_CAST)
 8443 tgl                      9787 ECB             :     {
 6892 neilc                    9788 CBC         656 :         Node       *arg = linitial(expr->args);
 7423 tgl                      9789             656 :         Oid         rettype = expr->funcresulttype;
                               9790                 :         int32       coercedTypmod;
 7508 tgl                      9791 ECB             : 
                               9792                 :         /* Get the typmod if this is a length-coercion function */
 7508 tgl                      9793 GIC         656 :         (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
                               9794                 : 
 5867                          9795             656 :         get_coercion_expr(arg, context,
                               9796                 :                           rettype, coercedTypmod,
                               9797                 :                           (Node *) expr);
 8179 tgl                      9798 ECB             : 
 8443 tgl                      9799 GIC         656 :         return;
                               9800                 :     }
 8443 tgl                      9801 ECB             : 
                               9802                 :     /*
  886                          9803                 :      * If the function was called using one of the SQL spec's random special
                               9804                 :      * syntaxes, try to reproduce that.  If we don't recognize the function,
                               9805                 :      * fall through.
                               9806                 :      */
  886 tgl                      9807 GIC        4159 :     if (expr->funcformat == COERCE_SQL_SYNTAX)
                               9808                 :     {
                               9809             625 :         if (get_func_sql_syntax(expr, context))
  886 tgl                      9810 CBC         622 :             return;
                               9811                 :     }
                               9812                 : 
                               9813                 :     /*
 6385 bruce                    9814 ECB             :      * Normal function: display as proname(args).  First we need to extract
                               9815                 :      * the argument datatypes.
                               9816                 :      */
 5215 tgl                      9817 CBC        3537 :     if (list_length(expr->args) > FUNC_MAX_ARGS)
 5215 tgl                      9818 UIC           0 :         ereport(ERROR,
                               9819                 :                 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
                               9820                 :                  errmsg("too many arguments")));
 7646 tgl                      9821 GIC        3537 :     nargs = 0;
 4931                          9822            3537 :     argnames = NIL;
 7646                          9823            7563 :     foreach(l, expr->args)
                               9824                 :     {
 4790 bruce                    9825            4026 :         Node       *arg = (Node *) lfirst(l);
 4931 tgl                      9826 ECB             : 
 4931 tgl                      9827 GIC        4026 :         if (IsA(arg, NamedArgExpr))
                               9828               9 :             argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
                               9829            4026 :         argtypes[nargs] = exprType(arg);
 7646 tgl                      9830 CBC        4026 :         nargs++;
 7646 tgl                      9831 ECB             :     }
 7522 bruce                    9832                 : 
 7646 tgl                      9833 GIC        3537 :     appendStringInfo(buf, "%s(",
 4931 tgl                      9834 ECB             :                      generate_function_name(funcoid, nargs,
                               9835                 :                                             argnames, argtypes,
 3730 tgl                      9836 GIC        3537 :                                             expr->funcvariadic,
                               9837                 :                                             &use_variadic,
                               9838                 :                                             context->special_exprkind));
 5380                          9839            3537 :     nargs = 0;
                               9840            7563 :     foreach(l, expr->args)
 5380 tgl                      9841 ECB             :     {
 5380 tgl                      9842 CBC        4026 :         if (nargs++ > 0)
 5380 tgl                      9843 GIC         809 :             appendStringInfoString(buf, ", ");
 1364                          9844            4026 :         if (use_variadic && lnext(expr->args, l) == NULL)
 5380 tgl                      9845 CBC           3 :             appendStringInfoString(buf, "VARIADIC ");
 5380 tgl                      9846 GIC        4026 :         get_rule_expr((Node *) lfirst(l), context, true);
 5380 tgl                      9847 ECB             :     }
 8449 tgl                      9848 CBC        3537 :     appendStringInfoChar(buf, ')');
 8994 bruce                    9849 ECB             : }
                               9850                 : 
                               9851                 : /*
                               9852                 :  * get_agg_expr         - Parse back an Aggref node
                               9853                 :  */
 7668 tgl                      9854                 : static void
  220 andrew                   9855 CBC         892 : get_agg_expr(Aggref *aggref, deparse_context *context,
                               9856                 :              Aggref *original_aggref)
                               9857                 : {
   11 alvherre                 9858 GNC         892 :     get_agg_expr_helper(aggref, context, original_aggref, NULL, NULL,
                               9859                 :                         false);
                               9860             892 : }
                               9861                 : 
                               9862                 : /*
                               9863                 :  * get_agg_expr_helper      - subroutine for get_agg_expr and
                               9864                 :  *                          get_json_agg_constructor
                               9865                 :  */
                               9866                 : static void
                               9867             910 : get_agg_expr_helper(Aggref *aggref, deparse_context *context,
                               9868                 :                     Aggref *original_aggref, const char *funcname,
                               9869                 :                     const char *options, bool is_json_objectagg)
 7668 tgl                      9870 ECB             : {
 7668 tgl                      9871 GIC         910 :     StringInfo  buf = context->buf;
                               9872                 :     Oid         argtypes[FUNC_MAX_ARGS];
                               9873                 :     int         nargs;
   11 alvherre                 9874 GNC         910 :     bool        use_variadic = false;
                               9875                 : 
                               9876                 :     /*
 2538 rhaas                    9877 ECB             :      * For a combining aggregate, we look up and deparse the corresponding
                               9878                 :      * partial aggregate instead.  This is necessary because our input
                               9879                 :      * argument list has been replaced; the new argument list always has just
                               9880                 :      * one element, which will point to a partial Aggref that supplies us with
                               9881                 :      * transition states to combine.
                               9882                 :      */
 2478 tgl                      9883 GIC         910 :     if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
                               9884                 :     {
                               9885                 :         TargetEntry *tle;
 2538 rhaas                    9886 ECB             : 
 2538 rhaas                    9887 CBC         130 :         Assert(list_length(aggref->args) == 1);
 1215 tgl                      9888 GIC         130 :         tle = linitial_node(TargetEntry, aggref->args);
                               9889             130 :         resolve_special_varno((Node *) tle->expr, context,
                               9890                 :                               get_agg_combine_expr, original_aggref);
 2538 rhaas                    9891             130 :         return;
                               9892                 :     }
 2538 rhaas                    9893 ECB             : 
 2478 tgl                      9894                 :     /*
                               9895                 :      * Mark as PARTIAL, if appropriate.  We look to the original aggref so as
                               9896                 :      * to avoid printing this when recursing from the code just above.
                               9897                 :      */
 2478 tgl                      9898 GIC         780 :     if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
 2538 rhaas                    9899 CBC          30 :         appendStringInfoString(buf, "PARTIAL ");
 2538 rhaas                    9900 ECB             : 
 3394 tgl                      9901                 :     /* Extract the argument types as seen by the parser */
 3394 tgl                      9902 CBC         780 :     nargs = get_aggregate_argtypes(aggref, argtypes);
                               9903                 : 
   11 alvherre                 9904 GNC         780 :     if (!funcname)
                               9905             762 :         funcname = generate_function_name(aggref->aggfnoid, nargs, NIL,
                               9906             762 :                                           argtypes, aggref->aggvariadic,
                               9907                 :                                           &use_variadic,
                               9908                 :                                           context->special_exprkind);
                               9909                 : 
 3394 tgl                      9910 ECB             :     /* Print the aggregate name, schema-qualified if needed */
   11 alvherre                 9911 GNC         780 :     appendStringInfo(buf, "%s(%s", funcname,
 4863 tgl                      9912 GBC         780 :                      (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
                               9913                 : 
 3394 tgl                      9914 CBC         780 :     if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
                               9915                 :     {
                               9916                 :         /*
 3394 tgl                      9917 ECB             :          * Ordered-set aggregates do not use "*" syntax.  Also, we needn't
                               9918                 :          * worry about inserting VARIADIC.  So we can just dump the direct
                               9919                 :          * args as-is.
                               9920                 :          */
 3394 tgl                      9921 CBC          14 :         Assert(!aggref->aggvariadic);
 3394 tgl                      9922 GIC          14 :         get_rule_expr((Node *) aggref->aggdirectargs, context, true);
                               9923              14 :         Assert(aggref->aggorder != NIL);
                               9924              14 :         appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
 3394 tgl                      9925 CBC          14 :         get_rule_orderby(aggref->aggorder, aggref->args, false, context);
                               9926                 :     }
 7668 tgl                      9927 ECB             :     else
 3505                          9928                 :     {
                               9929                 :         /* aggstar can be set only in zero-argument aggregates */
 3394 tgl                      9930 GIC         766 :         if (aggref->aggstar)
                               9931             112 :             appendStringInfoChar(buf, '*');
 3394 tgl                      9932 ECB             :         else
 3505                          9933                 :         {
                               9934                 :             ListCell   *l;
 3394                          9935                 :             int         i;
                               9936                 : 
 3394 tgl                      9937 CBC         654 :             i = 0;
                               9938            1387 :             foreach(l, aggref->args)
                               9939                 :             {
 3394 tgl                      9940 GIC         733 :                 TargetEntry *tle = (TargetEntry *) lfirst(l);
 3394 tgl                      9941 CBC         733 :                 Node       *arg = (Node *) tle->expr;
                               9942                 : 
 3394 tgl                      9943 GIC         733 :                 Assert(!IsA(arg, NamedArgExpr));
                               9944             733 :                 if (tle->resjunk)
                               9945              19 :                     continue;
                               9946             714 :                 if (i++ > 0)
                               9947                 :                 {
   11 alvherre                 9948 GNC          60 :                     if (is_json_objectagg)
                               9949                 :                     {
                               9950                 :                         /*
                               9951                 :                          * the ABSENT ON NULL and WITH UNIQUE args are printed
                               9952                 :                          * separately, so ignore them here
                               9953                 :                          */
                               9954               6 :                         if (i > 2)
   11 alvherre                 9955 UNC           0 :                             break;
                               9956                 : 
   11 alvherre                 9957 GNC           6 :                         appendStringInfoString(buf, " : ");
                               9958                 :                     }
                               9959                 :                     else
                               9960              54 :                         appendStringInfoString(buf, ", ");
                               9961                 :                 }
 3394 tgl                      9962 GIC         714 :                 if (use_variadic && i == nargs)
                               9963               4 :                     appendStringInfoString(buf, "VARIADIC ");
 3394 tgl                      9964 CBC         714 :                 get_rule_expr(arg, context, true);
                               9965                 :             }
                               9966                 :         }
 3505 tgl                      9967 ECB             : 
 3394 tgl                      9968 GIC         766 :         if (aggref->aggorder != NIL)
 3394 tgl                      9969 ECB             :         {
 3394 tgl                      9970 GBC          35 :             appendStringInfoString(buf, " ORDER BY ");
 3394 tgl                      9971 GIC          35 :             get_rule_orderby(aggref->aggorder, aggref->args, false, context);
 3394 tgl                      9972 ECB             :         }
 4863                          9973                 :     }
 3554 noah                     9974                 : 
   11 alvherre                 9975 GNC         780 :     if (options)
                               9976              18 :         appendStringInfoString(buf, options);
                               9977                 : 
 3554 noah                     9978 GIC         780 :     if (aggref->aggfilter != NULL)
                               9979                 :     {
                               9980              23 :         appendStringInfoString(buf, ") FILTER (WHERE ");
                               9981              23 :         get_rule_expr((Node *) aggref->aggfilter, context, false);
                               9982                 :     }
 3554 noah                     9983 ECB             : 
 7668 tgl                      9984 GIC         780 :     appendStringInfoChar(buf, ')');
 7668 tgl                      9985 ECB             : }
                               9986                 : 
                               9987                 : /*
                               9988                 :  * This is a helper function for get_agg_expr().  It's used when we deparse
                               9989                 :  * a combining Aggref; resolve_special_varno locates the corresponding partial
                               9990                 :  * Aggref and then calls this.
                               9991                 :  */
                               9992                 : static void
 1215 tgl                      9993 GIC         130 : get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
 2538 rhaas                    9994 ECB             : {
                               9995                 :     Aggref     *aggref;
 1215 tgl                      9996 GIC         130 :     Aggref     *original_aggref = callback_arg;
                               9997                 : 
 2538 rhaas                    9998 CBC         130 :     if (!IsA(node, Aggref))
 2538 rhaas                    9999 UIC           0 :         elog(ERROR, "combining Aggref does not point to an Aggref");
                              10000                 : 
 2538 rhaas                   10001 GIC         130 :     aggref = (Aggref *) node;
                              10002             130 :     get_agg_expr(aggref, context, original_aggref);
                              10003             130 : }
 2538 rhaas                   10004 ECB             : 
 5215 tgl                     10005 EUB             : /*
                              10006                 :  * get_windowfunc_expr  - Parse back a WindowFunc node
                              10007                 :  */
 5215 tgl                     10008 ECB             : static void
  220 andrew                  10009 CBC         117 : get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
                              10010                 : {
   11 alvherre                10011 GNC         117 :     get_windowfunc_expr_helper(wfunc, context, NULL, NULL, false);
                              10012             117 : }
                              10013                 : 
                              10014                 : 
                              10015                 : /*
                              10016                 :  * get_windowfunc_expr_helper   - subroutine for get_windowfunc_expr and
                              10017                 :  *                              get_json_agg_constructor
                              10018                 :  */
                              10019                 : static void
                              10020             123 : get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
                              10021                 :                            const char *funcname, const char *options,
                              10022                 :                            bool is_json_objectagg)
 5215 tgl                     10023 ECB             : {
 5215 tgl                     10024 GIC         123 :     StringInfo  buf = context->buf;
 5215 tgl                     10025 ECB             :     Oid         argtypes[FUNC_MAX_ARGS];
                              10026                 :     int         nargs;
 3441                         10027                 :     List       *argnames;
 5215 tgl                     10028 EUB             :     ListCell   *l;
 5215 tgl                     10029 ECB             : 
 5215 tgl                     10030 CBC         123 :     if (list_length(wfunc->args) > FUNC_MAX_ARGS)
 5215 tgl                     10031 UIC           0 :         ereport(ERROR,
                              10032                 :                 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
 5215 tgl                     10033 ECB             :                  errmsg("too many arguments")));
 5215 tgl                     10034 CBC         123 :     nargs = 0;
 3441 tgl                     10035 GIC         123 :     argnames = NIL;
 5215                         10036             192 :     foreach(l, wfunc->args)
                              10037                 :     {
 4790 bruce                   10038 CBC          69 :         Node       *arg = (Node *) lfirst(l);
                              10039                 : 
 3441 tgl                     10040 GIC          69 :         if (IsA(arg, NamedArgExpr))
 3441 tgl                     10041 LBC           0 :             argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
 4931 tgl                     10042 CBC          69 :         argtypes[nargs] = exprType(arg);
 5215 tgl                     10043 GIC          69 :         nargs++;
                              10044                 :     }
 5215 tgl                     10045 ECB             : 
   11 alvherre                10046 GNC         123 :     if (!funcname)
                              10047             117 :         funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
                              10048                 :                                           argtypes, false, NULL,
                              10049                 :                                           context->special_exprkind);
                              10050                 : 
                              10051             123 :     appendStringInfo(buf, "%s(", funcname);
                              10052                 : 
                              10053                 :     /* winstar can be set only in zero-argument aggregates */
 5215 tgl                     10054 CBC         123 :     if (wfunc->winstar)
 5215 tgl                     10055 GIC          12 :         appendStringInfoChar(buf, '*');
                              10056                 :     else
                              10057                 :     {
   11 alvherre                10058 GNC         111 :         if (is_json_objectagg)
                              10059                 :         {
                              10060               3 :             get_rule_expr((Node *) linitial(wfunc->args), context, false);
                              10061               3 :             appendStringInfoString(buf, " : ");
                              10062               3 :             get_rule_expr((Node *) lsecond(wfunc->args), context, false);
                              10063                 :         }
                              10064                 :         else
                              10065             108 :             get_rule_expr((Node *) wfunc->args, context, true);
                              10066                 :     }
                              10067                 : 
                              10068             123 :     if (options)
                              10069               6 :         appendStringInfoString(buf, options);
 3554 noah                    10070 ECB             : 
 3554 noah                    10071 GIC         123 :     if (wfunc->aggfilter != NULL)
 3554 noah                    10072 ECB             :     {
 3554 noah                    10073 UIC           0 :         appendStringInfoString(buf, ") FILTER (WHERE ");
 3554 noah                    10074 UBC           0 :         get_rule_expr((Node *) wfunc->aggfilter, context, false);
 3554 noah                    10075 EUB             :     }
                              10076                 : 
 5215 tgl                     10077 GIC         123 :     appendStringInfoString(buf, ") OVER ");
 5215 tgl                     10078 ECB             : 
 5215 tgl                     10079 GIC         123 :     foreach(l, context->windowClause)
 5215 tgl                     10080 ECB             :     {
 5215 tgl                     10081 GIC          21 :         WindowClause *wc = (WindowClause *) lfirst(l);
 5215 tgl                     10082 ECB             : 
 5215 tgl                     10083 GIC          21 :         if (wc->winref == wfunc->winref)
 5215 tgl                     10084 ECB             :         {
 5215 tgl                     10085 GIC          21 :             if (wc->name)
 5215 tgl                     10086 LBC           0 :                 appendStringInfoString(buf, quote_identifier(wc->name));
 5215 tgl                     10087 EUB             :             else
 5215 tgl                     10088 GIC          21 :                 get_rule_windowspec(wc, context->windowTList, context);
 5215 tgl                     10089 CBC          21 :             break;
 5215 tgl                     10090 ECB             :         }
                              10091                 :     }
 5215 tgl                     10092 GIC         123 :     if (l == NULL)
 5215 tgl                     10093 ECB             :     {
 5215 tgl                     10094 GIC         102 :         if (context->windowClause)
 5215 tgl                     10095 LBC           0 :             elog(ERROR, "could not find window clause for winref %u",
 5215 tgl                     10096 EUB             :                  wfunc->winref);
                              10097                 : 
                              10098                 :         /*
                              10099                 :          * In EXPLAIN, we don't have window context information available, so
                              10100                 :          * we have to settle for this:
                              10101                 :          */
 5215 tgl                     10102 GIC         102 :         appendStringInfoString(buf, "(?)");
 5215 tgl                     10103 ECB             :     }
 5215 tgl                     10104 GIC         123 : }
 5215 tgl                     10105 ECB             : 
                              10106                 : /*
                              10107                 :  * get_func_sql_syntax_time
                              10108                 :  *
                              10109                 :  * Parse back argument of SQL-syntax function call related to a time or a
                              10110                 :  * timestamp.  These require a specific handling when their typmod is given
                              10111                 :  * by the function caller through their SQL keyword.
                              10112                 :  */
                              10113                 : static void
  139 michael                 10114 GNC         366 : get_func_sql_syntax_time(List *args, deparse_context *context)
                              10115                 : {
                              10116             366 :     StringInfo  buf = context->buf;
                              10117                 :     Const      *cons;
                              10118                 : 
                              10119             366 :     if (list_length(args) != 1)
                              10120              24 :         return;
                              10121                 : 
                              10122             342 :     cons = (Const *) linitial(args);
                              10123             342 :     Assert(IsA(cons, Const));
                              10124                 : 
                              10125             342 :     if (!cons->constisnull)
                              10126                 :     {
                              10127             333 :         appendStringInfoString(buf, "(");
                              10128             333 :         get_rule_expr((Node *) cons, context, false);
                              10129             333 :         appendStringInfoString(buf, ")");
                              10130                 :     }
                              10131                 : }
                              10132                 : 
                              10133                 : /*
                              10134                 :  * get_func_sql_syntax      - Parse back a SQL-syntax function call
                              10135                 :  *
                              10136                 :  * Returns true if we successfully deparsed, false if we did not
                              10137                 :  * recognize the function.
                              10138                 :  */
                              10139                 : static bool
  886 tgl                     10140 GIC         625 : get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
                              10141                 : {
  886 tgl                     10142 CBC         625 :     StringInfo  buf = context->buf;
  886 tgl                     10143 GIC         625 :     Oid         funcoid = expr->funcid;
  886 tgl                     10144 ECB             : 
  886 tgl                     10145 GIC         625 :     switch (funcoid)
                              10146                 :     {
  886 tgl                     10147 CBC           6 :         case F_TIMEZONE_INTERVAL_TIMESTAMP:
  886 tgl                     10148 ECB             :         case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
                              10149                 :         case F_TIMEZONE_INTERVAL_TIMETZ:
                              10150                 :         case F_TIMEZONE_TEXT_TIMESTAMP:
                              10151                 :         case F_TIMEZONE_TEXT_TIMESTAMPTZ:
                              10152                 :         case F_TIMEZONE_TEXT_TIMETZ:
                              10153                 :             /* AT TIME ZONE ... note reversed argument order */
  886 tgl                     10154 GIC           6 :             appendStringInfoChar(buf, '(');
  129 tgl                     10155 CBC           6 :             get_rule_expr_paren((Node *) lsecond(expr->args), context, false,
  129 tgl                     10156 ECB             :                                 (Node *) expr);
  886 tgl                     10157 CBC           6 :             appendStringInfoString(buf, " AT TIME ZONE ");
  129 tgl                     10158 GIC           6 :             get_rule_expr_paren((Node *) linitial(expr->args), context, false,
                              10159                 :                                 (Node *) expr);
  886                         10160               6 :             appendStringInfoChar(buf, ')');
                              10161               6 :             return true;
                              10162                 : 
                              10163               3 :         case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
                              10164                 :         case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
                              10165                 :         case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
                              10166                 :         case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
                              10167                 :         case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
  886 tgl                     10168 ECB             :         case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
                              10169                 :         case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
                              10170                 :         case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
                              10171                 :         case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
                              10172                 :         case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
                              10173                 :         case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
                              10174                 :         case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
                              10175                 :         case F_OVERLAPS_TIME_TIME_TIME_TIME:
                              10176                 :             /* (x1, x2) OVERLAPS (y1, y2) */
  886 tgl                     10177 GIC           3 :             appendStringInfoString(buf, "((");
                              10178               3 :             get_rule_expr((Node *) linitial(expr->args), context, false);
                              10179               3 :             appendStringInfoString(buf, ", ");
                              10180               3 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
                              10181               3 :             appendStringInfoString(buf, ") OVERLAPS (");
  886 tgl                     10182 CBC           3 :             get_rule_expr((Node *) lthird(expr->args), context, false);
                              10183               3 :             appendStringInfoString(buf, ", ");
  886 tgl                     10184 GIC           3 :             get_rule_expr((Node *) lfourth(expr->args), context, false);
  886 tgl                     10185 CBC           3 :             appendStringInfoString(buf, "))");
                              10186               3 :             return true;
                              10187                 : 
  733 peter                   10188               3 :         case F_EXTRACT_TEXT_DATE:
  733 peter                   10189 ECB             :         case F_EXTRACT_TEXT_TIME:
                              10190                 :         case F_EXTRACT_TEXT_TIMETZ:
                              10191                 :         case F_EXTRACT_TEXT_TIMESTAMP:
                              10192                 :         case F_EXTRACT_TEXT_TIMESTAMPTZ:
                              10193                 :         case F_EXTRACT_TEXT_INTERVAL:
                              10194                 :             /* EXTRACT (x FROM y) */
  733 peter                   10195 GIC           3 :             appendStringInfoString(buf, "EXTRACT(");
                              10196                 :             {
                              10197               3 :                 Const      *con = (Const *) linitial(expr->args);
                              10198                 : 
                              10199               3 :                 Assert(IsA(con, Const) &&
                              10200                 :                        con->consttype == TEXTOID &&
                              10201                 :                        !con->constisnull);
                              10202               3 :                 appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
                              10203                 :             }
                              10204               3 :             appendStringInfoString(buf, " FROM ");
  733 peter                   10205 CBC           3 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
                              10206               3 :             appendStringInfoChar(buf, ')');
                              10207               3 :             return true;
  733 peter                   10208 ECB             : 
  886 tgl                     10209 CBC           6 :         case F_IS_NORMALIZED:
  886 tgl                     10210 ECB             :             /* IS xxx NORMALIZED */
  129 tgl                     10211 CBC           6 :             appendStringInfoString(buf, "(");
                              10212               6 :             get_rule_expr_paren((Node *) linitial(expr->args), context, false,
  129 tgl                     10213 ECB             :                                 (Node *) expr);
  129 tgl                     10214 CBC           6 :             appendStringInfoString(buf, " IS");
  886 tgl                     10215 GIC           6 :             if (list_length(expr->args) == 2)
  886 tgl                     10216 ECB             :             {
  886 tgl                     10217 GIC           3 :                 Const      *con = (Const *) lsecond(expr->args);
                              10218                 : 
                              10219               3 :                 Assert(IsA(con, Const) &&
                              10220                 :                        con->consttype == TEXTOID &&
                              10221                 :                        !con->constisnull);
                              10222               3 :                 appendStringInfo(buf, " %s",
  886 tgl                     10223 CBC           3 :                                  TextDatumGetCString(con->constvalue));
                              10224                 :             }
                              10225               6 :             appendStringInfoString(buf, " NORMALIZED)");
  886 tgl                     10226 GIC           6 :             return true;
  886 tgl                     10227 ECB             : 
  886 tgl                     10228 GIC           3 :         case F_PG_COLLATION_FOR:
                              10229                 :             /* COLLATION FOR */
  886 tgl                     10230 CBC           3 :             appendStringInfoString(buf, "COLLATION FOR (");
  886 tgl                     10231 GIC           3 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10232 CBC           3 :             appendStringInfoChar(buf, ')');
                              10233               3 :             return true;
  886 tgl                     10234 ECB             : 
  886 tgl                     10235 CBC           6 :         case F_NORMALIZE:
                              10236                 :             /* NORMALIZE() */
                              10237               6 :             appendStringInfoString(buf, "NORMALIZE(");
  886 tgl                     10238 GIC           6 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10239 CBC           6 :             if (list_length(expr->args) == 2)
  886 tgl                     10240 ECB             :             {
  886 tgl                     10241 GIC           3 :                 Const      *con = (Const *) lsecond(expr->args);
  886 tgl                     10242 ECB             : 
  886 tgl                     10243 CBC           3 :                 Assert(IsA(con, Const) &&
                              10244                 :                        con->consttype == TEXTOID &&
  886 tgl                     10245 ECB             :                        !con->constisnull);
  886 tgl                     10246 GIC           3 :                 appendStringInfo(buf, ", %s",
  886 tgl                     10247 CBC           3 :                                  TextDatumGetCString(con->constvalue));
                              10248                 :             }
  886 tgl                     10249 GIC           6 :             appendStringInfoChar(buf, ')');
  886 tgl                     10250 CBC           6 :             return true;
  886 tgl                     10251 ECB             : 
  886 tgl                     10252 GIC           6 :         case F_OVERLAY_BIT_BIT_INT4:
  886 tgl                     10253 ECB             :         case F_OVERLAY_BIT_BIT_INT4_INT4:
                              10254                 :         case F_OVERLAY_BYTEA_BYTEA_INT4:
                              10255                 :         case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
                              10256                 :         case F_OVERLAY_TEXT_TEXT_INT4:
                              10257                 :         case F_OVERLAY_TEXT_TEXT_INT4_INT4:
                              10258                 :             /* OVERLAY() */
  886 tgl                     10259 CBC           6 :             appendStringInfoString(buf, "OVERLAY(");
                              10260               6 :             get_rule_expr((Node *) linitial(expr->args), context, false);
                              10261               6 :             appendStringInfoString(buf, " PLACING ");
  886 tgl                     10262 GIC           6 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10263 CBC           6 :             appendStringInfoString(buf, " FROM ");
  886 tgl                     10264 GIC           6 :             get_rule_expr((Node *) lthird(expr->args), context, false);
  886 tgl                     10265 CBC           6 :             if (list_length(expr->args) == 4)
  886 tgl                     10266 ECB             :             {
  886 tgl                     10267 CBC           3 :                 appendStringInfoString(buf, " FOR ");
  886 tgl                     10268 GIC           3 :                 get_rule_expr((Node *) lfourth(expr->args), context, false);
  886 tgl                     10269 ECB             :             }
  886 tgl                     10270 GIC           6 :             appendStringInfoChar(buf, ')');
  886 tgl                     10271 CBC           6 :             return true;
                              10272                 : 
  886 tgl                     10273 GIC           3 :         case F_POSITION_BIT_BIT:
  886 tgl                     10274 ECB             :         case F_POSITION_BYTEA_BYTEA:
                              10275                 :         case F_POSITION_TEXT_TEXT:
                              10276                 :             /* POSITION() ... extra parens since args are b_expr not a_expr */
  886 tgl                     10277 CBC           3 :             appendStringInfoString(buf, "POSITION((");
                              10278               3 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10279 GIC           3 :             appendStringInfoString(buf, ") IN (");
  886 tgl                     10280 CBC           3 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10281 GIC           3 :             appendStringInfoString(buf, "))");
                              10282               3 :             return true;
                              10283                 : 
                              10284               3 :         case F_SUBSTRING_BIT_INT4:
                              10285                 :         case F_SUBSTRING_BIT_INT4_INT4:
                              10286                 :         case F_SUBSTRING_BYTEA_INT4:
  886 tgl                     10287 ECB             :         case F_SUBSTRING_BYTEA_INT4_INT4:
                              10288                 :         case F_SUBSTRING_TEXT_INT4:
                              10289                 :         case F_SUBSTRING_TEXT_INT4_INT4:
                              10290                 :             /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
  886 tgl                     10291 CBC           3 :             appendStringInfoString(buf, "SUBSTRING(");
                              10292               3 :             get_rule_expr((Node *) linitial(expr->args), context, false);
                              10293               3 :             appendStringInfoString(buf, " FROM ");
  886 tgl                     10294 GIC           3 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10295 CBC           3 :             if (list_length(expr->args) == 3)
  886 tgl                     10296 ECB             :             {
  886 tgl                     10297 GIC           3 :                 appendStringInfoString(buf, " FOR ");
  886 tgl                     10298 CBC           3 :                 get_rule_expr((Node *) lthird(expr->args), context, false);
  886 tgl                     10299 ECB             :             }
  886 tgl                     10300 GIC           3 :             appendStringInfoChar(buf, ')');
  886 tgl                     10301 CBC           3 :             return true;
                              10302                 : 
  886 tgl                     10303 GIC           3 :         case F_SUBSTRING_TEXT_TEXT_TEXT:
                              10304                 :             /* SUBSTRING SIMILAR/ESCAPE */
  886 tgl                     10305 CBC           3 :             appendStringInfoString(buf, "SUBSTRING(");
                              10306               3 :             get_rule_expr((Node *) linitial(expr->args), context, false);
                              10307               3 :             appendStringInfoString(buf, " SIMILAR ");
                              10308               3 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
                              10309               3 :             appendStringInfoString(buf, " ESCAPE ");
                              10310               3 :             get_rule_expr((Node *) lthird(expr->args), context, false);
  886 tgl                     10311 GIC           3 :             appendStringInfoChar(buf, ')');
  886 tgl                     10312 CBC           3 :             return true;
                              10313                 : 
  886 tgl                     10314 GIC           6 :         case F_BTRIM_BYTEA_BYTEA:
                              10315                 :         case F_BTRIM_TEXT:
                              10316                 :         case F_BTRIM_TEXT_TEXT:
                              10317                 :             /* TRIM() */
                              10318               6 :             appendStringInfoString(buf, "TRIM(BOTH");
  886 tgl                     10319 CBC           6 :             if (list_length(expr->args) == 2)
  886 tgl                     10320 ECB             :             {
  886 tgl                     10321 CBC           6 :                 appendStringInfoChar(buf, ' ');
                              10322               6 :                 get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10323 ECB             :             }
  886 tgl                     10324 GIC           6 :             appendStringInfoString(buf, " FROM ");
  886 tgl                     10325 CBC           6 :             get_rule_expr((Node *) linitial(expr->args), context, false);
                              10326               6 :             appendStringInfoChar(buf, ')');
  886 tgl                     10327 GIC           6 :             return true;
  886 tgl                     10328 ECB             : 
  811 tgl                     10329 CBC           6 :         case F_LTRIM_BYTEA_BYTEA:
                              10330                 :         case F_LTRIM_TEXT:
  886 tgl                     10331 ECB             :         case F_LTRIM_TEXT_TEXT:
                              10332                 :             /* TRIM() */
  886 tgl                     10333 CBC           6 :             appendStringInfoString(buf, "TRIM(LEADING");
                              10334               6 :             if (list_length(expr->args) == 2)
  886 tgl                     10335 ECB             :             {
  886 tgl                     10336 CBC           6 :                 appendStringInfoChar(buf, ' ');
                              10337               6 :                 get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10338 ECB             :             }
  886 tgl                     10339 CBC           6 :             appendStringInfoString(buf, " FROM ");
                              10340               6 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10341 GIC           6 :             appendStringInfoChar(buf, ')');
  886 tgl                     10342 CBC           6 :             return true;
                              10343                 : 
  811 tgl                     10344 GIC           6 :         case F_RTRIM_BYTEA_BYTEA:
                              10345                 :         case F_RTRIM_TEXT:
  886 tgl                     10346 ECB             :         case F_RTRIM_TEXT_TEXT:
                              10347                 :             /* TRIM() */
  886 tgl                     10348 GIC           6 :             appendStringInfoString(buf, "TRIM(TRAILING");
  886 tgl                     10349 CBC           6 :             if (list_length(expr->args) == 2)
  886 tgl                     10350 ECB             :             {
  886 tgl                     10351 GIC           3 :                 appendStringInfoChar(buf, ' ');
  886 tgl                     10352 CBC           3 :                 get_rule_expr((Node *) lsecond(expr->args), context, false);
  886 tgl                     10353 ECB             :             }
  886 tgl                     10354 CBC           6 :             appendStringInfoString(buf, " FROM ");
                              10355               6 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10356 GIC           6 :             appendStringInfoChar(buf, ')');
  886 tgl                     10357 CBC           6 :             return true;
                              10358                 : 
  140 michael                 10359 GNC           6 :         case F_CURRENT_CATALOG:
                              10360               6 :             appendStringInfoString(buf, "CURRENT_CATALOG");
                              10361               6 :             return true;
                              10362               6 :         case F_CURRENT_ROLE:
                              10363               6 :             appendStringInfoString(buf, "CURRENT_ROLE");
                              10364               6 :             return true;
                              10365               6 :         case F_CURRENT_SCHEMA:
                              10366               6 :             appendStringInfoString(buf, "CURRENT_SCHEMA");
                              10367               6 :             return true;
                              10368             141 :         case F_CURRENT_USER:
                              10369             141 :             appendStringInfoString(buf, "CURRENT_USER");
                              10370             141 :             return true;
                              10371               6 :         case F_USER:
                              10372               6 :             appendStringInfoString(buf, "USER");
                              10373               6 :             return true;
                              10374              16 :         case F_SESSION_USER:
                              10375              16 :             appendStringInfoString(buf, "SESSION_USER");
                              10376              16 :             return true;
  192                         10377               6 :         case F_SYSTEM_USER:
                              10378               6 :             appendStringInfoString(buf, "SYSTEM_USER");
                              10379               6 :             return true;
                              10380                 : 
  139                         10381               9 :         case F_CURRENT_DATE:
                              10382               9 :             appendStringInfoString(buf, "CURRENT_DATE");
                              10383               9 :             return true;
                              10384              12 :         case F_CURRENT_TIME:
                              10385              12 :             appendStringInfoString(buf, "CURRENT_TIME");
                              10386              12 :             get_func_sql_syntax_time(expr->args, context);
                              10387              12 :             return true;
                              10388             318 :         case F_CURRENT_TIMESTAMP:
                              10389             318 :             appendStringInfoString(buf, "CURRENT_TIMESTAMP");
                              10390             318 :             get_func_sql_syntax_time(expr->args, context);
                              10391             318 :             return true;
                              10392              12 :         case F_LOCALTIME:
                              10393              12 :             appendStringInfoString(buf, "LOCALTIME");
                              10394              12 :             get_func_sql_syntax_time(expr->args, context);
                              10395              12 :             return true;
                              10396              24 :         case F_LOCALTIMESTAMP:
                              10397              24 :             appendStringInfoString(buf, "LOCALTIMESTAMP");
                              10398              24 :             get_func_sql_syntax_time(expr->args, context);
                              10399              24 :             return true;
                              10400                 : 
  886 tgl                     10401 UIC           0 :         case F_XMLEXISTS:
                              10402                 :             /* XMLEXISTS ... extra parens because args are c_expr */
  886 tgl                     10403 LBC           0 :             appendStringInfoString(buf, "XMLEXISTS((");
                              10404               0 :             get_rule_expr((Node *) linitial(expr->args), context, false);
  886 tgl                     10405 UIC           0 :             appendStringInfoString(buf, ") PASSING (");
  886 tgl                     10406 LBC           0 :             get_rule_expr((Node *) lsecond(expr->args), context, false);
                              10407               0 :             appendStringInfoString(buf, "))");
  886 tgl                     10408 UIC           0 :             return true;
  886 tgl                     10409 ECB             :     }
  886 tgl                     10410 CBC           3 :     return false;
  886 tgl                     10411 ECB             : }
                              10412                 : 
                              10413                 : /* ----------
 5867                         10414                 :  * get_coercion_expr
                              10415                 :  *
                              10416                 :  *  Make a string representation of a value coerced to a specific type
                              10417                 :  * ----------
                              10418                 :  */
                              10419                 : static void
 5867 tgl                     10420 GIC        1999 : get_coercion_expr(Node *arg, deparse_context *context,
 5867 tgl                     10421 ECB             :                   Oid resulttype, int32 resulttypmod,
                              10422                 :                   Node *parentNode)
                              10423                 : {
 5867 tgl                     10424 CBC        1999 :     StringInfo  buf = context->buf;
 5867 tgl                     10425 ECB             : 
                              10426                 :     /*
                              10427                 :      * Since parse_coerce.c doesn't immediately collapse application of
                              10428                 :      * length-coercion functions to constants, what we'll typically see in
 5624 bruce                   10429                 :      * such cases is a Const with typmod -1 and a length-coercion function
 3260                         10430                 :      * right above it.  Avoid generating redundant output. However, beware of
 5624                         10431                 :      * suppressing casts when the user actually wrote something like
                              10432                 :      * 'foo'::text::char(3).
 2932 tgl                     10433                 :      *
                              10434                 :      * Note: it might seem that we are missing the possibility of needing to
                              10435                 :      * print a COLLATE clause for such a Const.  However, a Const could only
                              10436                 :      * have nondefault collation in a post-constant-folding tree, in which the
                              10437                 :      * length coercion would have been folded too.  See also the special
                              10438                 :      * handling of CollateExpr in coerce_to_target_type(): any collation
                              10439                 :      * marking will be above the coercion node, not below it.
 5867                         10440                 :      */
 5867 tgl                     10441 CBC        1999 :     if (arg && IsA(arg, Const) &&
                              10442             225 :         ((Const *) arg)->consttype == resulttype &&
                              10443              12 :         ((Const *) arg)->consttypmod == -1)
 5867 tgl                     10444 ECB             :     {
                              10445                 :         /* Show the constant without normal ::typename decoration */
 5572 tgl                     10446 CBC          12 :         get_const_expr((Const *) arg, context, -1);
 5867 tgl                     10447 ECB             :     }
                              10448                 :     else
                              10449                 :     {
 5867 tgl                     10450 GIC        1987 :         if (!PRETTY_PAREN(context))
 5867 tgl                     10451 CBC        1823 :             appendStringInfoChar(buf, '(');
                              10452            1987 :         get_rule_expr_paren(arg, context, false, parentNode);
                              10453            1987 :         if (!PRETTY_PAREN(context))
                              10454            1823 :             appendStringInfoChar(buf, ')');
 5867 tgl                     10455 ECB             :     }
 1343 noah                    10456                 : 
                              10457                 :     /*
                              10458                 :      * Never emit resulttype(arg) functional notation. A pg_proc entry could
                              10459                 :      * take precedence, and a resulttype in pg_temp would require schema
                              10460                 :      * qualification that format_type_with_typemod() would usually omit. We've
                              10461                 :      * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
                              10462                 :      * would work fine.
                              10463                 :      */
 5867 tgl                     10464 CBC        1999 :     appendStringInfo(buf, "::%s",
 5867 tgl                     10465 ECB             :                      format_type_with_typemod(resulttype, resulttypmod));
 5867 tgl                     10466 CBC        1999 : }
 8994 bruce                   10467 ECB             : 
                              10468                 : /* ----------
 8590 tgl                     10469                 :  * get_const_expr
                              10470                 :  *
 8588 tgl                     10471 EUB             :  *  Make a string representation of a Const
                              10472                 :  *
 5572                         10473                 :  * showtype can be -1 to never show "::typename" decoration, or +1 to always
                              10474                 :  * show it, or 0 to show it only if the constant wouldn't be assumed to be
                              10475                 :  * the right type by default.
 4412                         10476                 :  *
                              10477                 :  * If the Const's collation isn't default for its type, show that too.
 2932                         10478                 :  * We mustn't do this when showtype is -1 (since that means the caller will
                              10479                 :  * print "::typename", and we can't put a COLLATE clause in between).  It's
 2932 tgl                     10480 ECB             :  * caller's responsibility that collation isn't missed in such cases.
                              10481                 :  * ----------
                              10482                 :  */
                              10483                 : static void
 5572 tgl                     10484 GIC       28960 : get_const_expr(Const *constval, deparse_context *context, int showtype)
                              10485                 : {
 8589                         10486           28960 :     StringInfo  buf = context->buf;
                              10487                 :     Oid         typoutput;
                              10488                 :     bool        typIsVarlena;
                              10489                 :     char       *extval;
 2932 tgl                     10490 CBC       28960 :     bool        needlabel = false;
                              10491                 : 
 8507 tgl                     10492 GIC       28960 :     if (constval->constisnull)
                              10493                 :     {
 8507 tgl                     10494 ECB             :         /*
                              10495                 :          * Always label the type of a NULL constant to prevent misdecisions
                              10496                 :          * about type when reparsing.
                              10497                 :          */
 3447 rhaas                   10498 GIC         360 :         appendStringInfoString(buf, "NULL");
 5572 tgl                     10499             360 :         if (showtype >= 0)
                              10500                 :         {
 5867                         10501             338 :             appendStringInfo(buf, "::%s",
                              10502                 :                              format_type_with_typemod(constval->consttype,
                              10503                 :                                                       constval->consttypmod));
 4412                         10504             338 :             get_const_collation(constval, context);
                              10505                 :         }
 8507                         10506            3555 :         return;
                              10507                 :     }
                              10508                 : 
 6881                         10509           28600 :     getTypeOutputInfo(constval->consttype,
                              10510                 :                       &typoutput, &typIsVarlena);
 7651 tgl                     10511 ECB             : 
 6214 tgl                     10512 CBC       28600 :     extval = OidOutputFunctionCall(typoutput, constval->constvalue);
 8994 bruce                   10513 ECB             : 
 8588 tgl                     10514 GIC       28600 :     switch (constval->consttype)
                              10515                 :     {
 8588 tgl                     10516 CBC       16499 :         case INT4OID:
                              10517                 : 
                              10518                 :             /*
                              10519                 :              * INT4 can be printed without any decoration, unless it is
 2932 tgl                     10520 ECB             :              * negative; in that case print it as '-nnn'::integer to ensure
                              10521                 :              * that the output will re-parse as a constant, not as a constant
                              10522                 :              * plus operator.  In most cases we could get away with printing
                              10523                 :              * (-nnn) instead, because of the way that gram.y handles negative
                              10524                 :              * literals; but that doesn't work for INT_MIN, and it doesn't
                              10525                 :              * seem that much prettier anyway.
                              10526                 :              */
 2932 tgl                     10527 GIC       16499 :             if (extval[0] != '-')
                              10528           16243 :                 appendStringInfoString(buf, extval);
                              10529                 :             else
                              10530                 :             {
                              10531             256 :                 appendStringInfo(buf, "'%s'", extval);
 2118                         10532             256 :                 needlabel = true;   /* we must attach a cast */
                              10533                 :             }
 2932 tgl                     10534 CBC       16499 :             break;
                              10535                 : 
 7539 peter_e                 10536             508 :         case NUMERICOID:
                              10537                 : 
                              10538                 :             /*
                              10539                 :              * NUMERIC can be printed without quotes if it looks like a float
                              10540                 :              * constant (not an integer, and not Infinity or NaN) and doesn't
                              10541                 :              * have a leading sign (for the same reason as for INT4).
                              10542                 :              */
 2932 tgl                     10543 GIC         508 :             if (isdigit((unsigned char) extval[0]) &&
                              10544             508 :                 strcspn(extval, "eE.") != strlen(extval))
                              10545                 :             {
                              10546             180 :                 appendStringInfoString(buf, extval);
                              10547                 :             }
                              10548                 :             else
                              10549                 :             {
                              10550             328 :                 appendStringInfo(buf, "'%s'", extval);
 2118                         10551             328 :                 needlabel = true;   /* we must attach a cast */
                              10552                 :             }
 7522 bruce                   10553             508 :             break;
 7539 peter_e                 10554 ECB             : 
 7539 peter_e                 10555 GIC         669 :         case BOOLOID:
 7522 bruce                   10556 CBC         669 :             if (strcmp(extval, "t") == 0)
 3447 rhaas                   10557 GIC         354 :                 appendStringInfoString(buf, "true");
                              10558                 :             else
                              10559             315 :                 appendStringInfoString(buf, "false");
 7539 peter_e                 10560 CBC         669 :             break;
                              10561                 : 
                              10562           10924 :         default:
 5328 tgl                     10563 GIC       10924 :             simple_quote_literal(buf, extval);
 8588                         10564           10924 :             break;
                              10565                 :     }
                              10566                 : 
 8590                         10567           28600 :     pfree(extval);
 8588 tgl                     10568 ECB             : 
 5572 tgl                     10569 CBC       28600 :     if (showtype < 0)
 5867 tgl                     10570 GIC        3195 :         return;
 5867 tgl                     10571 ECB             : 
                              10572                 :     /*
                              10573                 :      * For showtype == 0, append ::typename unless the constant will be
 5572                         10574                 :      * implicitly typed as the right type when it is read in.
                              10575                 :      *
                              10576                 :      * XXX this code has to be kept in sync with the behavior of the parser,
                              10577                 :      * especially make_const.
                              10578                 :      */
 8588 tgl                     10579 CBC       25405 :     switch (constval->consttype)
                              10580                 :     {
 7539 peter_e                 10581 GIC         685 :         case BOOLOID:
 8588 tgl                     10582 ECB             :         case UNKNOWNOID:
                              10583                 :             /* These types can be left unlabeled */
 7508 tgl                     10584 CBC         685 :             needlabel = false;
 7508 tgl                     10585 GIC         685 :             break;
 2932 tgl                     10586 CBC       14466 :         case INT4OID:
                              10587                 :             /* We determined above whether a label is needed */
 2932 tgl                     10588 GIC       14466 :             break;
 7508                         10589             508 :         case NUMERICOID:
                              10590                 : 
                              10591                 :             /*
                              10592                 :              * Float-looking constants will be typed as numeric, which we
                              10593                 :              * checked above; but if there's a nondefault typmod we need to
                              10594                 :              * show it.
                              10595                 :              */
 2932                         10596             508 :             needlabel |= (constval->consttypmod >= 0);
 8588 tgl                     10597 CBC         508 :             break;
                              10598            9746 :         default:
 7508 tgl                     10599 GIC        9746 :             needlabel = true;
 8588                         10600            9746 :             break;
 8588 tgl                     10601 ECB             :     }
 5572 tgl                     10602 CBC       25405 :     if (needlabel || showtype > 0)
 7508 tgl                     10603 GIC       10323 :         appendStringInfo(buf, "::%s",
 5867 tgl                     10604 ECB             :                          format_type_with_typemod(constval->consttype,
                              10605                 :                                                   constval->consttypmod));
 4412                         10606                 : 
 4412 tgl                     10607 GIC       25405 :     get_const_collation(constval, context);
                              10608                 : }
                              10609                 : 
                              10610                 : /*
                              10611                 :  * helper for get_const_expr: append COLLATE if needed
                              10612                 :  */
 4412 tgl                     10613 ECB             : static void
 4412 tgl                     10614 CBC       25743 : get_const_collation(Const *constval, deparse_context *context)
                              10615                 : {
                              10616           25743 :     StringInfo  buf = context->buf;
                              10617                 : 
 4412 tgl                     10618 GIC       25743 :     if (OidIsValid(constval->constcollid))
                              10619                 :     {
 4382 bruce                   10620 CBC        3672 :         Oid         typcollation = get_typcollation(constval->consttype);
 4412 tgl                     10621 ECB             : 
 4412 tgl                     10622 GIC        3672 :         if (constval->constcollid != typcollation)
 4412 tgl                     10623 ECB             :         {
 4412 tgl                     10624 GIC          35 :             appendStringInfo(buf, " COLLATE %s",
 4412 tgl                     10625 ECB             :                              generate_collation_name(constval->constcollid));
                              10626                 :         }
                              10627                 :     }
 8955 bruce                   10628 GIC       25743 : }
 8955 bruce                   10629 ECB             : 
                              10630                 : /*
                              10631                 :  * get_json_format          - Parse back a JsonFormat node
                              10632                 :  */
                              10633                 : static void
   11 alvherre                10634 GNC          24 : get_json_format(JsonFormat *format, StringInfo buf)
                              10635                 : {
                              10636              24 :     if (format->format_type == JS_FORMAT_DEFAULT)
   11 alvherre                10637 UNC           0 :         return;
                              10638                 : 
   11 alvherre                10639 GNC          24 :     appendStringInfoString(buf,
                              10640              24 :                            format->format_type == JS_FORMAT_JSONB ?
                              10641                 :                            " FORMAT JSONB" : " FORMAT JSON");
                              10642                 : 
                              10643              24 :     if (format->encoding != JS_ENC_DEFAULT)
                              10644                 :     {
                              10645                 :         const char *encoding;
                              10646                 : 
   11 alvherre                10647 UNC           0 :         encoding =
                              10648               0 :             format->encoding == JS_ENC_UTF16 ? "UTF16" :
                              10649               0 :             format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
                              10650                 : 
                              10651               0 :         appendStringInfo(buf, " ENCODING %s", encoding);
                              10652                 :     }
                              10653                 : }
                              10654                 : 
                              10655                 : /*
                              10656                 :  * get_json_returning       - Parse back a JsonReturning structure
                              10657                 :  */
                              10658                 : static void
   11 alvherre                10659 GNC          36 : get_json_returning(JsonReturning *returning, StringInfo buf,
                              10660                 :                    bool json_format_by_default)
                              10661                 : {
                              10662              36 :     if (!OidIsValid(returning->typid))
   11 alvherre                10663 UNC           0 :         return;
                              10664                 : 
   11 alvherre                10665 GNC          36 :     appendStringInfo(buf, " RETURNING %s",
                              10666                 :                      format_type_with_typemod(returning->typid,
                              10667                 :                                               returning->typmod));
                              10668                 : 
                              10669              72 :     if (!json_format_by_default ||
                              10670              36 :         returning->format->format_type !=
                              10671              36 :         (returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
   11 alvherre                10672 UNC           0 :         get_json_format(returning->format, buf);
                              10673                 : }
                              10674                 : 
                              10675                 : /*
                              10676                 :  * get_json_constructor     - Parse back a JsonConstructorExpr node
                              10677                 :  */
                              10678                 : static void
   11 alvherre                10679 GNC          36 : get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context,
                              10680                 :                      bool showimplicit)
                              10681                 : {
                              10682              36 :     StringInfo  buf = context->buf;
                              10683                 :     const char *funcname;
                              10684                 :     bool        is_json_object;
                              10685                 :     int         curridx;
                              10686                 :     ListCell   *lc;
                              10687                 : 
                              10688              36 :     if (ctor->type == JSCTOR_JSON_OBJECTAGG)
                              10689                 :     {
                              10690               9 :         get_json_agg_constructor(ctor, context, "JSON_OBJECTAGG", true);
                              10691               9 :         return;
                              10692                 :     }
                              10693              27 :     else if (ctor->type == JSCTOR_JSON_ARRAYAGG)
                              10694                 :     {
                              10695              15 :         get_json_agg_constructor(ctor, context, "JSON_ARRAYAGG", false);
                              10696              15 :         return;
                              10697                 :     }
                              10698                 : 
                              10699              12 :     switch (ctor->type)
                              10700                 :     {
                              10701               6 :         case JSCTOR_JSON_OBJECT:
                              10702               6 :             funcname = "JSON_OBJECT";
                              10703               6 :             break;
                              10704               6 :         case JSCTOR_JSON_ARRAY:
                              10705               6 :             funcname = "JSON_ARRAY";
                              10706               6 :             break;
   11 alvherre                10707 UNC           0 :         default:
   10                         10708               0 :             elog(ERROR, "invalid JsonConstructorType %d", ctor->type);
                              10709                 :     }
                              10710                 : 
   11 alvherre                10711 GNC          12 :     appendStringInfo(buf, "%s(", funcname);
                              10712                 : 
                              10713              12 :     is_json_object = ctor->type == JSCTOR_JSON_OBJECT;
                              10714              48 :     foreach(lc, ctor->args)
                              10715                 :     {
                              10716              36 :         curridx = foreach_current_index(lc);
                              10717              36 :         if (curridx > 0)
                              10718                 :         {
                              10719                 :             const char *sep;
                              10720                 : 
                              10721              24 :             sep = (is_json_object && (curridx % 2) != 0) ? " : " : ", ";
                              10722              24 :             appendStringInfoString(buf, sep);
                              10723                 :         }
                              10724                 : 
                              10725              36 :         get_rule_expr((Node *) lfirst(lc), context, true);
                              10726                 :     }
                              10727                 : 
                              10728              12 :     get_json_constructor_options(ctor, buf);
                              10729              12 :     appendStringInfo(buf, ")");
                              10730                 : }
                              10731                 : 
                              10732                 : /*
                              10733                 :  * Append options, if any, to the JSON constructor being deparsed
                              10734                 :  */
                              10735                 : static void
                              10736              36 : get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
                              10737                 : {
                              10738              36 :     if (ctor->absent_on_null)
                              10739                 :     {
                              10740              12 :         if (ctor->type == JSCTOR_JSON_OBJECT ||
                              10741              12 :             ctor->type == JSCTOR_JSON_OBJECTAGG)
   11 alvherre                10742 UNC           0 :             appendStringInfoString(buf, " ABSENT ON NULL");
                              10743                 :     }
                              10744                 :     else
                              10745                 :     {
   11 alvherre                10746 GNC          24 :         if (ctor->type == JSCTOR_JSON_ARRAY ||
                              10747              24 :             ctor->type == JSCTOR_JSON_ARRAYAGG)
                              10748               9 :             appendStringInfoString(buf, " NULL ON NULL");
                              10749                 :     }
                              10750                 : 
                              10751              36 :     if (ctor->unique)
                              10752               9 :         appendStringInfoString(buf, " WITH UNIQUE KEYS");
                              10753                 : 
                              10754              36 :     get_json_returning(ctor->returning, buf, true);
                              10755              36 : }
                              10756                 : 
                              10757                 : /*
                              10758                 :  * get_json_agg_constructor - Parse back an aggregate JsonConstructorExpr node
                              10759                 :  */
                              10760                 : static void
                              10761              24 : get_json_agg_constructor(JsonConstructorExpr *ctor, deparse_context *context,
                              10762                 :                          const char *funcname, bool is_json_objectagg)
                              10763                 : {
                              10764                 :     StringInfoData options;
                              10765                 : 
                              10766              24 :     initStringInfo(&options);
                              10767              24 :     get_json_constructor_options(ctor, &options);
                              10768                 : 
                              10769              24 :     if (IsA(ctor->func, Aggref))
                              10770              18 :         get_agg_expr_helper((Aggref *) ctor->func, context,
                              10771              18 :                             (Aggref *) ctor->func,
                              10772              18 :                             funcname, options.data, is_json_objectagg);
                              10773               6 :     else if (IsA(ctor->func, WindowFunc))
                              10774               6 :         get_windowfunc_expr_helper((WindowFunc *) ctor->func, context,
                              10775               6 :                                    funcname, options.data,
                              10776                 :                                    is_json_objectagg);
                              10777                 :     else
   11 alvherre                10778 UNC           0 :         elog(ERROR, "invalid JsonConstructorExpr underlying node type: %d",
                              10779                 :              nodeTag(ctor->func));
   11 alvherre                10780 GNC          24 : }
                              10781                 : 
 5328 tgl                     10782 ECB             : /*
                              10783                 :  * simple_quote_literal - Format a string as a SQL literal, append to buf
                              10784                 :  */
                              10785                 : static void
 5328 tgl                     10786 CBC       11451 : simple_quote_literal(StringInfo buf, const char *val)
                              10787                 : {
                              10788                 :     const char *valptr;
 5328 tgl                     10789 ECB             : 
                              10790                 :     /*
 5050 bruce                   10791                 :      * We form the string literal according to the prevailing setting of
                              10792                 :      * standard_conforming_strings; we never use E''. User is responsible for
                              10793                 :      * making sure result is used correctly.
                              10794                 :      */
 5328 tgl                     10795 GIC       11451 :     appendStringInfoChar(buf, '\'');
                              10796          118056 :     for (valptr = val; *valptr; valptr++)
                              10797                 :     {
                              10798          106605 :         char        ch = *valptr;
                              10799                 : 
                              10800          106605 :         if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
 5328 tgl                     10801 CBC         153 :             appendStringInfoChar(buf, ch);
 5328 tgl                     10802 GIC      106605 :         appendStringInfoChar(buf, ch);
 5328 tgl                     10803 ECB             :     }
 5328 tgl                     10804 GIC       11451 :     appendStringInfoChar(buf, '\'');
                              10805           11451 : }
 5328 tgl                     10806 ECB             : 
 8955 bruce                   10807                 : 
                              10808                 : /* ----------
                              10809                 :  * get_sublink_expr         - Parse back a sublink
                              10810                 :  * ----------
                              10811                 :  */
                              10812                 : static void
 7423 tgl                     10813 GIC         191 : get_sublink_expr(SubLink *sublink, deparse_context *context)
                              10814                 : {
 8589                         10815             191 :     StringInfo  buf = context->buf;
 8955 bruce                   10816             191 :     Query      *query = (Query *) (sublink->subselect);
 6311 tgl                     10817             191 :     char       *opname = NULL;
 8546 tgl                     10818 ECB             :     bool        need_paren;
 8955 bruce                   10819                 : 
 7306 tgl                     10820 CBC         191 :     if (sublink->subLinkType == ARRAY_SUBLINK)
 3447 rhaas                   10821               6 :         appendStringInfoString(buf, "ARRAY(");
 7306 tgl                     10822 ECB             :     else
 7306 tgl                     10823 GIC         185 :         appendStringInfoChar(buf, '(');
 8625 tgl                     10824 ECB             : 
 6311                         10825                 :     /*
                              10826                 :      * Note that we print the name of only the first operator, when there are
                              10827                 :      * multiple combining operators.  This is an approximation that could go
                              10828                 :      * wrong in various scenarios (operators in different schemas, renamed
 6031 bruce                   10829                 :      * operators, etc) but there is not a whole lot we can do about it, since
                              10830                 :      * the syntax allows only one operator to be shown.
                              10831                 :      */
 6311 tgl                     10832 GIC         191 :     if (sublink->testexpr)
                              10833                 :     {
                              10834               9 :         if (IsA(sublink->testexpr, OpExpr))
                              10835                 :         {
 6311 tgl                     10836 ECB             :             /* single combining operator */
 6031 bruce                   10837 GIC           3 :             OpExpr     *opexpr = (OpExpr *) sublink->testexpr;
 6311 tgl                     10838 ECB             : 
 6311 tgl                     10839 GIC           3 :             get_rule_expr(linitial(opexpr->args), context, true);
 6311 tgl                     10840 CBC           3 :             opname = generate_operator_name(opexpr->opno,
 6311 tgl                     10841 GIC           3 :                                             exprType(linitial(opexpr->args)),
 6311 tgl                     10842 CBC           3 :                                             exprType(lsecond(opexpr->args)));
                              10843                 :         }
                              10844               6 :         else if (IsA(sublink->testexpr, BoolExpr))
                              10845                 :         {
 6311 tgl                     10846 ECB             :             /* multiple combining operators, = or <> cases */
                              10847                 :             char       *sep;
                              10848                 :             ListCell   *l;
                              10849                 : 
 8449 tgl                     10850 CBC           3 :             appendStringInfoChar(buf, '(');
 6311 tgl                     10851 GIC           3 :             sep = "";
                              10852               9 :             foreach(l, ((BoolExpr *) sublink->testexpr)->args)
                              10853                 :             {
 2190                         10854               6 :                 OpExpr     *opexpr = lfirst_node(OpExpr, l);
                              10855                 : 
 6311 tgl                     10856 CBC           6 :                 appendStringInfoString(buf, sep);
 6311 tgl                     10857 GIC           6 :                 get_rule_expr(linitial(opexpr->args), context, true);
 6311 tgl                     10858 CBC           6 :                 if (!opname)
 6311 tgl                     10859 GBC           3 :                     opname = generate_operator_name(opexpr->opno,
 2118 tgl                     10860 GIC           3 :                                                     exprType(linitial(opexpr->args)),
 2118 tgl                     10861 CBC           3 :                                                     exprType(lsecond(opexpr->args)));
 6311                         10862               6 :                 sep = ", ";
                              10863                 :             }
 6758 tgl                     10864 GIC           3 :             appendStringInfoChar(buf, ')');
 6311 tgl                     10865 ECB             :         }
 6311 tgl                     10866 GIC           3 :         else if (IsA(sublink->testexpr, RowCompareExpr))
                              10867                 :         {
                              10868                 :             /* multiple combining operators, < <= > >= cases */
 6311 tgl                     10869 GBC           3 :             RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
 6311 tgl                     10870 EUB             : 
 6311 tgl                     10871 GBC           3 :             appendStringInfoChar(buf, '(');
 6311 tgl                     10872 GIC           3 :             get_rule_expr((Node *) rcexpr->largs, context, true);
 6311 tgl                     10873 GBC           3 :             opname = generate_operator_name(linitial_oid(rcexpr->opnos),
 6311 tgl                     10874 GIC           3 :                                             exprType(linitial(rcexpr->largs)),
 2118                         10875               3 :                                             exprType(linitial(rcexpr->rargs)));
 6311                         10876               3 :             appendStringInfoChar(buf, ')');
                              10877                 :         }
                              10878                 :         else
 6311 tgl                     10879 UIC           0 :             elog(ERROR, "unrecognized testexpr type: %d",
                              10880                 :                  (int) nodeTag(sublink->testexpr));
 8955 bruce                   10881 ECB             :     }
                              10882                 : 
 8546 tgl                     10883 GIC         191 :     need_paren = true;
 8546 tgl                     10884 ECB             : 
 8720 bruce                   10885 GBC         191 :     switch (sublink->subLinkType)
                              10886                 :     {
 8955 bruce                   10887 CBC          85 :         case EXISTS_SUBLINK:
 3447 rhaas                   10888 GIC          85 :             appendStringInfoString(buf, "EXISTS ");
 8955 bruce                   10889              85 :             break;
                              10890                 : 
 8955 bruce                   10891 CBC           6 :         case ANY_SUBLINK:
 2118 tgl                     10892               6 :             if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
 3447 rhaas                   10893               3 :                 appendStringInfoString(buf, " IN ");
 7395 tgl                     10894 EUB             :             else
 6311 tgl                     10895 GIC           3 :                 appendStringInfo(buf, " %s ANY ", opname);
 8955 bruce                   10896               6 :             break;
                              10897                 : 
                              10898               3 :         case ALL_SUBLINK:
 6311 tgl                     10899               3 :             appendStringInfo(buf, " %s ALL ", opname);
 8955 bruce                   10900               3 :             break;
 8955 bruce                   10901 ECB             : 
 6311 tgl                     10902 UIC           0 :         case ROWCOMPARE_SUBLINK:
                              10903               0 :             appendStringInfo(buf, " %s ", opname);
 8955 bruce                   10904 LBC           0 :             break;
                              10905                 : 
 8546 tgl                     10906 GIC          97 :         case EXPR_SUBLINK:
                              10907                 :         case MULTIEXPR_SUBLINK:
                              10908                 :         case ARRAY_SUBLINK:
                              10909              97 :             need_paren = false;
 8546 tgl                     10910 CBC          97 :             break;
                              10911                 : 
 5300 tgl                     10912 LBC           0 :         case CTE_SUBLINK:       /* shouldn't occur in a SubLink */
 8955 bruce                   10913 ECB             :         default:
 7196 tgl                     10914 UIC           0 :             elog(ERROR, "unrecognized sublink type: %d",
 7196 tgl                     10915 ECB             :                  (int) sublink->subLinkType);
                              10916                 :             break;
 8955 bruce                   10917                 :     }
                              10918                 : 
 8546 tgl                     10919 GIC         191 :     if (need_paren)
 8449                         10920              94 :         appendStringInfoChar(buf, '(');
 8546 tgl                     10921 ECB             : 
  323 tgl                     10922 GIC         191 :     get_query_def(query, buf, context->namespaces, NULL, false,
 3758 tgl                     10923 ECB             :                   context->prettyFlags, context->wrapColumn,
                              10924                 :                   context->indentLevel);
 8546                         10925                 : 
 8546 tgl                     10926 CBC         191 :     if (need_paren)
 3447 rhaas                   10927              94 :         appendStringInfoString(buf, "))");
 8546 tgl                     10928 ECB             :     else
 8449 tgl                     10929 GBC          97 :         appendStringInfoChar(buf, ')');
 8994 bruce                   10930             191 : }
                              10931                 : 
                              10932                 : 
 2223 alvherre                10933 ECB             : /* ----------
                              10934                 :  * get_tablefunc            - Parse back a table function
                              10935                 :  * ----------
                              10936                 :  */
                              10937                 : static void
  220 andrew                  10938 CBC          25 : get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
 2223 alvherre                10939 ECB             : {
 2223 alvherre                10940 GIC          25 :     StringInfo  buf = context->buf;
                              10941                 : 
                              10942                 :     /* XMLTABLE is the only existing implementation.  */
  220 andrew                  10943 ECB             : 
 2223 alvherre                10944 CBC          25 :     appendStringInfoString(buf, "XMLTABLE(");
                              10945                 : 
 2223 alvherre                10946 GIC          25 :     if (tf->ns_uris != NIL)
 2223 alvherre                10947 ECB             :     {
                              10948                 :         ListCell   *lc1,
                              10949                 :                    *lc2;
 2223 alvherre                10950 CBC           5 :         bool        first = true;
 2223 alvherre                10951 ECB             : 
 2223 alvherre                10952 GIC           5 :         appendStringInfoString(buf, "XMLNAMESPACES (");
                              10953              10 :         forboth(lc1, tf->ns_uris, lc2, tf->ns_names)
                              10954                 :         {
                              10955               5 :             Node       *expr = (Node *) lfirst(lc1);
  577 peter                   10956               5 :             String     *ns_node = lfirst_node(String, lc2);
                              10957                 : 
 2223 alvherre                10958 CBC           5 :             if (!first)
 2223 alvherre                10959 UIC           0 :                 appendStringInfoString(buf, ", ");
 2223 alvherre                10960 ECB             :             else
 2223 alvherre                10961 GIC           5 :                 first = false;
 2223 alvherre                10962 ECB             : 
 1665 tgl                     10963 CBC           5 :             if (ns_node != NULL)
 2223 alvherre                10964 EUB             :             {
 2223 alvherre                10965 GIC           5 :                 get_rule_expr(expr, context, showimplicit);
 1665 tgl                     10966               5 :                 appendStringInfo(buf, " AS %s", strVal(ns_node));
                              10967                 :             }
 2223 alvherre                10968 ECB             :             else
                              10969                 :             {
 2223 alvherre                10970 LBC           0 :                 appendStringInfoString(buf, "DEFAULT ");
 2223 alvherre                10971 UIC           0 :                 get_rule_expr(expr, context, showimplicit);
                              10972                 :             }
 2223 alvherre                10973 ECB             :         }
 2223 alvherre                10974 CBC           5 :         appendStringInfoString(buf, "), ");
                              10975                 :     }
 2223 alvherre                10976 ECB             : 
 2223 alvherre                10977 CBC          25 :     appendStringInfoChar(buf, '(');
 2223 alvherre                10978 GIC          25 :     get_rule_expr((Node *) tf->rowexpr, context, showimplicit);
                              10979              25 :     appendStringInfoString(buf, ") PASSING (");
                              10980              25 :     get_rule_expr((Node *) tf->docexpr, context, showimplicit);
                              10981              25 :     appendStringInfoChar(buf, ')');
                              10982                 : 
 2223 alvherre                10983 CBC          25 :     if (tf->colexprs != NIL)
                              10984                 :     {
                              10985                 :         ListCell   *l1;
                              10986                 :         ListCell   *l2;
                              10987                 :         ListCell   *l3;
 2223 alvherre                10988 ECB             :         ListCell   *l4;
                              10989                 :         ListCell   *l5;
 2223 alvherre                10990 GIC          25 :         int         colnum = 0;
 2223 alvherre                10991 ECB             : 
 2223 alvherre                10992 CBC          25 :         appendStringInfoString(buf, " COLUMNS ");
 1501 tgl                     10993             172 :         forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods,
 1501 tgl                     10994 ECB             :                 l4, tf->colexprs, l5, tf->coldefexprs)
 2223 alvherre                10995                 :         {
 2223 alvherre                10996 CBC         147 :             char       *colname = strVal(lfirst(l1));
 1501 tgl                     10997             147 :             Oid         typid = lfirst_oid(l2);
 1501 tgl                     10998 GIC         147 :             int32       typmod = lfirst_int(l3);
                              10999             147 :             Node       *colexpr = (Node *) lfirst(l4);
 1501 tgl                     11000 GBC         147 :             Node       *coldefexpr = (Node *) lfirst(l5);
 1501 tgl                     11001 GIC         147 :             bool        ordinality = (tf->ordinalitycol == colnum);
 2223 alvherre                11002 CBC         147 :             bool        notnull = bms_is_member(colnum, tf->notnulls);
                              11003                 : 
 2223 alvherre                11004 GIC         147 :             if (colnum > 0)
                              11005             122 :                 appendStringInfoString(buf, ", ");
                              11006             147 :             colnum++;
                              11007                 : 
 2223 alvherre                11008 CBC         277 :             appendStringInfo(buf, "%s %s", quote_identifier(colname),
                              11009                 :                              ordinality ? "FOR ORDINALITY" :
 2223 alvherre                11010 GIC         130 :                              format_type_with_typemod(typid, typmod));
                              11011             147 :             if (ordinality)
                              11012              17 :                 continue;
                              11013                 : 
                              11014             130 :             if (coldefexpr != NULL)
                              11015                 :             {
                              11016              17 :                 appendStringInfoString(buf, " DEFAULT (");
 2223 alvherre                11017 CBC          17 :                 get_rule_expr((Node *) coldefexpr, context, showimplicit);
                              11018              17 :                 appendStringInfoChar(buf, ')');
                              11019                 :             }
                              11020             130 :             if (colexpr != NULL)
                              11021                 :             {
                              11022             124 :                 appendStringInfoString(buf, " PATH (");
                              11023             124 :                 get_rule_expr((Node *) colexpr, context, showimplicit);
                              11024             124 :                 appendStringInfoChar(buf, ')');
                              11025                 :             }
                              11026             130 :             if (notnull)
                              11027              17 :                 appendStringInfoString(buf, " NOT NULL");
                              11028                 :         }
                              11029                 :     }
                              11030                 : 
 2223 alvherre                11031 GIC          25 :     appendStringInfoChar(buf, ')');
                              11032              25 : }
                              11033                 : 
                              11034                 : /* ----------
 8244 tgl                     11035 ECB             :  * get_from_clause          - Parse back a FROM clause
                              11036                 :  *
 6576 neilc                   11037                 :  * "prefix" is the keyword that denotes the start of the list of FROM
                              11038                 :  * elements. It is FROM when used to parse back SELECT and UPDATE, but
                              11039                 :  * is USING when parsing back DELETE.
                              11040                 :  * ----------
                              11041                 :  */
 8244 tgl                     11042                 : static void
 6576 neilc                   11043 CBC        1932 : get_from_clause(Query *query, const char *prefix, deparse_context *context)
                              11044                 : {
 8244 tgl                     11045            1932 :     StringInfo  buf = context->buf;
 7193 tgl                     11046 GIC        1932 :     bool        first = true;
                              11047                 :     ListCell   *l;
                              11048                 : 
                              11049                 :     /*
                              11050                 :      * We use the query's jointree as a guide to what to print.  However, we
                              11051                 :      * must ignore auto-added RTEs that are marked not inFromCl. (These can
                              11052                 :      * only appear at the top level of the jointree, so it's sufficient to
                              11053                 :      * check here.)  This check also ensures we ignore the rule pseudo-RTEs
 6385 bruce                   11054 ECB             :      * for NEW and OLD.
                              11055                 :      */
 8227 tgl                     11056 CBC        3860 :     foreach(l, query->jointree->fromlist)
                              11057                 :     {
 8053 bruce                   11058 GIC        1928 :         Node       *jtnode = (Node *) lfirst(l);
 8244 tgl                     11059 ECB             : 
 8244 tgl                     11060 GIC        1928 :         if (IsA(jtnode, RangeTblRef))
 8244 tgl                     11061 ECB             :         {
 8244 tgl                     11062 CBC        1593 :             int         varno = ((RangeTblRef *) jtnode)->rtindex;
                              11063            1593 :             RangeTblEntry *rte = rt_fetch(varno, query->rtable);
 8244 tgl                     11064 ECB             : 
 8244 tgl                     11065 GIC        1593 :             if (!rte->inFromCl)
 8244 tgl                     11066 CBC         185 :                 continue;
                              11067                 :         }
                              11068                 : 
 7193 tgl                     11069 GIC        1743 :         if (first)
                              11070                 :         {
 6576 neilc                   11071            1591 :             appendContextKeyword(context, prefix,
 7193 tgl                     11072 ECB             :                                  -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
 7193 tgl                     11073 CBC        1591 :             first = false;
 4067 andrew                  11074 ECB             : 
 4067 andrew                  11075 GIC        1591 :             get_from_clause_item(jtnode, query, context);
 7193 tgl                     11076 ECB             :         }
                              11077                 :         else
 4067 andrew                  11078                 :         {
 3758 tgl                     11079                 :             StringInfoData itembuf;
 4067 andrew                  11080                 : 
 7188 bruce                   11081 CBC         152 :             appendStringInfoString(buf, ", ");
 3955 bruce                   11082 ECB             : 
 3758 tgl                     11083                 :             /*
                              11084                 :              * Put the new FROM item's text into itembuf so we can decide
                              11085                 :              * after we've got it whether or not it needs to go on a new line.
                              11086                 :              */
 3758 tgl                     11087 GIC         152 :             initStringInfo(&itembuf);
 3758 tgl                     11088 CBC         152 :             context->buf = &itembuf;
                              11089                 : 
 4067 andrew                  11090 GIC         152 :             get_from_clause_item(jtnode, query, context);
 4067 andrew                  11091 ECB             : 
                              11092                 :             /* Restore context's output buffer */
 4067 andrew                  11093 CBC         152 :             context->buf = buf;
 4067 andrew                  11094 ECB             : 
 3758 tgl                     11095                 :             /* Consider line-wrapping if enabled */
 3758 tgl                     11096 CBC         152 :             if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
 3758 tgl                     11097 ECB             :             {
 3436                         11098                 :                 /* Does the new item start with a new line? */
 3436 tgl                     11099 GIC         152 :                 if (itembuf.len > 0 && itembuf.data[0] == '\n')
                              11100                 :                 {
 3436 tgl                     11101 EUB             :                     /* If so, we shouldn't add anything */
                              11102                 :                     /* instead, remove any trailing spaces currently in buf */
 3436 tgl                     11103 UIC           0 :                     removeStringInfoSpaces(buf);
                              11104                 :                 }
 3758 tgl                     11105 ECB             :                 else
                              11106                 :                 {
 3436                         11107                 :                     char       *trailing_nl;
                              11108                 : 
                              11109                 :                     /* Locate the start of the current line in the buffer */
 3436 tgl                     11110 CBC         152 :                     trailing_nl = strrchr(buf->data, '\n');
                              11111             152 :                     if (trailing_nl == NULL)
 3436 tgl                     11112 UIC           0 :                         trailing_nl = buf->data;
 3436 tgl                     11113 ECB             :                     else
 3436 tgl                     11114 CBC         152 :                         trailing_nl++;
 3436 tgl                     11115 ECB             : 
                              11116                 :                     /*
                              11117                 :                      * Add a newline, plus some indentation, if the new item
                              11118                 :                      * would cause an overflow.
                              11119                 :                      */
 3436 tgl                     11120 CBC         152 :                     if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
                              11121             152 :                         appendContextKeyword(context, "", -PRETTYINDENT_STD,
 3436 tgl                     11122 ECB             :                                              PRETTYINDENT_STD,
                              11123                 :                                              PRETTYINDENT_VAR);
 3436 tgl                     11124 EUB             :                 }
 4067 andrew                  11125                 :             }
                              11126                 : 
                              11127                 :             /* Add the new item */
 1356 drowley                 11128 CBC         152 :             appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
                              11129                 : 
                              11130                 :             /* clean up */
 3758 tgl                     11131             152 :             pfree(itembuf.data);
 4067 andrew                  11132 ECB             :         }
                              11133                 :     }
 8244 tgl                     11134 GBC        1932 : }
                              11135                 : 
 8244 tgl                     11136 EUB             : static void
 8244 tgl                     11137 GIC        2743 : get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
                              11138                 : {
                              11139            2743 :     StringInfo  buf = context->buf;
 3751                         11140            2743 :     deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
 8244 tgl                     11141 ECB             : 
 8244 tgl                     11142 CBC        2743 :     if (IsA(jtnode, RangeTblRef))
                              11143                 :     {
                              11144            2243 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
 8244 tgl                     11145 GIC        2243 :         RangeTblEntry *rte = rt_fetch(varno, query->rtable);
 3751                         11146            2243 :         deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
 3426                         11147            2243 :         RangeTblFunction *rtfunc1 = NULL;
 8244 tgl                     11148 ECB             : 
 3897 tgl                     11149 CBC        2243 :         if (rte->lateral)
 3897 tgl                     11150 GIC          32 :             appendStringInfoString(buf, "LATERAL ");
 3897 tgl                     11151 ECB             : 
 3831                         11152                 :         /* Print the FROM item proper */
 7688 tgl                     11153 GIC        2243 :         switch (rte->rtekind)
                              11154                 :         {
                              11155            1752 :             case RTE_RELATION:
                              11156                 :                 /* Normal relation RTE */
                              11157            3504 :                 appendStringInfo(buf, "%s%s",
                              11158            1752 :                                  only_marker(rte),
                              11159                 :                                  generate_relation_name(rte->relid,
 5298 tgl                     11160 ECB             :                                                         context->namespaces));
 7688 tgl                     11161 GIC        1752 :                 break;
 7688 tgl                     11162 CBC         119 :             case RTE_SUBQUERY:
                              11163                 :                 /* Subquery RTE */
 7688 tgl                     11164 GIC         119 :                 appendStringInfoChar(buf, '(');
 7188 bruce                   11165             119 :                 get_query_def(rte->subquery, buf, context->namespaces, NULL,
  323 tgl                     11166 ECB             :                               true,
                              11167                 :                               context->prettyFlags, context->wrapColumn,
 3758                         11168                 :                               context->indentLevel);
 7688 tgl                     11169 GIC         119 :                 appendStringInfoChar(buf, ')');
                              11170             119 :                 break;
 7637                         11171             267 :             case RTE_FUNCTION:
 7637 tgl                     11172 ECB             :                 /* Function RTE */
 3426 tgl                     11173 GIC         267 :                 rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
 3426 tgl                     11174 ECB             : 
                              11175                 :                 /*
                              11176                 :                  * Omit ROWS FROM() syntax for just one function, unless it
                              11177                 :                  * has both a coldeflist and WITH ORDINALITY. If it has both,
 3407 noah                    11178                 :                  * we must use ROWS FROM() syntax to avoid ambiguity about
                              11179                 :                  * whether the coldeflist includes the ordinality column.
 3426 tgl                     11180                 :                  */
 3426 tgl                     11181 GBC         267 :                 if (list_length(rte->functions) == 1 &&
 3426 tgl                     11182 GIC         252 :                     (rtfunc1->funccolnames == NIL || !rte->funcordinality))
 3426 tgl                     11183 ECB             :                 {
 2096 tgl                     11184 GIC         252 :                     get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
 3426 tgl                     11185 ECB             :                     /* we'll print the coldeflist below, if it has one */
                              11186                 :                 }
                              11187                 :                 else
                              11188                 :                 {
                              11189                 :                     bool        all_unnest;
                              11190                 :                     ListCell   *lc;
                              11191                 : 
 3426 tgl                     11192 EUB             :                     /*
                              11193                 :                      * If all the function calls in the list are to unnest,
                              11194                 :                      * and none need a coldeflist, then collapse the list back
                              11195                 :                      * down to UNNEST(args).  (If we had more than one
 3426 tgl                     11196 ECB             :                      * built-in unnest function, this would get more
                              11197                 :                      * difficult.)
                              11198                 :                      *
                              11199                 :                      * XXX This is pretty ugly, since it makes not-terribly-
                              11200                 :                      * future-proof assumptions about what the parser would do
                              11201                 :                      * with the output; but the alternative is to emit our
 3407 noah                    11202                 :                      * nonstandard ROWS FROM() notation for what might have
                              11203                 :                      * been a perfectly spec-compliant multi-argument
                              11204                 :                      * UNNEST().
 3426 tgl                     11205                 :                      */
 3426 tgl                     11206 GIC          15 :                     all_unnest = true;
                              11207              39 :                     foreach(lc, rte->functions)
                              11208                 :                     {
                              11209              33 :                         RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
                              11210                 : 
                              11211              33 :                         if (!IsA(rtfunc->funcexpr, FuncExpr) ||
  888 tgl                     11212 CBC          33 :                             ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
 3426 tgl                     11213 GIC          24 :                             rtfunc->funccolnames != NIL)
 3426 tgl                     11214 ECB             :                         {
 3426 tgl                     11215 CBC           9 :                             all_unnest = false;
 3426 tgl                     11216 GIC           9 :                             break;
                              11217                 :                         }
 3426 tgl                     11218 ECB             :                     }
                              11219                 : 
 3426 tgl                     11220 CBC          15 :                     if (all_unnest)
 3426 tgl                     11221 ECB             :                     {
 3426 tgl                     11222 CBC           6 :                         List       *allargs = NIL;
 3426 tgl                     11223 ECB             : 
 3426 tgl                     11224 CBC          24 :                         foreach(lc, rte->functions)
                              11225                 :                         {
                              11226              18 :                             RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
                              11227              18 :                             List       *args = ((FuncExpr *) rtfunc->funcexpr)->args;
 3426 tgl                     11228 ECB             : 
 1336 tgl                     11229 GIC          18 :                             allargs = list_concat(allargs, args);
 3426 tgl                     11230 ECB             :                         }
                              11231                 : 
 3426 tgl                     11232 CBC           6 :                         appendStringInfoString(buf, "UNNEST(");
                              11233               6 :                         get_rule_expr((Node *) allargs, context, true);
                              11234               6 :                         appendStringInfoChar(buf, ')');
                              11235                 :                     }
 3426 tgl                     11236 ECB             :                     else
                              11237                 :                     {
 3426 tgl                     11238 CBC           9 :                         int         funcno = 0;
 3426 tgl                     11239 ECB             : 
 3407 noah                    11240 CBC           9 :                         appendStringInfoString(buf, "ROWS FROM(");
 3426 tgl                     11241 GIC          33 :                         foreach(lc, rte->functions)
 3426 tgl                     11242 ECB             :                         {
 3426 tgl                     11243 GIC          24 :                             RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
 3426 tgl                     11244 ECB             : 
 3426 tgl                     11245 CBC          24 :                             if (funcno > 0)
                              11246              15 :                                 appendStringInfoString(buf, ", ");
 2096 tgl                     11247 GIC          24 :                             get_rule_expr_funccall(rtfunc->funcexpr, context, true);
 3426 tgl                     11248 CBC          24 :                             if (rtfunc->funccolnames != NIL)
 3426 tgl                     11249 ECB             :                             {
                              11250                 :                                 /* Reconstruct the column definition list */
 3426 tgl                     11251 GIC           3 :                                 appendStringInfoString(buf, " AS ");
                              11252               3 :                                 get_from_clause_coldeflist(rtfunc,
 3426 tgl                     11253 ECB             :                                                            NULL,
                              11254                 :                                                            context);
                              11255                 :                             }
 3426 tgl                     11256 GIC          24 :                             funcno++;
                              11257                 :                         }
                              11258               9 :                         appendStringInfoChar(buf, ')');
                              11259                 :                     }
                              11260                 :                     /* prevent printing duplicate coldeflist below */
                              11261              15 :                     rtfunc1 = NULL;
                              11262                 :                 }
 3541 stark                   11263             267 :                 if (rte->funcordinality)
                              11264               9 :                     appendStringInfoString(buf, " WITH ORDINALITY");
 7637 tgl                     11265 CBC         267 :                 break;
 2223 alvherre                11266 GIC          13 :             case RTE_TABLEFUNC:
 2223 alvherre                11267 CBC          13 :                 get_tablefunc(rte->tablefunc, context, true);
                              11268              13 :                 break;
 6094 mail                    11269 GIC           6 :             case RTE_VALUES:
                              11270                 :                 /* Values list RTE */
 2965 tgl                     11271               6 :                 appendStringInfoChar(buf, '(');
 6094 mail                    11272               6 :                 get_values_def(rte->values_lists, context);
 2965 tgl                     11273               6 :                 appendStringInfoChar(buf, ')');
 6094 mail                    11274               6 :                 break;
 5300 tgl                     11275              86 :             case RTE_CTE:
                              11276              86 :                 appendStringInfoString(buf, quote_identifier(rte->ctename));
                              11277              86 :                 break;
 7688 tgl                     11278 LBC           0 :             default:
 7196 tgl                     11279 UIC           0 :                 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
 7688 tgl                     11280 ECB             :                 break;
                              11281                 :         }
 6394                         11282                 : 
                              11283                 :         /* Print the relation alias, if needed */
   51 tgl                     11284 CBC        2243 :         get_rte_alias(rte, varno, false, context);
 6394 tgl                     11285 ECB             : 
                              11286                 :         /* Print the column definitions or aliases, if needed */
 3426 tgl                     11287 CBC        2243 :         if (rtfunc1 && rtfunc1->funccolnames != NIL)
 7528 tgl                     11288 ECB             :         {
                              11289                 :             /* Reconstruct the columndef list, which is also the aliases */
 3426 tgl                     11290 UIC           0 :             get_from_clause_coldeflist(rtfunc1, colinfo, context);
 7549 tgl                     11291 ECB             :         }
                              11292                 :         else
 6394                         11293                 :         {
                              11294                 :             /* Else print column aliases as needed */
 3751 tgl                     11295 CBC        2243 :             get_column_alias_list(colinfo, context);
                              11296                 :         }
 2815 tgl                     11297 ECB             : 
                              11298                 :         /* Tablesample clause must go after any alias */
 2815 tgl                     11299 GIC        2243 :         if (rte->rtekind == RTE_RELATION && rte->tablesample)
                              11300              16 :             get_tablesample_def(rte->tablesample, context);
                              11301                 :     }
 8244                         11302             500 :     else if (IsA(jtnode, JoinExpr))
 8244 tgl                     11303 ECB             :     {
 8244 tgl                     11304 GIC         500 :         JoinExpr   *j = (JoinExpr *) jtnode;
 3751                         11305             500 :         deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
                              11306                 :         bool        need_paren_on_right;
                              11307                 : 
 7193                         11308            1219 :         need_paren_on_right = PRETTY_PAREN(context) &&
 6496 tgl                     11309 CBC         500 :             !IsA(j->rarg, RangeTblRef) &&
 1058 tgl                     11310 LBC           0 :             !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
                              11311                 : 
 7193 tgl                     11312 CBC         500 :         if (!PRETTY_PAREN(context) || j->alias != NULL)
 7188 bruce                   11313 GIC         335 :             appendStringInfoChar(buf, '(');
                              11314                 : 
 8244 tgl                     11315 CBC         500 :         get_from_clause_item(j->larg, query, context);
                              11316                 : 
 3751 tgl                     11317 GIC         500 :         switch (j->jointype)
 7193 tgl                     11318 ECB             :         {
 3751 tgl                     11319 GIC         302 :             case JOIN_INNER:
                              11320             302 :                 if (j->quals)
 3751 tgl                     11321 CBC         281 :                     appendContextKeyword(context, " JOIN ",
                              11322                 :                                          -PRETTYINDENT_STD,
                              11323                 :                                          PRETTYINDENT_STD,
                              11324                 :                                          PRETTYINDENT_JOIN);
 3751 tgl                     11325 EUB             :                 else
 3751 tgl                     11326 GIC          21 :                     appendContextKeyword(context, " CROSS JOIN ",
                              11327                 :                                          -PRETTYINDENT_STD,
                              11328                 :                                          PRETTYINDENT_STD,
                              11329                 :                                          PRETTYINDENT_JOIN);
                              11330             302 :                 break;
                              11331             147 :             case JOIN_LEFT:
 3751 tgl                     11332 CBC         147 :                 appendContextKeyword(context, " LEFT JOIN ",
 3266 tgl                     11333 ECB             :                                      -PRETTYINDENT_STD,
 3266 tgl                     11334 EUB             :                                      PRETTYINDENT_STD,
                              11335                 :                                      PRETTYINDENT_JOIN);
 3751 tgl                     11336 CBC         147 :                 break;
 3751 tgl                     11337 GIC          51 :             case JOIN_FULL:
                              11338              51 :                 appendContextKeyword(context, " FULL JOIN ",
                              11339                 :                                      -PRETTYINDENT_STD,
                              11340                 :                                      PRETTYINDENT_STD,
                              11341                 :                                      PRETTYINDENT_JOIN);
 3751 tgl                     11342 CBC          51 :                 break;
 3751 tgl                     11343 LBC           0 :             case JOIN_RIGHT:
 3751 tgl                     11344 UIC           0 :                 appendContextKeyword(context, " RIGHT JOIN ",
                              11345                 :                                      -PRETTYINDENT_STD,
                              11346                 :                                      PRETTYINDENT_STD,
                              11347                 :                                      PRETTYINDENT_JOIN);
                              11348               0 :                 break;
                              11349               0 :             default:
 3751 tgl                     11350 LBC           0 :                 elog(ERROR, "unrecognized join type: %d",
                              11351                 :                      (int) j->jointype);
                              11352                 :         }
 7193 tgl                     11353 ECB             : 
 7193 tgl                     11354 GIC         500 :         if (need_paren_on_right)
 7188 bruce                   11355 UIC           0 :             appendStringInfoChar(buf, '(');
 8244 tgl                     11356 CBC         500 :         get_from_clause_item(j->rarg, query, context);
 7193 tgl                     11357 GIC         500 :         if (need_paren_on_right)
 7188 bruce                   11358 UIC           0 :             appendStringInfoChar(buf, ')');
 7193 tgl                     11359 ECB             : 
 3751 tgl                     11360 GIC         500 :         if (j->usingClause)
 8244 tgl                     11361 ECB             :         {
 3751                         11362                 :             ListCell   *lc;
 3751 tgl                     11363 GIC         212 :             bool        first = true;
 8244 tgl                     11364 ECB             : 
 3447 rhaas                   11365 GIC         212 :             appendStringInfoString(buf, " USING (");
 3751 tgl                     11366 ECB             :             /* Use the assigned names, not what's in usingClause */
 3751 tgl                     11367 CBC         502 :             foreach(lc, colinfo->usingNames)
 8244 tgl                     11368 ECB             :             {
 3751 tgl                     11369 CBC         290 :                 char       *colname = (char *) lfirst(lc);
                              11370                 : 
                              11371             290 :                 if (first)
                              11372             212 :                     first = false;
                              11373                 :                 else
 3447 rhaas                   11374 GIC          78 :                     appendStringInfoString(buf, ", ");
 3751 tgl                     11375 CBC         290 :                 appendStringInfoString(buf, quote_identifier(colname));
                              11376                 :             }
                              11377             212 :             appendStringInfoChar(buf, ')');
                              11378                 : 
  739 peter                   11379             212 :             if (j->join_using_alias)
                              11380               6 :                 appendStringInfo(buf, " AS %s",
  739 peter                   11381 GIC           6 :                                  quote_identifier(j->join_using_alias->aliasname));
                              11382                 :         }
 3751 tgl                     11383 CBC         288 :         else if (j->quals)
 3751 tgl                     11384 ECB             :         {
 3447 rhaas                   11385 GIC         264 :             appendStringInfoString(buf, " ON ");
 3751 tgl                     11386 CBC         264 :             if (!PRETTY_PAREN(context))
                              11387             261 :                 appendStringInfoChar(buf, '(');
 3751 tgl                     11388 GIC         264 :             get_rule_expr(j->quals, context, false);
                              11389             264 :             if (!PRETTY_PAREN(context))
                              11390             261 :                 appendStringInfoChar(buf, ')');
 8244 tgl                     11391 ECB             :         }
 2089 tgl                     11392 CBC          24 :         else if (j->jointype != JOIN_INNER)
 2089 tgl                     11393 ECB             :         {
                              11394                 :             /* If we didn't say CROSS JOIN above, we must provide an ON */
 2089 tgl                     11395 CBC           3 :             appendStringInfoString(buf, " ON TRUE");
                              11396                 :         }
                              11397                 : 
 7193 tgl                     11398 GIC         500 :         if (!PRETTY_PAREN(context) || j->alias != NULL)
 7188 bruce                   11399             335 :             appendStringInfoChar(buf, ')');
                              11400                 : 
                              11401                 :         /* Yes, it's correct to put alias after the right paren ... */
 8244 tgl                     11402             500 :         if (j->alias != NULL)
 8244 tgl                     11403 ECB             :         {
 1397                         11404                 :             /*
                              11405                 :              * Note that it's correct to emit an alias clause if and only if
                              11406                 :              * there was one originally.  Otherwise we'd be converting a named
                              11407                 :              * join to unnamed or vice versa, which creates semantic
                              11408                 :              * subtleties we don't want.  However, we might print a different
                              11409                 :              * alias name than was there originally.
                              11410                 :              */
 8244 tgl                     11411 GIC          54 :             appendStringInfo(buf, " %s",
 1397                         11412              54 :                              quote_identifier(get_rtable_name(j->rtindex,
                              11413                 :                                                               context)));
 3751                         11414              54 :             get_column_alias_list(colinfo, context);
                              11415                 :         }
                              11416                 :     }
                              11417                 :     else
 7196 tgl                     11418 UIC           0 :         elog(ERROR, "unrecognized node type: %d",
                              11419                 :              (int) nodeTag(jtnode));
 8244 tgl                     11420 GIC        2743 : }
                              11421                 : 
                              11422                 : /*
                              11423                 :  * get_rte_alias - print the relation's alias, if needed
                              11424                 :  *
                              11425                 :  * If printed, the alias is preceded by a space, or by " AS " if use_as is true.
                              11426                 :  */
                              11427                 : static void
   51 tgl                     11428 CBC        2507 : get_rte_alias(RangeTblEntry *rte, int varno, bool use_as,
   51 tgl                     11429 ECB             :               deparse_context *context)
                              11430                 : {
   51 tgl                     11431 CBC        2507 :     deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces);
   51 tgl                     11432 GIC        2507 :     char       *refname = get_rtable_name(varno, context);
   51 tgl                     11433 CBC        2507 :     deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
                              11434            2507 :     bool        printalias = false;
   51 tgl                     11435 ECB             : 
   51 tgl                     11436 GIC        2507 :     if (rte->alias != NULL)
   51 tgl                     11437 ECB             :     {
                              11438                 :         /* Always print alias if user provided one */
   51 tgl                     11439 GIC        1007 :         printalias = true;
                              11440                 :     }
                              11441            1500 :     else if (colinfo->printaliases)
   51 tgl                     11442 ECB             :     {
                              11443                 :         /* Always print alias if we need to print column aliases */
   51 tgl                     11444 CBC         126 :         printalias = true;
                              11445                 :     }
                              11446            1374 :     else if (rte->rtekind == RTE_RELATION)
                              11447                 :     {
   51 tgl                     11448 ECB             :         /*
                              11449                 :          * No need to print alias if it's same as relation name (this would
                              11450                 :          * normally be the case, but not if set_rtable_names had to resolve a
                              11451                 :          * conflict).
                              11452                 :          */
   51 tgl                     11453 GIC        1274 :         if (strcmp(refname, get_relation_name(rte->relid)) != 0)
   51 tgl                     11454 CBC          19 :             printalias = true;
   51 tgl                     11455 ECB             :     }
   51 tgl                     11456 CBC         100 :     else if (rte->rtekind == RTE_FUNCTION)
                              11457                 :     {
                              11458                 :         /*
                              11459                 :          * For a function RTE, always print alias.  This covers possible
   51 tgl                     11460 ECB             :          * renaming of the function and/or instability of the FigureColname
                              11461                 :          * rules for things that aren't simple functions.  Note we'd need to
                              11462                 :          * force it anyway for the columndef list case.
                              11463                 :          */
   51 tgl                     11464 UIC           0 :         printalias = true;
   51 tgl                     11465 ECB             :     }
   51 tgl                     11466 GIC         100 :     else if (rte->rtekind == RTE_SUBQUERY ||
   51 tgl                     11467 CBC          88 :              rte->rtekind == RTE_VALUES)
   51 tgl                     11468 ECB             :     {
                              11469                 :         /*
                              11470                 :          * For a subquery, always print alias.  This makes the output
                              11471                 :          * SQL-spec-compliant, even though we allow such aliases to be omitted
                              11472                 :          * on input.
                              11473                 :          */
   51 tgl                     11474 CBC          18 :         printalias = true;
                              11475                 :     }
   51 tgl                     11476 GIC          82 :     else if (rte->rtekind == RTE_CTE)
   51 tgl                     11477 ECB             :     {
                              11478                 :         /*
                              11479                 :          * No need to print alias if it's same as CTE name (this would
                              11480                 :          * normally be the case, but not if set_rtable_names had to resolve a
                              11481                 :          * conflict).
                              11482                 :          */
   51 tgl                     11483 GIC          69 :         if (strcmp(refname, rte->ctename) != 0)
   51 tgl                     11484 CBC          11 :             printalias = true;
                              11485                 :     }
                              11486                 : 
                              11487            2507 :     if (printalias)
   51 tgl                     11488 GIC        1181 :         appendStringInfo(context->buf, "%s%s",
   51 tgl                     11489 ECB             :                          use_as ? " AS " : " ",
                              11490                 :                          quote_identifier(refname));
   51 tgl                     11491 CBC        2507 : }
   51 tgl                     11492 ECB             : 
 6807                         11493                 : /*
 3751                         11494                 :  * get_column_alias_list - print column alias list for an RTE
 6807                         11495                 :  *
                              11496                 :  * Caller must already have printed the relation's alias name.
                              11497                 :  */
                              11498                 : static void
 3751 tgl                     11499 CBC        2297 : get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
 6807 tgl                     11500 ECB             : {
 6807 tgl                     11501 CBC        2297 :     StringInfo  buf = context->buf;
 3751 tgl                     11502 ECB             :     int         i;
 6807 tgl                     11503 CBC        2297 :     bool        first = true;
 6807 tgl                     11504 EUB             : 
 3751                         11505                 :     /* Don't print aliases if not needed */
 3751 tgl                     11506 GIC        2297 :     if (!colinfo->printaliases)
                              11507            1853 :         return;
                              11508                 : 
                              11509            2898 :     for (i = 0; i < colinfo->num_new_cols; i++)
 6807 tgl                     11510 ECB             :     {
 3751 tgl                     11511 GIC        2454 :         char       *colname = colinfo->new_colnames[i];
                              11512                 : 
 6807 tgl                     11513 CBC        2454 :         if (first)
                              11514                 :         {
 6807 tgl                     11515 GIC         444 :             appendStringInfoChar(buf, '(');
 6807 tgl                     11516 GBC         444 :             first = false;
                              11517                 :         }
                              11518                 :         else
 3447 rhaas                   11519 GIC        2010 :             appendStringInfoString(buf, ", ");
 3751 tgl                     11520            2454 :         appendStringInfoString(buf, quote_identifier(colname));
 6807 tgl                     11521 ECB             :     }
 6807 tgl                     11522 GIC         444 :     if (!first)
                              11523             444 :         appendStringInfoChar(buf, ')');
                              11524                 : }
 6807 tgl                     11525 ECB             : 
 7528                         11526                 : /*
                              11527                 :  * get_from_clause_coldeflist - reproduce FROM clause coldeflist
                              11528                 :  *
                              11529                 :  * When printing a top-level coldeflist (which is syntactically also the
 3426                         11530                 :  * relation's column alias list), use column names from colinfo.  But when
 3407 noah                    11531                 :  * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
                              11532                 :  * original coldeflist's names, which are available in rtfunc->funccolnames.
                              11533                 :  * Pass NULL for colinfo to select the latter behavior.
 3426 tgl                     11534                 :  *
 7528                         11535                 :  * The coldeflist is appended immediately (no space) to buf.  Caller is
 7528 tgl                     11536 EUB             :  * responsible for ensuring that an alias or AS is present before it.
                              11537                 :  */
 7528 tgl                     11538 ECB             : static void
 3426 tgl                     11539 CBC           3 : get_from_clause_coldeflist(RangeTblFunction *rtfunc,
                              11540                 :                            deparse_columns *colinfo,
 6233 tgl                     11541 ECB             :                            deparse_context *context)
                              11542                 : {
 7528 tgl                     11543 CBC           3 :     StringInfo  buf = context->buf;
                              11544                 :     ListCell   *l1;
 6233 tgl                     11545 ECB             :     ListCell   *l2;
                              11546                 :     ListCell   *l3;
 3426                         11547                 :     ListCell   *l4;
                              11548                 :     int         i;
                              11549                 : 
 7528 tgl                     11550 GIC           3 :     appendStringInfoChar(buf, '(');
                              11551                 : 
 3751 tgl                     11552 CBC           3 :     i = 0;
 1501 tgl                     11553 GIC          12 :     forfour(l1, rtfunc->funccoltypes,
                              11554                 :             l2, rtfunc->funccoltypmods,
                              11555                 :             l3, rtfunc->funccolcollations,
 1501 tgl                     11556 ECB             :             l4, rtfunc->funccolnames)
 3751                         11557                 :     {
 3751 tgl                     11558 CBC           9 :         Oid         atttypid = lfirst_oid(l1);
 3751 tgl                     11559 GIC           9 :         int32       atttypmod = lfirst_int(l2);
                              11560               9 :         Oid         attcollation = lfirst_oid(l3);
                              11561                 :         char       *attname;
 3426 tgl                     11562 ECB             : 
 3426 tgl                     11563 CBC           9 :         if (colinfo)
 3426 tgl                     11564 LBC           0 :             attname = colinfo->colnames[i];
                              11565                 :         else
 3426 tgl                     11566 GIC           9 :             attname = strVal(lfirst(l4));
                              11567                 : 
 3751 tgl                     11568 CBC           9 :         Assert(attname);        /* shouldn't be any dropped columns here */
 7528 tgl                     11569 EUB             : 
 7528 tgl                     11570 GBC           9 :         if (i > 0)
 3447 rhaas                   11571 GIC           6 :             appendStringInfoString(buf, ", ");
 7528 tgl                     11572               9 :         appendStringInfo(buf, "%s %s",
                              11573                 :                          quote_identifier(attname),
 6233 tgl                     11574 EUB             :                          format_type_with_typemod(atttypid, atttypmod));
 4370 tgl                     11575 GBC          12 :         if (OidIsValid(attcollation) &&
                              11576               3 :             attcollation != get_typcollation(atttypid))
 4399 tgl                     11577 UIC           0 :             appendStringInfo(buf, " COLLATE %s",
                              11578                 :                              generate_collation_name(attcollation));
                              11579                 : 
 7528 tgl                     11580 CBC           9 :         i++;
 7528 tgl                     11581 EUB             :     }
 7528 tgl                     11582 ECB             : 
 7528 tgl                     11583 CBC           3 :     appendStringInfoChar(buf, ')');
 7528 tgl                     11584 GBC           3 : }
                              11585                 : 
 2815 tgl                     11586 ECB             : /*
                              11587                 :  * get_tablesample_def          - print a TableSampleClause
                              11588                 :  */
                              11589                 : static void
 2815 tgl                     11590 GIC          16 : get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
 2815 tgl                     11591 ECB             : {
 2815 tgl                     11592 GIC          16 :     StringInfo  buf = context->buf;
 2815 tgl                     11593 ECB             :     Oid         argtypes[1];
                              11594                 :     int         nargs;
                              11595                 :     ListCell   *l;
                              11596                 : 
                              11597                 :     /*
                              11598                 :      * We should qualify the handler's function name if it wouldn't be
                              11599                 :      * resolved by lookup in the current search path.
                              11600                 :      */
 2815 tgl                     11601 CBC          16 :     argtypes[0] = INTERNALOID;
 2815 tgl                     11602 GIC          16 :     appendStringInfo(buf, " TABLESAMPLE %s (",
 2815 tgl                     11603 ECB             :                      generate_function_name(tablesample->tsmhandler, 1,
                              11604                 :                                             NIL, argtypes,
                              11605                 :                                             false, NULL, EXPR_KIND_NONE));
                              11606                 : 
 2815 tgl                     11607 CBC          16 :     nargs = 0;
 2815 tgl                     11608 GIC          32 :     foreach(l, tablesample->args)
 2815 tgl                     11609 ECB             :     {
 2815 tgl                     11610 GIC          16 :         if (nargs++ > 0)
 2815 tgl                     11611 LBC           0 :             appendStringInfoString(buf, ", ");
 2815 tgl                     11612 CBC          16 :         get_rule_expr((Node *) lfirst(l), context, false);
 2815 tgl                     11613 ECB             :     }
 2815 tgl                     11614 CBC          16 :     appendStringInfoChar(buf, ')');
 2815 tgl                     11615 ECB             : 
 2815 tgl                     11616 CBC          16 :     if (tablesample->repeatable != NULL)
                              11617                 :     {
                              11618               8 :         appendStringInfoString(buf, " REPEATABLE (");
 2815 tgl                     11619 GIC           8 :         get_rule_expr((Node *) tablesample->repeatable, context, false);
                              11620               8 :         appendStringInfoChar(buf, ')');
 2815 tgl                     11621 ECB             :     }
 2815 tgl                     11622 GIC          16 : }
                              11623                 : 
 7646 tgl                     11624 ECB             : /*
 7860                         11625                 :  * get_opclass_name         - fetch name of an index operator class
                              11626                 :  *
                              11627                 :  * The opclass name is appended (after a space) to buf.
 7857                         11628                 :  *
                              11629                 :  * Output is suppressed if the opclass is the default for the given
                              11630                 :  * actual_datatype.  (If you don't want this behavior, just pass
                              11631                 :  * InvalidOid for actual_datatype.)
                              11632                 :  */
                              11633                 : static void
 7857 tgl                     11634 GIC        4810 : get_opclass_name(Oid opclass, Oid actual_datatype,
                              11635                 :                  StringInfo buf)
                              11636                 : {
 7860 tgl                     11637 ECB             :     HeapTuple   ht_opc;
                              11638                 :     Form_pg_opclass opcrec;
                              11639                 :     char       *opcname;
 7646                         11640                 :     char       *nspname;
                              11641                 : 
 4802 rhaas                   11642 GIC        4810 :     ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
 7860 tgl                     11643            4810 :     if (!HeapTupleIsValid(ht_opc))
 7860 tgl                     11644 UBC           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
 7860 tgl                     11645 GIC        4810 :     opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
 7175 tgl                     11646 ECB             : 
 5951 tgl                     11647 GIC        9602 :     if (!OidIsValid(actual_datatype) ||
                              11648            4792 :         GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
                              11649                 :     {
                              11650                 :         /* Okay, we need the opclass name.  Do we need to qualify it? */
 7646                         11651             277 :         opcname = NameStr(opcrec->opcname);
 5951                         11652             277 :         if (OpclassIsVisible(opclass))
 7646                         11653             277 :             appendStringInfo(buf, " %s", quote_identifier(opcname));
 7646 tgl                     11654 ECB             :         else
                              11655                 :         {
  621 tgl                     11656 UIC           0 :             nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
 7646 tgl                     11657 LBC           0 :             appendStringInfo(buf, " %s.%s",
 7646 tgl                     11658 ECB             :                              quote_identifier(nspname),
                              11659                 :                              quote_identifier(opcname));
                              11660                 :         }
                              11661                 :     }
 7860 tgl                     11662 CBC        4810 :     ReleaseSysCache(ht_opc);
 7860 tgl                     11663 GIC        4810 : }
                              11664                 : 
 1105 akorotkov               11665 ECB             : /*
                              11666                 :  * generate_opclass_name
   96 michael                 11667                 :  *      Compute the name to display for an opclass specified by OID
                              11668                 :  *
                              11669                 :  * The result includes all necessary quoting and schema-prefixing.
 1105 akorotkov               11670                 :  */
                              11671                 : char *
 1105 akorotkov               11672 CBC           3 : generate_opclass_name(Oid opclass)
                              11673                 : {
                              11674                 :     StringInfoData buf;
                              11675                 : 
 1105 akorotkov               11676 GIC           3 :     initStringInfo(&buf);
                              11677               3 :     get_opclass_name(opclass, InvalidOid, &buf);
                              11678                 : 
 1060 tgl                     11679 CBC           3 :     return &buf.data[1];        /* get_opclass_name() prepends space */
 1105 akorotkov               11680 ECB             : }
                              11681                 : 
 7646 tgl                     11682                 : /*
                              11683                 :  * processIndirection - take care of array and subfield assignment
                              11684                 :  *
                              11685                 :  * We strip any top-level FieldStore or assignment SubscriptingRef nodes that
                              11686                 :  * appear in the input, printing them as decoration for the base column
                              11687                 :  * name (which we assume the caller just printed).  We might also need to
                              11688                 :  * strip CoerceToDomain nodes, but only ones that appear above assignment
                              11689                 :  * nodes.
 2097 tgl                     11690 EUB             :  *
                              11691                 :  * Returns the subexpression that's to be assigned.
 8275 tgl                     11692 ECB             :  */
 6878                         11693                 : static Node *
 2440 tgl                     11694 GIC         558 : processIndirection(Node *node, deparse_context *context)
                              11695                 : {
 6878                         11696             558 :     StringInfo  buf = context->buf;
 2097                         11697             558 :     CoerceToDomain *cdomain = NULL;
                              11698                 : 
                              11699                 :     for (;;)
 6878 tgl                     11700 ECB             :     {
 6878 tgl                     11701 GIC         645 :         if (node == NULL)
 6878 tgl                     11702 LBC           0 :             break;
 6878 tgl                     11703 GIC         645 :         if (IsA(node, FieldStore))
                              11704                 :         {
                              11705              36 :             FieldStore *fstore = (FieldStore *) node;
                              11706                 :             Oid         typrelid;
                              11707                 :             char       *fieldname;
                              11708                 : 
 6878 tgl                     11709 ECB             :             /* lookup tuple type */
 6878 tgl                     11710 CBC          36 :             typrelid = get_typ_typrelid(fstore->resulttype);
 6878 tgl                     11711 GIC          36 :             if (!OidIsValid(typrelid))
 6878 tgl                     11712 UIC           0 :                 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
 6878 tgl                     11713 ECB             :                      format_type_be(fstore->resulttype));
 6797 bruce                   11714                 : 
                              11715                 :             /*
                              11716                 :              * Print the field name.  There should only be one target field in
 4790                         11717                 :              * stored rules.  There could be more than that in executable
                              11718                 :              * target lists, but this function cannot be used for that case.
                              11719                 :              */
 4798 tgl                     11720 GIC          36 :             Assert(list_length(fstore->fieldnums) == 1);
 1882 alvherre                11721              36 :             fieldname = get_attname(typrelid,
                              11722              36 :                                     linitial_int(fstore->fieldnums), false);
 2440 tgl                     11723              36 :             appendStringInfo(buf, ".%s", quote_identifier(fieldname));
                              11724                 : 
 6878 tgl                     11725 ECB             :             /*
                              11726                 :              * We ignore arg since it should be an uninteresting reference to
 6385 bruce                   11727                 :              * the target column or subcolumn.
                              11728                 :              */
 6878 tgl                     11729 CBC          36 :             node = (Node *) linitial(fstore->newvals);
                              11730                 :         }
 1528 alvherre                11731 GIC         609 :         else if (IsA(node, SubscriptingRef))
 6878 tgl                     11732 ECB             :         {
 1528 alvherre                11733 CBC          39 :             SubscriptingRef *sbsref = (SubscriptingRef *) node;
                              11734                 : 
                              11735              39 :             if (sbsref->refassgnexpr == NULL)
 6878 tgl                     11736 UIC           0 :                 break;
 1528 alvherre                11737 ECB             : 
 1528 alvherre                11738 GIC          39 :             printSubscripts(sbsref, context);
 6797 bruce                   11739 ECB             : 
                              11740                 :             /*
 6385                         11741                 :              * We ignore refexpr since it should be an uninteresting reference
                              11742                 :              * to the target column or subcolumn.
                              11743                 :              */
 1528 alvherre                11744 GIC          39 :             node = (Node *) sbsref->refassgnexpr;
 6878 tgl                     11745 ECB             :         }
 2097 tgl                     11746 CBC         570 :         else if (IsA(node, CoerceToDomain))
                              11747                 :         {
                              11748              12 :             cdomain = (CoerceToDomain *) node;
 2097 tgl                     11749 ECB             :             /* If it's an explicit domain coercion, we're done */
 2097 tgl                     11750 GIC          12 :             if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
 2097 tgl                     11751 UIC           0 :                 break;
                              11752                 :             /* Tentatively descend past the CoerceToDomain */
 2097 tgl                     11753 GIC          12 :             node = (Node *) cdomain->arg;
                              11754                 :         }
                              11755                 :         else
 6878                         11756             558 :             break;
                              11757                 :     }
                              11758                 : 
                              11759                 :     /*
                              11760                 :      * If we descended past a CoerceToDomain whose argument turned out not to
                              11761                 :      * be a FieldStore or array assignment, back up to the CoerceToDomain.
                              11762                 :      * (This is not enough to be fully correct if there are nested implicit
                              11763                 :      * CoerceToDomains, but such cases shouldn't ever occur.)
                              11764                 :      */
 2097 tgl                     11765 CBC         558 :     if (cdomain && node == (Node *) cdomain->arg)
 2097 tgl                     11766 UIC           0 :         node = (Node *) cdomain;
                              11767                 : 
 6878 tgl                     11768 GIC         558 :     return node;
 6878 tgl                     11769 ECB             : }
                              11770                 : 
                              11771                 : static void
 1528 alvherre                11772 GIC         131 : printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
                              11773                 : {
 6878 tgl                     11774             131 :     StringInfo  buf = context->buf;
                              11775                 :     ListCell   *lowlist_item;
 6878 tgl                     11776 ECB             :     ListCell   *uplist_item;
                              11777                 : 
 1528 alvherre                11778 CBC         131 :     lowlist_item = list_head(sbsref->reflowerindexpr);   /* could be NULL */
                              11779             262 :     foreach(uplist_item, sbsref->refupperindexpr)
                              11780                 :     {
 6878 tgl                     11781 GIC         131 :         appendStringInfoChar(buf, '[');
                              11782             131 :         if (lowlist_item)
                              11783                 :         {
 2665 tgl                     11784 ECB             :             /* If subexpression is NULL, get_rule_expr prints nothing */
 6878 tgl                     11785 LBC           0 :             get_rule_expr((Node *) lfirst(lowlist_item), context, false);
                              11786               0 :             appendStringInfoChar(buf, ':');
 1364 tgl                     11787 UIC           0 :             lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
                              11788                 :         }
 2665 tgl                     11789 ECB             :         /* If subexpression is NULL, get_rule_expr prints nothing */
 6878 tgl                     11790 GBC         131 :         get_rule_expr((Node *) lfirst(uplist_item), context, false);
 6878 tgl                     11791 GIC         131 :         appendStringInfoChar(buf, ']');
 6878 tgl                     11792 ECB             :     }
 8275 tgl                     11793 GIC         131 : }
 8275 tgl                     11794 ECB             : 
                              11795                 : /*
 8588                         11796                 :  * quote_identifier         - Quote an identifier only if needed
                              11797                 :  *
                              11798                 :  * When quotes are needed, we palloc the required space; slightly
                              11799                 :  * space-wasteful but well worth it for notational simplicity.
                              11800                 :  */
 7654                         11801                 : const char *
 7654 tgl                     11802 CBC     1056314 : quote_identifier(const char *ident)
 8588 tgl                     11803 EUB             : {
                              11804                 :     /*
                              11805                 :      * Can avoid quoting if ident starts with a lowercase letter or underscore
 6385 bruce                   11806 ECB             :      * and contains only lowercase letters, digits, and underscores, *and* is
                              11807                 :      * not any SQL keyword.  Otherwise, supply quotes.
                              11808                 :      */
 7632 tgl                     11809 CBC     1056314 :     int         nquotes = 0;
 8588 tgl                     11810 ECB             :     bool        safe;
                              11811                 :     const char *ptr;
                              11812                 :     char       *result;
                              11813                 :     char       *optr;
                              11814                 : 
                              11815                 :     /*
 6385 bruce                   11816                 :      * would like to use <ctype.h> macros here, but they might yield unwanted
                              11817                 :      * locale-specific results...
 8588 tgl                     11818                 :      */
 7651 tgl                     11819 GIC     1056314 :     safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
                              11820                 : 
 7632                         11821         8625457 :     for (ptr = ident; *ptr; ptr++)
                              11822                 :     {
                              11823         7569143 :         char        ch = *ptr;
                              11824                 : 
                              11825         7569143 :         if ((ch >= 'a' && ch <= 'z') ||
                              11826          843761 :             (ch >= '0' && ch <= '9') ||
 7632 tgl                     11827 ECB             :             (ch == '_'))
 8588                         11828                 :         {
                              11829                 :             /* okay */
                              11830                 :         }
                              11831                 :         else
                              11832                 :         {
 7632 tgl                     11833 CBC       23897 :             safe = false;
                              11834           23897 :             if (ch == '"')
 7632 tgl                     11835 GIC           6 :                 nquotes++;
 8588 tgl                     11836 ECB             :         }
 8588 tgl                     11837 EUB             :     }
 8588 tgl                     11838 ECB             : 
 4644 rhaas                   11839 GIC     1056314 :     if (quote_all_identifiers)
 4644 rhaas                   11840 CBC        5564 :         safe = false;
                              11841                 : 
 8525 tgl                     11842         1056314 :     if (safe)
                              11843                 :     {
 8525 tgl                     11844 ECB             :         /*
 5774                         11845                 :          * Check for keyword.  We quote keywords except for unreserved ones.
                              11846                 :          * (In some cases we could avoid quoting a col_name or type_func_name
                              11847                 :          * keyword, but it seems much harder than it's worth to tell that.)
 8525                         11848                 :          *
                              11849                 :          * Note: ScanKeywordLookup() does case-insensitive comparison, but
                              11850                 :          * that's fine, since we already know we have all-lower-case.
                              11851                 :          */
 1554 tgl                     11852 GIC     1041297 :         int         kwnum = ScanKeywordLookup(ident, &ScanKeywords);
                              11853                 : 
                              11854         1041297 :         if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
 8525                         11855            1046 :             safe = false;
                              11856                 :     }
                              11857                 : 
 8588                         11858         1056314 :     if (safe)
                              11859         1040251 :         return ident;           /* no change needed */
 8588 tgl                     11860 ECB             : 
 7632 tgl                     11861 GIC       16063 :     result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
                              11862                 : 
                              11863           16063 :     optr = result;
                              11864           16063 :     *optr++ = '"';
                              11865           97533 :     for (ptr = ident; *ptr; ptr++)
                              11866                 :     {
                              11867           81470 :         char        ch = *ptr;
 7632 tgl                     11868 ECB             : 
 7632 tgl                     11869 CBC       81470 :         if (ch == '"')
 7632 tgl                     11870 GBC           6 :             *optr++ = '"';
 7632 tgl                     11871 CBC       81470 :         *optr++ = ch;
                              11872                 :     }
                              11873           16063 :     *optr++ = '"';
                              11874           16063 :     *optr = '\0';
                              11875                 : 
 8588 tgl                     11876 GIC       16063 :     return result;
 8588 tgl                     11877 ECB             : }
 8994 bruce                   11878                 : 
 7646 tgl                     11879                 : /*
                              11880                 :  * quote_qualified_identifier   - Quote a possibly-qualified identifier
                              11881                 :  *
 5015 peter_e                 11882 EUB             :  * Return a name of the form qualifier.ident, or just ident if qualifier
 7654 tgl                     11883                 :  * is NULL, quoting each component if necessary.  The result is palloc'd.
                              11884                 :  */
                              11885                 : char *
 5015 peter_e                 11886 GIC      488282 : quote_qualified_identifier(const char *qualifier,
                              11887                 :                            const char *ident)
 7654 tgl                     11888 ECB             : {
                              11889                 :     StringInfoData buf;
                              11890                 : 
 7654 tgl                     11891 GIC      488282 :     initStringInfo(&buf);
 5015 peter_e                 11892          488282 :     if (qualifier)
                              11893          200798 :         appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
 7008 neilc                   11894          488282 :     appendStringInfoString(&buf, quote_identifier(ident));
 7654 tgl                     11895          488282 :     return buf.data;
                              11896                 : }
                              11897                 : 
 4541 tgl                     11898 ECB             : /*
                              11899                 :  * get_relation_name
                              11900                 :  *      Get the unqualified name of a relation specified by OID
                              11901                 :  *
                              11902                 :  * This differs from the underlying get_rel_name() function in that it will
                              11903                 :  * throw error instead of silently returning NULL if the OID is bad.
                              11904                 :  */
                              11905                 : static char *
 4541 tgl                     11906 GIC        6844 : get_relation_name(Oid relid)
                              11907                 : {
                              11908            6844 :     char       *relname = get_rel_name(relid);
                              11909                 : 
                              11910            6844 :     if (!relname)
 4541 tgl                     11911 UIC           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
 4541 tgl                     11912 GIC        6844 :     return relname;
                              11913                 : }
                              11914                 : 
                              11915                 : /*
                              11916                 :  * generate_relation_name
                              11917                 :  *      Compute the name to display for a relation specified by OID
                              11918                 :  *
                              11919                 :  * The result includes all necessary quoting and schema-prefixing.
 5298 tgl                     11920 ECB             :  *
                              11921                 :  * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
                              11922                 :  * We will forcibly qualify the relation name if it equals any CTE name
                              11923                 :  * visible in the namespace list.
                              11924                 :  */
                              11925                 : static char *
 5298 tgl                     11926 GIC        3210 : generate_relation_name(Oid relid, List *namespaces)
 7646 tgl                     11927 ECB             : {
 7646 tgl                     11928 EUB             :     HeapTuple   tp;
 7646 tgl                     11929 ECB             :     Form_pg_class reltup;
                              11930                 :     bool        need_qual;
 5298                         11931                 :     ListCell   *nslist;
                              11932                 :     char       *relname;
                              11933                 :     char       *nspname;
                              11934                 :     char       *result;
                              11935                 : 
 4802 rhaas                   11936 CBC        3210 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
 7646 tgl                     11937            3210 :     if (!HeapTupleIsValid(tp))
 7196 tgl                     11938 UBC           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
 7646 tgl                     11939 GIC        3210 :     reltup = (Form_pg_class) GETSTRUCT(tp);
 5298                         11940            3210 :     relname = NameStr(reltup->relname);
                              11941                 : 
                              11942                 :     /* Check for conflicting CTE name */
                              11943            3210 :     need_qual = false;
                              11944            5383 :     foreach(nslist, namespaces)
                              11945                 :     {
 5298 tgl                     11946 CBC        2173 :         deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
 5298 tgl                     11947 ECB             :         ListCell   *ctlist;
                              11948                 : 
 5298 tgl                     11949 CBC        2203 :         foreach(ctlist, dpns->ctes)
                              11950                 :         {
 5298 tgl                     11951 GIC          30 :             CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
                              11952                 : 
                              11953              30 :             if (strcmp(cte->ctename, relname) == 0)
                              11954                 :             {
 5298 tgl                     11955 LBC           0 :                 need_qual = true;
 5298 tgl                     11956 UIC           0 :                 break;
 5298 tgl                     11957 ECB             :             }
                              11958                 :         }
 5298 tgl                     11959 CBC        2173 :         if (need_qual)
 5298 tgl                     11960 UIC           0 :             break;
 5298 tgl                     11961 ECB             :     }
 5298 tgl                     11962 EUB             : 
                              11963                 :     /* Otherwise, qualify the name if not visible in search path */
 5298 tgl                     11964 CBC        3210 :     if (!need_qual)
 5298 tgl                     11965 GIC        3210 :         need_qual = !RelationIsVisible(relid);
                              11966                 : 
                              11967            3210 :     if (need_qual)
  621                         11968            1079 :         nspname = get_namespace_name_or_temp(reltup->relnamespace);
                              11969                 :     else
 5298 tgl                     11970 CBC        2131 :         nspname = NULL;
                              11971                 : 
                              11972            3210 :     result = quote_qualified_identifier(nspname, relname);
                              11973                 : 
 7646                         11974            3210 :     ReleaseSysCache(tp);
                              11975                 : 
                              11976            3210 :     return result;
 7646 tgl                     11977 EUB             : }
                              11978                 : 
 2697 tgl                     11979 ECB             : /*
                              11980                 :  * generate_qualified_relation_name
                              11981                 :  *      Compute the name to display for a relation specified by OID
                              11982                 :  *
                              11983                 :  * As above, but unconditionally schema-qualify the name.
                              11984                 :  */
                              11985                 : static char *
 2697 tgl                     11986 GIC        3205 : generate_qualified_relation_name(Oid relid)
                              11987                 : {
                              11988                 :     HeapTuple   tp;
                              11989                 :     Form_pg_class reltup;
                              11990                 :     char       *relname;
 2697 tgl                     11991 ECB             :     char       *nspname;
 2697 tgl                     11992 EUB             :     char       *result;
                              11993                 : 
 2697 tgl                     11994 CBC        3205 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
 2697 tgl                     11995 GIC        3205 :     if (!HeapTupleIsValid(tp))
 2697 tgl                     11996 UIC           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
 2697 tgl                     11997 GIC        3205 :     reltup = (Form_pg_class) GETSTRUCT(tp);
 2697 tgl                     11998 CBC        3205 :     relname = NameStr(reltup->relname);
                              11999                 : 
  621                         12000            3205 :     nspname = get_namespace_name_or_temp(reltup->relnamespace);
 2697 tgl                     12001 GIC        3205 :     if (!nspname)
 2697 tgl                     12002 UIC           0 :         elog(ERROR, "cache lookup failed for namespace %u",
                              12003                 :              reltup->relnamespace);
 2697 tgl                     12004 ECB             : 
 2697 tgl                     12005 CBC        3205 :     result = quote_qualified_identifier(nspname, relname);
                              12006                 : 
                              12007            3205 :     ReleaseSysCache(tp);
 2697 tgl                     12008 ECB             : 
 2697 tgl                     12009 GIC        3205 :     return result;
                              12010                 : }
 2697 tgl                     12011 EUB             : 
 7646                         12012                 : /*
                              12013                 :  * generate_function_name
                              12014                 :  *      Compute the name to display for a function specified by OID,
                              12015                 :  *      given that it is being called with the specified actual arg names and
 3260 bruce                   12016 ECB             :  *      types.  (Those matter because of ambiguous-function resolution rules.)
 7646 tgl                     12017                 :  *
                              12018                 :  * If we're dealing with a potentially variadic function (in practice, this
 3505                         12019                 :  * means a FuncExpr or Aggref, not some other way of calling a function), then
                              12020                 :  * has_variadic must specify whether variadic arguments have been merged,
                              12021                 :  * and *use_variadic_p will be set to indicate whether to print VARIADIC in
                              12022                 :  * the output.  For non-FuncExpr cases, has_variadic should be false and
                              12023                 :  * use_variadic_p can be NULL.
                              12024                 :  *
                              12025                 :  * The result includes all necessary quoting and schema-prefixing.
                              12026                 :  */
                              12027                 : static char *
 3730 tgl                     12028 CBC        5107 : generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
                              12029                 :                        bool has_variadic, bool *use_variadic_p,
                              12030                 :                        ParseExprKind special_exprkind)
                              12031                 : {
                              12032                 :     char       *result;
                              12033                 :     HeapTuple   proctup;
                              12034                 :     Form_pg_proc procform;
 7646 tgl                     12035 ECB             :     char       *proname;
                              12036                 :     bool        use_variadic;
                              12037                 :     char       *nspname;
                              12038                 :     FuncDetailCode p_result;
                              12039                 :     Oid         p_funcid;
                              12040                 :     Oid         p_rettype;
                              12041                 :     bool        p_retset;
                              12042                 :     int         p_nvargs;
                              12043                 :     Oid         p_vatype;
                              12044                 :     Oid        *p_true_typeids;
 2885 andres                  12045 CBC        5107 :     bool        force_qualify = false;
                              12046                 : 
 4802 rhaas                   12047            5107 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
 7646 tgl                     12048 GIC        5107 :     if (!HeapTupleIsValid(proctup))
 7196 tgl                     12049 LBC           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
 7646 tgl                     12050 GIC        5107 :     procform = (Form_pg_proc) GETSTRUCT(proctup);
 7646 tgl                     12051 CBC        5107 :     proname = NameStr(procform->proname);
 7646 tgl                     12052 ECB             : 
                              12053                 :     /*
                              12054                 :      * Due to parser hacks to avoid needing to reserve CUBE, we need to force
                              12055                 :      * qualification in some special cases.
                              12056                 :      */
 2885 andres                  12057 GIC        5107 :     if (special_exprkind == EXPR_KIND_GROUP_BY)
                              12058                 :     {
 2885 andres                  12059 LBC           0 :         if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
                              12060               0 :             force_qualify = true;
 2885 andres                  12061 ECB             :     }
                              12062                 : 
                              12063                 :     /*
                              12064                 :      * Determine whether VARIADIC should be printed.  We must do this first
 3730 tgl                     12065                 :      * since it affects the lookup rules in func_get_detail().
                              12066                 :      *
                              12067                 :      * We always print VARIADIC if the function has a merged variadic-array
 1716 noah                    12068                 :      * argument.  Note that this is always the case for functions taking a
                              12069                 :      * VARIADIC argument type other than VARIADIC ANY.  If we omitted VARIADIC
                              12070                 :      * and printed the array elements as separate arguments, the call could
                              12071                 :      * match a newer non-VARIADIC function.
                              12072                 :      */
 3730 tgl                     12073 GIC        5107 :     if (use_variadic_p)
                              12074                 :     {
                              12075                 :         /* Parser should not have set funcvariadic unless fn is variadic */
 3293                         12076            4299 :         Assert(!has_variadic || OidIsValid(procform->provariadic));
                              12077            4299 :         use_variadic = has_variadic;
 3730 tgl                     12078 CBC        4299 :         *use_variadic_p = use_variadic;
                              12079                 :     }
 3730 tgl                     12080 ECB             :     else
                              12081                 :     {
 3293 tgl                     12082 GIC         808 :         Assert(!has_variadic);
 3730                         12083             808 :         use_variadic = false;
 3730 tgl                     12084 ECB             :     }
                              12085                 : 
                              12086                 :     /*
 7646                         12087                 :      * The idea here is to schema-qualify only if the parser would fail to
                              12088                 :      * resolve the correct function given the unqualified func name with the
 2885 andres                  12089                 :      * specified argtypes and VARIADIC flag.  But if we already decided to
                              12090                 :      * force qualification, then we can skip the lookup and pretend we didn't
                              12091                 :      * find it.
                              12092                 :      */
 2885 andres                  12093 CBC        5107 :     if (!force_qualify)
 2885 andres                  12094 GIC        5107 :         p_result = func_get_detail(list_make1(makeString(proname)),
 2885 andres                  12095 ECB             :                                    NIL, argnames, nargs, argtypes,
  668 tgl                     12096 CBC        5107 :                                    !use_variadic, true, false,
 2885 andres                  12097 ECB             :                                    &p_funcid, &p_rettype,
                              12098                 :                                    &p_retset, &p_nvargs, &p_vatype,
 2885 andres                  12099 CBC        5107 :                                    &p_true_typeids, NULL);
 2885 andres                  12100 ECB             :     else
                              12101                 :     {
 2885 andres                  12102 LBC           0 :         p_result = FUNCDETAIL_NOTFOUND;
 2885 andres                  12103 UIC           0 :         p_funcid = InvalidOid;
                              12104                 :     }
                              12105                 : 
 5215 tgl                     12106 GIC        5107 :     if ((p_result == FUNCDETAIL_NORMAL ||
                              12107             589 :          p_result == FUNCDETAIL_AGGREGATE ||
                              12108            4569 :          p_result == FUNCDETAIL_WINDOWFUNC) &&
 7219                         12109            4569 :         p_funcid == funcid)
 7646                         12110            4569 :         nspname = NULL;
                              12111                 :     else
  621 tgl                     12112 CBC         538 :         nspname = get_namespace_name_or_temp(procform->pronamespace);
                              12113                 : 
 7646 tgl                     12114 GIC        5107 :     result = quote_qualified_identifier(nspname, proname);
                              12115                 : 
                              12116            5107 :     ReleaseSysCache(proctup);
 7646 tgl                     12117 ECB             : 
 7646 tgl                     12118 CBC        5107 :     return result;
 7646 tgl                     12119 ECB             : }
                              12120                 : 
                              12121                 : /*
                              12122                 :  * generate_operator_name
                              12123                 :  *      Compute the name to display for an operator specified by OID,
                              12124                 :  *      given that it is being called with the specified actual arg types.
                              12125                 :  *      (Arg types matter because of ambiguous-operator resolution rules.
                              12126                 :  *      Pass InvalidOid for unused arg of a unary operator.)
                              12127                 :  *
                              12128                 :  * The result includes all necessary quoting and schema-prefixing,
                              12129                 :  * plus the OPERATOR() decoration needed to use a qualified operator name
                              12130                 :  * in an expression.
                              12131                 :  */
                              12132                 : static char *
 7646 tgl                     12133 GIC       26028 : generate_operator_name(Oid operid, Oid arg1, Oid arg2)
 7646 tgl                     12134 ECB             : {
                              12135                 :     StringInfoData buf;
                              12136                 :     HeapTuple   opertup;
 7646 tgl                     12137 EUB             :     Form_pg_operator operform;
 7646 tgl                     12138 ECB             :     char       *oprname;
                              12139                 :     char       *nspname;
                              12140                 :     Operator    p_result;
                              12141                 : 
 7646 tgl                     12142 GIC       26028 :     initStringInfo(&buf);
                              12143                 : 
 4802 rhaas                   12144           26028 :     opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
 7646 tgl                     12145           26028 :     if (!HeapTupleIsValid(opertup))
 7196 tgl                     12146 UIC           0 :         elog(ERROR, "cache lookup failed for operator %u", operid);
 7646 tgl                     12147 GIC       26028 :     operform = (Form_pg_operator) GETSTRUCT(opertup);
                              12148           26028 :     oprname = NameStr(operform->oprname);
                              12149                 : 
                              12150                 :     /*
                              12151                 :      * The idea here is to schema-qualify only if the parser would fail to
 7522 bruce                   12152 ECB             :      * resolve the correct operator given the unqualified op name with the
                              12153                 :      * specified argtypes.
                              12154                 :      */
 7646 tgl                     12155 GIC       26028 :     switch (operform->oprkind)
                              12156                 :     {
                              12157           26013 :         case 'b':
 6235                         12158           26013 :             p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
                              12159                 :                             true, -1);
 7646                         12160           26013 :             break;
                              12161              15 :         case 'l':
 6235 tgl                     12162 CBC          15 :             p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
 6235 tgl                     12163 ECB             :                                  true, -1);
 7646 tgl                     12164 GBC          15 :             break;
 7646 tgl                     12165 LBC           0 :         default:
 7196                         12166               0 :             elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
                              12167                 :             p_result = NULL;    /* keep compiler quiet */
                              12168                 :             break;
 7646 tgl                     12169 ECB             :     }
                              12170                 : 
 7646 tgl                     12171 GIC       26028 :     if (p_result != NULL && oprid(p_result) == operid)
 7646 tgl                     12172 CBC       26023 :         nspname = NULL;
                              12173                 :     else
                              12174                 :     {
  621                         12175               5 :         nspname = get_namespace_name_or_temp(operform->oprnamespace);
 7646 tgl                     12176 GIC           5 :         appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
 7646 tgl                     12177 ECB             :     }
                              12178                 : 
 7008 neilc                   12179 CBC       26028 :     appendStringInfoString(&buf, oprname);
                              12180                 : 
 7646 tgl                     12181 GBC       26028 :     if (nspname)
                              12182               5 :         appendStringInfoChar(&buf, ')');
                              12183                 : 
 7646 tgl                     12184 GIC       26028 :     if (p_result != NULL)
 7646 tgl                     12185 CBC       26023 :         ReleaseSysCache(p_result);
 7646 tgl                     12186 EUB             : 
 7646 tgl                     12187 GIC       26028 :     ReleaseSysCache(opertup);
                              12188                 : 
                              12189           26028 :     return buf.data;
 7646 tgl                     12190 ECB             : }
                              12191                 : 
                              12192                 : /*
 1847                         12193                 :  * generate_operator_clause --- generate a binary-operator WHERE clause
                              12194                 :  *
                              12195                 :  * This is used for internally-generated-and-executed SQL queries, where
                              12196                 :  * precision is essential and readability is secondary.  The basic
                              12197                 :  * requirement is to append "leftop op rightop" to buf, where leftop and
                              12198                 :  * rightop are given as strings and are assumed to yield types leftoptype
                              12199                 :  * and rightoptype; the operator is identified by OID.  The complexity
                              12200                 :  * comes from needing to be sure that the parser will select the desired
                              12201                 :  * operator when the query is parsed.  We always name the operator using
                              12202                 :  * OPERATOR(schema.op) syntax, so as to avoid search-path uncertainties.
                              12203                 :  * We have to emit casts too, if either input isn't already the input type
                              12204                 :  * of the operator; else we are at the mercy of the parser's heuristics for
                              12205                 :  * ambiguous-operator resolution.  The caller must ensure that leftop and
                              12206                 :  * rightop are suitable arguments for a cast operation; it's best to insert
                              12207                 :  * parentheses if they aren't just variables or parameters.
                              12208                 :  */
                              12209                 : void
 1847 tgl                     12210 GIC        2508 : generate_operator_clause(StringInfo buf,
                              12211                 :                          const char *leftop, Oid leftoptype,
 1847 tgl                     12212 ECB             :                          Oid opoid,
                              12213                 :                          const char *rightop, Oid rightoptype)
                              12214                 : {
                              12215                 :     HeapTuple   opertup;
                              12216                 :     Form_pg_operator operform;
                              12217                 :     char       *oprname;
                              12218                 :     char       *nspname;
                              12219                 : 
 1847 tgl                     12220 CBC        2508 :     opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
                              12221            2508 :     if (!HeapTupleIsValid(opertup))
 1847 tgl                     12222 UBC           0 :         elog(ERROR, "cache lookup failed for operator %u", opoid);
 1847 tgl                     12223 CBC        2508 :     operform = (Form_pg_operator) GETSTRUCT(opertup);
                              12224            2508 :     Assert(operform->oprkind == 'b');
 1847 tgl                     12225 GIC        2508 :     oprname = NameStr(operform->oprname);
 1847 tgl                     12226 ECB             : 
 1847 tgl                     12227 CBC        2508 :     nspname = get_namespace_name(operform->oprnamespace);
 1847 tgl                     12228 EUB             : 
 1847 tgl                     12229 GIC        2508 :     appendStringInfoString(buf, leftop);
                              12230            2508 :     if (leftoptype != operform->oprleft)
 1847 tgl                     12231 CBC          21 :         add_cast_to(buf, operform->oprleft);
 1847 tgl                     12232 GIC        2508 :     appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
 1847 tgl                     12233 CBC        2508 :     appendStringInfoString(buf, oprname);
 1847 tgl                     12234 GIC        2508 :     appendStringInfo(buf, ") %s", rightop);
 1847 tgl                     12235 CBC        2508 :     if (rightoptype != operform->oprright)
 1847 tgl                     12236 GIC          30 :         add_cast_to(buf, operform->oprright);
                              12237                 : 
                              12238            2508 :     ReleaseSysCache(opertup);
                              12239            2508 : }
                              12240                 : 
                              12241                 : /*
                              12242                 :  * Add a cast specification to buf.  We spell out the type name the hard way,
                              12243                 :  * intentionally not using format_type_be().  This is to avoid corner cases
                              12244                 :  * for CHARACTER, BIT, and perhaps other types, where specifying the type
                              12245                 :  * using SQL-standard syntax results in undesirable data truncation.  By
                              12246                 :  * doing it this way we can be certain that the cast will have default (-1)
                              12247                 :  * target typmod.
                              12248                 :  */
                              12249                 : static void
                              12250              51 : add_cast_to(StringInfo buf, Oid typid)
                              12251                 : {
                              12252                 :     HeapTuple   typetup;
                              12253                 :     Form_pg_type typform;
 1847 tgl                     12254 ECB             :     char       *typname;
                              12255                 :     char       *nspname;
                              12256                 : 
 1847 tgl                     12257 GIC          51 :     typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
                              12258              51 :     if (!HeapTupleIsValid(typetup))
 1847 tgl                     12259 UIC           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
 1847 tgl                     12260 GIC          51 :     typform = (Form_pg_type) GETSTRUCT(typetup);
                              12261                 : 
                              12262              51 :     typname = NameStr(typform->typname);
  621                         12263              51 :     nspname = get_namespace_name_or_temp(typform->typnamespace);
                              12264                 : 
 1847                         12265              51 :     appendStringInfo(buf, "::%s.%s",
                              12266                 :                      quote_identifier(nspname), quote_identifier(typname));
                              12267                 : 
                              12268              51 :     ReleaseSysCache(typetup);
                              12269              51 : }
                              12270                 : 
 1985 tgl                     12271 ECB             : /*
                              12272                 :  * generate_qualified_type_name
                              12273                 :  *      Compute the name to display for a type specified by OID
                              12274                 :  *
 1985 tgl                     12275 EUB             :  * This is different from format_type_be() in that we unconditionally
 1985 tgl                     12276 ECB             :  * schema-qualify the name.  That also means no special syntax for
                              12277                 :  * SQL-standard type names ... although in current usage, this should
                              12278                 :  * only get used for domains, so such cases wouldn't occur anyway.
                              12279                 :  */
                              12280                 : static char *
 1985 tgl                     12281 GIC           7 : generate_qualified_type_name(Oid typid)
                              12282                 : {
 1985 tgl                     12283 ECB             :     HeapTuple   tp;
                              12284                 :     Form_pg_type typtup;
 1985 tgl                     12285 EUB             :     char       *typname;
                              12286                 :     char       *nspname;
                              12287                 :     char       *result;
                              12288                 : 
 1985 tgl                     12289 GIC           7 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
                              12290               7 :     if (!HeapTupleIsValid(tp))
 1985 tgl                     12291 UIC           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
 1985 tgl                     12292 GIC           7 :     typtup = (Form_pg_type) GETSTRUCT(tp);
                              12293               7 :     typname = NameStr(typtup->typname);
                              12294                 : 
  621                         12295               7 :     nspname = get_namespace_name_or_temp(typtup->typnamespace);
 1985                         12296               7 :     if (!nspname)
 1985 tgl                     12297 UIC           0 :         elog(ERROR, "cache lookup failed for namespace %u",
                              12298                 :              typtup->typnamespace);
 1985 tgl                     12299 ECB             : 
 1985 tgl                     12300 GIC           7 :     result = quote_qualified_identifier(nspname, typname);
                              12301                 : 
 1985 tgl                     12302 CBC           7 :     ReleaseSysCache(tp);
 1985 tgl                     12303 ECB             : 
 1985 tgl                     12304 CBC           7 :     return result;
                              12305                 : }
                              12306                 : 
                              12307                 : /*
 4443 peter_e                 12308 ECB             :  * generate_collation_name
                              12309                 :  *      Compute the name to display for a collation specified by OID
                              12310                 :  *
                              12311                 :  * The result includes all necessary quoting and schema-prefixing.
                              12312                 :  */
                              12313                 : char *
 4443 peter_e                 12314 GIC         155 : generate_collation_name(Oid collid)
                              12315                 : {
                              12316                 :     HeapTuple   tp;
                              12317                 :     Form_pg_collation colltup;
                              12318                 :     char       *collname;
 4443 peter_e                 12319 ECB             :     char       *nspname;
                              12320                 :     char       *result;
                              12321                 : 
 4443 peter_e                 12322 CBC         155 :     tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
 4443 peter_e                 12323 GIC         155 :     if (!HeapTupleIsValid(tp))
 4443 peter_e                 12324 UIC           0 :         elog(ERROR, "cache lookup failed for collation %u", collid);
 4443 peter_e                 12325 CBC         155 :     colltup = (Form_pg_collation) GETSTRUCT(tp);
 4443 peter_e                 12326 GIC         155 :     collname = NameStr(colltup->collname);
                              12327                 : 
 4443 peter_e                 12328 GBC         155 :     if (!CollationIsVisible(collid))
  621 tgl                     12329 UBC           0 :         nspname = get_namespace_name_or_temp(colltup->collnamespace);
                              12330                 :     else
 4443 peter_e                 12331 GIC         155 :         nspname = NULL;
 4443 peter_e                 12332 ECB             : 
 4443 peter_e                 12333 CBC         155 :     result = quote_qualified_identifier(nspname, collname);
 4443 peter_e                 12334 ECB             : 
 4443 peter_e                 12335 CBC         155 :     ReleaseSysCache(tp);
 4443 peter_e                 12336 ECB             : 
 4443 peter_e                 12337 GIC         155 :     return result;
 4443 peter_e                 12338 ECB             : }
                              12339                 : 
 6913 tgl                     12340                 : /*
                              12341                 :  * Given a C string, produce a TEXT datum.
                              12342                 :  *
                              12343                 :  * We assume that the input was palloc'd and may be freed.
                              12344                 :  */
                              12345                 : static text *
 6913 tgl                     12346 GIC       18304 : string_to_text(char *str)
                              12347                 : {
                              12348                 :     text       *result;
                              12349                 : 
 5493                         12350           18304 :     result = cstring_to_text(str);
 6913                         12351           18304 :     pfree(str);
                              12352           18304 :     return result;
                              12353                 : }
                              12354                 : 
                              12355                 : /*
                              12356                 :  * Generate a C string representing a relation options from text[] datum.
                              12357                 :  */
                              12358                 : static void
 1105 akorotkov               12359 CBC         120 : get_reloptions(StringInfo buf, Datum reloptions)
                              12360                 : {
                              12361                 :     Datum      *options;
                              12362                 :     int         noptions;
                              12363                 :     int         i;
                              12364                 : 
  282 peter                   12365 GNC         120 :     deconstruct_array_builtin(DatumGetArrayTypeP(reloptions), TEXTOID,
                              12366                 :                               &options, NULL, &noptions);
 1105 akorotkov               12367 ECB             : 
 1105 akorotkov               12368 GIC         250 :     for (i = 0; i < noptions; i++)
 1105 akorotkov               12369 ECB             :     {
 1105 akorotkov               12370 CBC         130 :         char       *option = TextDatumGetCString(options[i]);
 1105 akorotkov               12371 EUB             :         char       *name;
 1105 akorotkov               12372 ECB             :         char       *separator;
                              12373                 :         char       *value;
                              12374                 : 
                              12375                 :         /*
                              12376                 :          * Each array element should have the form name=value.  If the "=" is
                              12377                 :          * missing for some reason, treat it like an empty value.
                              12378                 :          */
 1105 akorotkov               12379 GIC         130 :         name = option;
 1105 akorotkov               12380 CBC         130 :         separator = strchr(option, '=');
 1105 akorotkov               12381 GIC         130 :         if (separator)
 1105 akorotkov               12382 ECB             :         {
 1105 akorotkov               12383 CBC         130 :             *separator = '\0';
 1105 akorotkov               12384 GIC         130 :             value = separator + 1;
 1105 akorotkov               12385 ECB             :         }
                              12386                 :         else
 1105 akorotkov               12387 LBC           0 :             value = "";
                              12388                 : 
 1105 akorotkov               12389 CBC         130 :         if (i > 0)
 1105 akorotkov               12390 GBC          10 :             appendStringInfoString(buf, ", ");
                              12391             130 :         appendStringInfo(buf, "%s=", quote_identifier(name));
                              12392                 : 
                              12393                 :         /*
                              12394                 :          * In general we need to quote the value; but to avoid unnecessary
                              12395                 :          * clutter, do not quote if it is an identifier that would not need
 1060 tgl                     12396 ECB             :          * quoting.  (We could also allow numbers, but that is a bit trickier
                              12397                 :          * than it looks --- for example, are leading zeroes significant?  We
                              12398                 :          * don't want to assume very much here about what custom reloptions
                              12399                 :          * might mean.)
 1105 akorotkov               12400                 :          */
 1105 akorotkov               12401 CBC         130 :         if (quote_identifier(value) == value)
 1105 akorotkov               12402 GIC           4 :             appendStringInfoString(buf, value);
                              12403                 :         else
 1105 akorotkov               12404 CBC         126 :             simple_quote_literal(buf, value);
                              12405                 : 
                              12406             130 :         pfree(option);
 1105 akorotkov               12407 ECB             :     }
 1105 akorotkov               12408 GIC         120 : }
 1105 akorotkov               12409 ECB             : 
 6124 tgl                     12410                 : /*
                              12411                 :  * Generate a C string representing a relation's reloptions, or NULL if none.
                              12412                 :  */
                              12413                 : static char *
 6125 bruce                   12414 CBC        2949 : flatten_reloptions(Oid relid)
                              12415                 : {
 6125 bruce                   12416 GIC        2949 :     char       *result = NULL;
                              12417                 :     HeapTuple   tuple;
                              12418                 :     Datum       reloptions;
                              12419                 :     bool        isnull;
                              12420                 : 
 4802 rhaas                   12421            2949 :     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
 6124 tgl                     12422            2949 :     if (!HeapTupleIsValid(tuple))
 6124 tgl                     12423 UIC           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
                              12424                 : 
 6124 tgl                     12425 GIC        2949 :     reloptions = SysCacheGetAttr(RELOID, tuple,
                              12426                 :                                  Anum_pg_class_reloptions, &isnull);
                              12427            2949 :     if (!isnull)
                              12428                 :     {
                              12429                 :         StringInfoData buf;
                              12430                 : 
 2655                         12431             105 :         initStringInfo(&buf);
 1105 akorotkov               12432             105 :         get_reloptions(&buf, reloptions);
                              12433                 : 
 2655 tgl                     12434             105 :         result = buf.data;
 6125 bruce                   12435 ECB             :     }
                              12436                 : 
 6124 tgl                     12437 GIC        2949 :     ReleaseSysCache(tuple);
                              12438                 : 
 6125 bruce                   12439            2949 :     return result;
                              12440                 : }
                              12441                 : 
                              12442                 : /*
                              12443                 :  * get_range_partbound_string
                              12444                 :  *      A C string representation of one range partition bound
 2068 rhaas                   12445 ECB             :  */
                              12446                 : char *
 2068 rhaas                   12447 GBC        2034 : get_range_partbound_string(List *bound_datums)
 2068 rhaas                   12448 ECB             : {
                              12449                 :     deparse_context context;
 2068 rhaas                   12450 CBC        2034 :     StringInfo  buf = makeStringInfo();
                              12451                 :     ListCell   *cell;
 2068 rhaas                   12452 ECB             :     char       *sep;
                              12453                 : 
 2068 rhaas                   12454 CBC        2034 :     memset(&context, 0, sizeof(deparse_context));
                              12455            2034 :     context.buf = buf;
 2068 rhaas                   12456 ECB             : 
  906 drowley                 12457 CBC        2034 :     appendStringInfoChar(buf, '(');
 2068 rhaas                   12458            2034 :     sep = "";
                              12459            4464 :     foreach(cell, bound_datums)
 2068 rhaas                   12460 ECB             :     {
                              12461                 :         PartitionRangeDatum *datum =
  629 peter                   12462 GIC        2430 :         lfirst_node(PartitionRangeDatum, cell);
 2068 rhaas                   12463 ECB             : 
 2068 rhaas                   12464 CBC        2430 :         appendStringInfoString(buf, sep);
 2068 rhaas                   12465 GIC        2430 :         if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
                              12466             111 :             appendStringInfoString(buf, "MINVALUE");
                              12467            2319 :         else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
                              12468              60 :             appendStringInfoString(buf, "MAXVALUE");
                              12469                 :         else
                              12470                 :         {
                              12471            2259 :             Const      *val = castNode(Const, datum->value);
                              12472                 : 
                              12473            2259 :             get_const_expr(val, &context, -1);
                              12474                 :         }
 2068 rhaas                   12475 CBC        2430 :         sep = ", ";
                              12476                 :     }
 2063 peter_e                 12477 GIC        2034 :     appendStringInfoChar(buf, ')');
                              12478                 : 
 2068 rhaas                   12479            2034 :     return buf->data;
                              12480                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a