PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ruleutils.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "access/amapi.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/partition.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_language.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/tablespace.h"
#include "common/keywords.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/tlist.h"
#include "parser/parse_node.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parser.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSupport.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
#include "utils/typcache.h"
#include "utils/varlena.h"
#include "utils/xml.h"
Include dependency graph for ruleutils.c:

Go to the source code of this file.

Data Structures

struct  deparse_context
 
struct  deparse_namespace
 
struct  deparse_columns
 
struct  NameHashEntry
 

Macros

#define PRETTYINDENT_STD   8
 
#define PRETTYINDENT_JOIN   4
 
#define PRETTYINDENT_VAR   4
 
#define PRETTYINDENT_LIMIT   40 /* wrap limit */
 
#define PRETTYFLAG_PAREN   1
 
#define PRETTYFLAG_INDENT   2
 
#define WRAP_COLUMN_DEFAULT   0
 
#define PRETTY_PAREN(context)   ((context)->prettyFlags & PRETTYFLAG_PAREN)
 
#define PRETTY_INDENT(context)   ((context)->prettyFlags & PRETTYFLAG_INDENT)
 
#define deparse_columns_fetch(rangetable_index, dpns)   ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
 
#define only_marker(rte)   ((rte)->inh ? "" : "ONLY ")
 

Functions

static char * deparse_expression_pretty (Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
 
static char * pg_get_viewdef_worker (Oid viewoid, int prettyFlags, int wrapColumn)
 
static char * pg_get_triggerdef_worker (Oid trigid, bool pretty)
 
static void decompile_column_index_array (Datum column_index_array, Oid relId, StringInfo buf)
 
static char * pg_get_ruledef_worker (Oid ruleoid, int prettyFlags)
 
static char * pg_get_indexdef_worker (Oid indexrelid, int colno, const Oid *excludeOps, bool attrsOnly, bool showTblSpc, int prettyFlags, bool missing_ok)
 
static char * pg_get_statisticsobj_worker (Oid statextid, bool missing_ok)
 
static char * pg_get_partkeydef_worker (Oid relid, int prettyFlags, bool attrsOnly, bool missing_ok)
 
static char * pg_get_constraintdef_worker (Oid constraintId, bool fullCommand, int prettyFlags, bool missing_ok)
 
static textpg_get_expr_worker (text *expr, Oid relid, const char *relname, int prettyFlags)
 
static int print_function_arguments (StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults)
 
static void print_function_rettype (StringInfo buf, HeapTuple proctup)
 
static void print_function_trftypes (StringInfo buf, HeapTuple proctup)
 
static void set_rtable_names (deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
 
static void set_deparse_for_query (deparse_namespace *dpns, Query *query, List *parent_namespaces)
 
static void set_simple_column_names (deparse_namespace *dpns)
 
static bool has_dangerous_join_using (deparse_namespace *dpns, Node *jtnode)
 
static void set_using_names (deparse_namespace *dpns, Node *jtnode, List *parentUsing)
 
static void set_relation_column_names (deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
 
static void set_join_column_names (deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
 
static bool colname_is_unique (char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
 
static char * make_colname_unique (char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
 
static void expand_colnames_array_to (deparse_columns *colinfo, int n)
 
static void identify_join_columns (JoinExpr *j, RangeTblEntry *jrte, deparse_columns *colinfo)
 
static void flatten_join_using_qual (Node *qual, List **leftvars, List **rightvars)
 
static char * get_rtable_name (int rtindex, deparse_context *context)
 
static void set_deparse_planstate (deparse_namespace *dpns, PlanState *ps)
 
static void push_child_plan (deparse_namespace *dpns, PlanState *ps, deparse_namespace *save_dpns)
 
static void pop_child_plan (deparse_namespace *dpns, deparse_namespace *save_dpns)
 
static void push_ancestor_plan (deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
 
static void pop_ancestor_plan (deparse_namespace *dpns, deparse_namespace *save_dpns)
 
static void make_ruledef (StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags)
 
static void make_viewdef (StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags, int wrapColumn)
 
static void get_query_def (Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
 
static void get_values_def (List *values_lists, deparse_context *context)
 
static void get_with_clause (Query *query, deparse_context *context)
 
static void get_select_query_def (Query *query, deparse_context *context, TupleDesc resultDesc)
 
static void get_insert_query_def (Query *query, deparse_context *context)
 
static void get_update_query_def (Query *query, deparse_context *context)
 
static void get_update_query_targetlist_def (Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
 
static void get_delete_query_def (Query *query, deparse_context *context)
 
static void get_utility_query_def (Query *query, deparse_context *context)
 
static void get_basic_select_query (Query *query, deparse_context *context, TupleDesc resultDesc)
 
static void get_target_list (List *targetList, deparse_context *context, TupleDesc resultDesc)
 
static void get_setop_query (Node *setOp, Query *query, deparse_context *context, TupleDesc resultDesc)
 
static Nodeget_rule_sortgroupclause (Index ref, List *tlist, bool force_colno, deparse_context *context)
 
static void get_rule_groupingset (GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
 
static void get_rule_orderby (List *orderList, List *targetList, bool force_colno, deparse_context *context)
 
static void get_rule_windowclause (Query *query, deparse_context *context)
 
static void get_rule_windowspec (WindowClause *wc, List *targetList, deparse_context *context)
 
static char * get_variable (Var *var, int levelsup, bool istoplevel, deparse_context *context)
 
static void get_special_variable (Node *node, deparse_context *context, void *private)
 
static void resolve_special_varno (Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
 
static Nodefind_param_referent (Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
 
static void get_parameter (Param *param, deparse_context *context)
 
static const char * get_simple_binary_op_name (OpExpr *expr)
 
static bool isSimpleNode (Node *node, Node *parentNode, int prettyFlags)
 
static void appendContextKeyword (deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
 
static void removeStringInfoSpaces (StringInfo str)
 
static void get_rule_expr (Node *node, deparse_context *context, bool showimplicit)
 
static void get_rule_expr_toplevel (Node *node, deparse_context *context, bool showimplicit)
 
static void get_rule_expr_funccall (Node *node, deparse_context *context, bool showimplicit)
 
static bool looks_like_function (Node *node)
 
static void get_oper_expr (OpExpr *expr, deparse_context *context)
 
static void get_func_expr (FuncExpr *expr, deparse_context *context, bool showimplicit)
 
static void get_agg_expr (Aggref *aggref, deparse_context *context, Aggref *original_aggref)
 
static void get_agg_combine_expr (Node *node, deparse_context *context, void *private)
 
static void get_windowfunc_expr (WindowFunc *wfunc, deparse_context *context)
 
static void get_coercion_expr (Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
 
static void get_const_expr (Const *constval, deparse_context *context, int showtype)
 
static void get_const_collation (Const *constval, deparse_context *context)
 
static void simple_quote_literal (StringInfo buf, const char *val)
 
static void get_sublink_expr (SubLink *sublink, deparse_context *context)
 
static void get_tablefunc (TableFunc *tf, deparse_context *context, bool showimplicit)
 
static void get_from_clause (Query *query, const char *prefix, deparse_context *context)
 
static void get_from_clause_item (Node *jtnode, Query *query, deparse_context *context)
 
static void get_column_alias_list (deparse_columns *colinfo, deparse_context *context)
 
static void get_from_clause_coldeflist (RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
 
static void get_tablesample_def (TableSampleClause *tablesample, deparse_context *context)
 
static void get_opclass_name (Oid opclass, Oid actual_datatype, StringInfo buf)
 
static NodeprocessIndirection (Node *node, deparse_context *context)
 
static void printSubscripts (ArrayRef *aref, deparse_context *context)
 
static char * get_relation_name (Oid relid)
 
static char * generate_relation_name (Oid relid, List *namespaces)
 
static char * generate_qualified_relation_name (Oid relid)
 
static char * generate_function_name (Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
 
static char * generate_operator_name (Oid operid, Oid arg1, Oid arg2)
 
static textstring_to_text (char *str)
 
static char * flatten_reloptions (Oid relid)
 
Datum pg_get_ruledef (PG_FUNCTION_ARGS)
 
Datum pg_get_ruledef_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_viewdef (PG_FUNCTION_ARGS)
 
Datum pg_get_viewdef_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_viewdef_wrap (PG_FUNCTION_ARGS)
 
Datum pg_get_viewdef_name (PG_FUNCTION_ARGS)
 
Datum pg_get_viewdef_name_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_triggerdef (PG_FUNCTION_ARGS)
 
Datum pg_get_triggerdef_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_indexdef (PG_FUNCTION_ARGS)
 
Datum pg_get_indexdef_ext (PG_FUNCTION_ARGS)
 
char * pg_get_indexdef_string (Oid indexrelid)
 
char * pg_get_indexdef_columns (Oid indexrelid, bool pretty)
 
Datum pg_get_statisticsobjdef (PG_FUNCTION_ARGS)
 
Datum pg_get_partkeydef (PG_FUNCTION_ARGS)
 
char * pg_get_partkeydef_columns (Oid relid, bool pretty)
 
Datum pg_get_partition_constraintdef (PG_FUNCTION_ARGS)
 
Datum pg_get_constraintdef (PG_FUNCTION_ARGS)
 
Datum pg_get_constraintdef_ext (PG_FUNCTION_ARGS)
 
char * pg_get_constraintdef_command (Oid constraintId)
 
Datum pg_get_expr (PG_FUNCTION_ARGS)
 
Datum pg_get_expr_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_userbyid (PG_FUNCTION_ARGS)
 
Datum pg_get_serial_sequence (PG_FUNCTION_ARGS)
 
Datum pg_get_functiondef (PG_FUNCTION_ARGS)
 
Datum pg_get_function_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_identity_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_result (PG_FUNCTION_ARGS)
 
static bool is_input_argument (int nth, const char *argmodes)
 
Datum pg_get_function_arg_default (PG_FUNCTION_ARGS)
 
char * deparse_expression (Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
 
Listdeparse_context_for (const char *aliasname, Oid relid)
 
Listdeparse_context_for_plan_rtable (List *rtable, List *rtable_names)
 
Listset_deparse_context_planstate (List *dpcontext, Node *planstate, List *ancestors)
 
Listselect_rtable_names_for_explain (List *rtable, Bitmapset *rels_used)
 
static RangeTblEntryget_simple_values_rte (Query *query)
 
static const char * get_name_for_var_field (Var *var, int fieldno, int levelsup, deparse_context *context)
 
static void get_rule_expr_paren (Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
 
const char * quote_identifier (const char *ident)
 
char * quote_qualified_identifier (const char *qualifier, const char *ident)
 
char * generate_collation_name (Oid collid)
 
char * get_range_partbound_string (List *bound_datums)
 

Variables

static SPIPlanPtr plan_getrulebyoid = NULL
 
static const char * query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1"
 
static SPIPlanPtr plan_getviewrule = NULL
 
static const char * query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2"
 
bool quote_all_identifiers = false
 

Macro Definition Documentation

#define deparse_columns_fetch (   rangetable_index,
  dpns 
)    ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))
#define only_marker (   rte)    ((rte)->inh ? "" : "ONLY ")

Definition at line 466 of file ruleutils.c.

Referenced by get_delete_query_def(), get_from_clause_item(), and get_update_query_def().

#define PRETTY_PAREN (   context)    ((context)->prettyFlags & PRETTYFLAG_PAREN)
#define PRETTYINDENT_JOIN   4

Definition at line 83 of file ruleutils.c.

Referenced by get_from_clause_item().

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 86 of file ruleutils.c.

Referenced by appendContextKeyword().

#define PRETTYINDENT_VAR   4

Definition at line 84 of file ruleutils.c.

Referenced by get_from_clause(), get_rule_expr(), and get_target_list().

Function Documentation

static void appendContextKeyword ( deparse_context context,
const char *  str,
int  indentBefore,
int  indentAfter,
int  indentPlus 
)
static

Definition at line 7495 of file ruleutils.c.

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoString(), buf, deparse_context::buf, deparse_context::indentLevel, Max, PRETTY_INDENT, PRETTYINDENT_LIMIT, PRETTYINDENT_STD, and removeStringInfoSpaces().

Referenced by get_basic_select_query(), get_delete_query_def(), get_from_clause(), get_from_clause_item(), get_insert_query_def(), get_rule_expr(), get_rule_windowclause(), get_select_query_def(), get_setop_query(), get_target_list(), get_update_query_def(), get_utility_query_def(), and get_with_clause().

7497 {
7498  StringInfo buf = context->buf;
7499 
7500  if (PRETTY_INDENT(context))
7501  {
7502  int indentAmount;
7503 
7504  context->indentLevel += indentBefore;
7505 
7506  /* remove any trailing spaces currently in the buffer ... */
7508  /* ... then add a newline and some spaces */
7509  appendStringInfoChar(buf, '\n');
7510 
7511  if (context->indentLevel < PRETTYINDENT_LIMIT)
7512  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7513  else
7514  {
7515  /*
7516  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7517  * to conserve horizontal space by reducing the per-level
7518  * indentation. For best results the scale factor here should
7519  * divide all the indent amounts that get added to indentLevel
7520  * (PRETTYINDENT_STD, etc). It's important that the indentation
7521  * not grow unboundedly, else deeply-nested trees use O(N^2)
7522  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7523  */
7524  indentAmount = PRETTYINDENT_LIMIT +
7525  (context->indentLevel - PRETTYINDENT_LIMIT) /
7526  (PRETTYINDENT_STD / 2);
7527  indentAmount %= PRETTYINDENT_LIMIT;
7528  /* scale/wrap logic affects indentLevel, but not indentPlus */
7529  indentAmount += indentPlus;
7530  }
7531  appendStringInfoSpaces(buf, indentAmount);
7532 
7533  appendStringInfoString(buf, str);
7534 
7535  context->indentLevel += indentAfter;
7536  if (context->indentLevel < 0)
7537  context->indentLevel = 0;
7538  }
7539  else
7540  appendStringInfoString(buf, str);
7541 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7549
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:86
#define Max(x, y)
Definition: c.h:806
StringInfo buf
Definition: ruleutils.c:108
static bool colname_is_unique ( char *  colname,
deparse_namespace dpns,
deparse_columns colinfo 
)
static

Definition at line 4103 of file ruleutils.c.

References deparse_columns::colnames, i, lfirst, deparse_columns::new_colnames, deparse_columns::num_cols, deparse_columns::num_new_cols, deparse_columns::parentUsing, and deparse_namespace::using_names.

Referenced by make_colname_unique().

4105 {
4106  int i;
4107  ListCell *lc;
4108 
4109  /* Check against already-assigned column aliases within RTE */
4110  for (i = 0; i < colinfo->num_cols; i++)
4111  {
4112  char *oldname = colinfo->colnames[i];
4113 
4114  if (oldname && strcmp(oldname, colname) == 0)
4115  return false;
4116  }
4117 
4118  /*
4119  * If we're building a new_colnames array, check that too (this will be
4120  * partially but not completely redundant with the previous checks)
4121  */
4122  for (i = 0; i < colinfo->num_new_cols; i++)
4123  {
4124  char *oldname = colinfo->new_colnames[i];
4125 
4126  if (oldname && strcmp(oldname, colname) == 0)
4127  return false;
4128  }
4129 
4130  /* Also check against USING-column names that must be globally unique */
4131  foreach(lc, dpns->using_names)
4132  {
4133  char *oldname = (char *) lfirst(lc);
4134 
4135  if (strcmp(oldname, colname) == 0)
4136  return false;
4137  }
4138 
4139  /* Also check against names already assigned for parent-join USING cols */
4140  foreach(lc, colinfo->parentUsing)
4141  {
4142  char *oldname = (char *) lfirst(lc);
4143 
4144  if (strcmp(oldname, colname) == 0)
4145  return false;
4146  }
4147 
4148  return true;
4149 }
List * using_names
Definition: ruleutils.c:155
#define lfirst(lc)
Definition: pg_list.h:106
int i
List * parentUsing
Definition: ruleutils.c:249
char ** new_colnames
Definition: ruleutils.c:242
char ** colnames
Definition: ruleutils.c:225
static void decompile_column_index_array ( Datum  column_index_array,
Oid  relId,
StringInfo  buf 
)
static

Definition at line 2163 of file ruleutils.c.

References appendStringInfo(), appendStringInfoString(), DatumGetArrayTypeP, DatumGetInt16, deconstruct_array(), get_relid_attribute_name(), INT2OID, and quote_identifier().

Referenced by pg_get_constraintdef_worker().

2165 {
2166  Datum *keys;
2167  int nKeys;
2168  int j;
2169 
2170  /* Extract data from array of int16 */
2171  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2172  INT2OID, 2, true, 's',
2173  &keys, NULL, &nKeys);
2174 
2175  for (j = 0; j < nKeys; j++)
2176  {
2177  char *colName;
2178 
2179  colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
2180 
2181  if (j == 0)
2183  else
2184  appendStringInfo(buf, ", %s", quote_identifier(colName));
2185  }
2186 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define INT2OID
Definition: pg_type.h:308
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define DatumGetInt16(X)
Definition: postgres.h:450
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
uintptr_t Datum
Definition: postgres.h:372
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
#define DatumGetArrayTypeP(X)
Definition: array.h:246
List* deparse_context_for ( const char *  aliasname,
Oid  relid 
)

Definition at line 3044 of file ruleutils.c.

References RangeTblEntry::alias, deparse_namespace::ctes, RangeTblEntry::eref, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, list_make1, makeAlias(), makeNode, NIL, palloc0(), RangeTblEntry::relid, RangeTblEntry::relkind, RELKIND_RELATION, deparse_namespace::rtable, RTE_RELATION, RangeTblEntry::rtekind, set_rtable_names(), and set_simple_column_names().

Referenced by pg_get_constraintdef_worker(), pg_get_expr_worker(), pg_get_indexdef_worker(), pg_get_partition_constraintdef(), pg_get_partkeydef_worker(), StoreAttrDefault(), StoreRelCheck(), and transformPartitionBound().

3045 {
3046  deparse_namespace *dpns;
3047  RangeTblEntry *rte;
3048 
3049  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3050 
3051  /* Build a minimal RTE for the rel */
3052  rte = makeNode(RangeTblEntry);
3053  rte->rtekind = RTE_RELATION;
3054  rte->relid = relid;
3055  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3056  rte->alias = makeAlias(aliasname, NIL);
3057  rte->eref = rte->alias;
3058  rte->lateral = false;
3059  rte->inh = false;
3060  rte->inFromCl = true;
3061 
3062  /* Build one-element rtable */
3063  dpns->rtable = list_make1(rte);
3064  dpns->ctes = NIL;
3065  set_rtable_names(dpns, NIL, NULL);
3067 
3068  /* Return a one-deep namespace stack */
3069  return list_make1(dpns);
3070 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:1048
#define list_make1(x1)
Definition: pg_list.h:139
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:384
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3188
void * palloc0(Size size)
Definition: mcxt.c:877
#define makeNode(_type_)
Definition: nodes.h:558
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3401
RTEKind rtekind
Definition: parsenodes.h:945
Alias * eref
Definition: parsenodes.h:1049
#define RELKIND_RELATION
Definition: pg_class.h:160
List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

Definition at line 3086 of file ruleutils.c.

References deparse_namespace::ctes, list_make1, NIL, palloc0(), deparse_namespace::rtable, deparse_namespace::rtable_names, and set_simple_column_names().

Referenced by ExplainPrintPlan().

3087 {
3088  deparse_namespace *dpns;
3089 
3090  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3091 
3092  /* Initialize fields that stay the same across the whole plan tree */
3093  dpns->rtable = rtable;
3094  dpns->rtable_names = rtable_names;
3095  dpns->ctes = NIL;
3096 
3097  /*
3098  * Set up column name aliases. We will get rather bogus results for join
3099  * RTEs, but that doesn't matter because plan trees don't contain any join
3100  * alias Vars.
3101  */
3103 
3104  /* Return a one-deep namespace stack */
3105  return list_make1(dpns);
3106 }
#define NIL
Definition: pg_list.h:69
List * rtable_names
Definition: ruleutils.c:150
#define list_make1(x1)
Definition: pg_list.h:139
void * palloc0(Size size)
Definition: mcxt.c:877
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3401
char* deparse_expression ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit 
)

Definition at line 2985 of file ruleutils.c.

References deparse_expression_pretty().

Referenced by AlterDomainDefault(), DefineDomain(), domainAddConstraint(), pg_get_function_arg_default(), print_function_arguments(), show_expression(), show_grouping_set_keys(), show_plan_tlist(), show_sort_group_keys(), show_tablesample(), StoreAttrDefault(), StoreRelCheck(), and transformPartitionBound().

2987 {
2988  return deparse_expression_pretty(expr, dpcontext, forceprefix,
2989  showimplicit, 0, 0);
2990 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3012
static char * deparse_expression_pretty ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit,
int  prettyFlags,
int  startIndent 
)
static

Definition at line 3012 of file ruleutils.c.

References buf, deparse_context::buf, StringInfoData::data, EXPR_KIND_NONE, get_rule_expr(), deparse_context::indentLevel, initStringInfo(), deparse_context::namespaces, NIL, deparse_context::prettyFlags, deparse_context::special_exprkind, deparse_context::varprefix, deparse_context::windowClause, deparse_context::windowTList, WRAP_COLUMN_DEFAULT, and deparse_context::wrapColumn.

Referenced by deparse_expression(), pg_get_constraintdef_worker(), pg_get_expr_worker(), pg_get_indexdef_worker(), pg_get_partition_constraintdef(), and pg_get_partkeydef_worker().

3015 {
3017  deparse_context context;
3018 
3019  initStringInfo(&buf);
3020  context.buf = &buf;
3021  context.namespaces = dpcontext;
3022  context.windowClause = NIL;
3023  context.windowTList = NIL;
3024  context.varprefix = forceprefix;
3025  context.prettyFlags = prettyFlags;
3026  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3027  context.indentLevel = startIndent;
3028  context.special_exprkind = EXPR_KIND_NONE;
3029 
3030  get_rule_expr(expr, &context, showimplicit);
3031 
3032  return buf.data;
3033 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:93
static char * buf
Definition: pg_test_fsync.c:67
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
List * windowTList
Definition: ruleutils.c:111
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
List * windowClause
Definition: ruleutils.c:110
StringInfo buf
Definition: ruleutils.c:108
static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

Definition at line 4201 of file ruleutils.c.

References deparse_columns::colnames, deparse_columns::num_cols, palloc0(), and repalloc().

Referenced by set_join_column_names(), set_relation_column_names(), and set_using_names().

4202 {
4203  if (n > colinfo->num_cols)
4204  {
4205  if (colinfo->colnames == NULL)
4206  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4207  else
4208  {
4209  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4210  n * sizeof(char *));
4211  memset(colinfo->colnames + colinfo->num_cols, 0,
4212  (n - colinfo->num_cols) * sizeof(char *));
4213  }
4214  colinfo->num_cols = n;
4215  }
4216 }
void * palloc0(Size size)
Definition: mcxt.c:877
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
char ** colnames
Definition: ruleutils.c:225
static Node * find_param_referent ( Param param,
deparse_context context,
deparse_namespace **  dpns_p,
ListCell **  ancestor_cell_p 
)
static

Definition at line 7069 of file ruleutils.c.

References deparse_namespace::ancestors, arg, SubPlan::args, Assert, forboth, PlanState::initPlan, innerPlanState, IsA, lfirst, lfirst_int, linitial, deparse_context::namespaces, NestLoop::nestParams, NIL, PARAM_EXEC, Param::paramid, Param::paramkind, NestLoopParam::paramno, NestLoopParam::paramval, SubPlan::parParam, PlanState::plan, deparse_namespace::planstate, SubPlanState::planstate, SubPlanState::subplan, and PlanState::subPlan.

Referenced by get_name_for_var_field(), and get_parameter().

7071 {
7072  /* Initialize output parameters to prevent compiler warnings */
7073  *dpns_p = NULL;
7074  *ancestor_cell_p = NULL;
7075 
7076  /*
7077  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7078  * SubPlan argument. This will necessarily be in some ancestor of the
7079  * current expression's PlanState.
7080  */
7081  if (param->paramkind == PARAM_EXEC)
7082  {
7083  deparse_namespace *dpns;
7084  PlanState *child_ps;
7085  bool in_same_plan_level;
7086  ListCell *lc;
7087 
7088  dpns = (deparse_namespace *) linitial(context->namespaces);
7089  child_ps = dpns->planstate;
7090  in_same_plan_level = true;
7091 
7092  foreach(lc, dpns->ancestors)
7093  {
7094  PlanState *ps = (PlanState *) lfirst(lc);
7095  ListCell *lc2;
7096 
7097  /*
7098  * NestLoops transmit params to their inner child only; also, once
7099  * we've crawled up out of a subplan, this couldn't possibly be
7100  * the right match.
7101  */
7102  if (IsA(ps, NestLoopState) &&
7103  child_ps == innerPlanState(ps) &&
7104  in_same_plan_level)
7105  {
7106  NestLoop *nl = (NestLoop *) ps->plan;
7107 
7108  foreach(lc2, nl->nestParams)
7109  {
7110  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7111 
7112  if (nlp->paramno == param->paramid)
7113  {
7114  /* Found a match, so return it */
7115  *dpns_p = dpns;
7116  *ancestor_cell_p = lc;
7117  return (Node *) nlp->paramval;
7118  }
7119  }
7120  }
7121 
7122  /*
7123  * Check to see if we're crawling up from a subplan.
7124  */
7125  foreach(lc2, ps->subPlan)
7126  {
7127  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7128  SubPlan *subplan = sstate->subplan;
7129  ListCell *lc3;
7130  ListCell *lc4;
7131 
7132  if (child_ps != sstate->planstate)
7133  continue;
7134 
7135  /* Matched subplan, so check its arguments */
7136  forboth(lc3, subplan->parParam, lc4, subplan->args)
7137  {
7138  int paramid = lfirst_int(lc3);
7139  Node *arg = (Node *) lfirst(lc4);
7140 
7141  if (paramid == param->paramid)
7142  {
7143  /* Found a match, so return it */
7144  *dpns_p = dpns;
7145  *ancestor_cell_p = lc;
7146  return arg;
7147  }
7148  }
7149 
7150  /* Keep looking, but we are emerging from a subplan. */
7151  in_same_plan_level = false;
7152  break;
7153  }
7154 
7155  /*
7156  * Likewise check to see if we're emerging from an initplan.
7157  * Initplans never have any parParams, so no need to search that
7158  * list, but we need to know if we should reset
7159  * in_same_plan_level.
7160  */
7161  foreach(lc2, ps->initPlan)
7162  {
7163  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7164 
7165  if (child_ps != sstate->planstate)
7166  continue;
7167 
7168  /* No parameters to be had here. */
7169  Assert(sstate->subplan->parParam == NIL);
7170 
7171  /* Keep looking, but we are emerging from an initplan. */
7172  in_same_plan_level = false;
7173  break;
7174  }
7175 
7176  /* No luck, crawl up to next ancestor */
7177  child_ps = ps;
7178  }
7179  }
7180 
7181  /* No referent found */
7182  return NULL;
7183 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
List * nestParams
Definition: plannodes.h:686
List * initPlan
Definition: execnodes.h:868
List * subPlan
Definition: execnodes.h:870
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:510
Var * paramval
Definition: plannodes.h:693
#define linitial(l)
Definition: pg_list.h:111
struct PlanState * planstate
Definition: execnodes.h:758
SubPlan * subplan
Definition: execnodes.h:757
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:847
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:245
List * parParam
Definition: primnodes.h:709
PlanState * planstate
Definition: ruleutils.c:157
void * arg
#define innerPlanState(node)
Definition: execnodes.h:892
List * args
Definition: primnodes.h:710
static void flatten_join_using_qual ( Node qual,
List **  leftvars,
List **  rightvars 
)
static

Definition at line 4352 of file ruleutils.c.

References AND_EXPR, OpExpr::args, BoolExpr::args, Assert, BoolExpr::boolop, elog, ERROR, IsA, lappend(), lfirst, linitial, list_length(), lsecond, nodeTag, and strip_implicit_coercions().

Referenced by identify_join_columns().

4353 {
4354  if (IsA(qual, BoolExpr))
4355  {
4356  /* Handle AND nodes by recursion */
4357  BoolExpr *b = (BoolExpr *) qual;
4358  ListCell *lc;
4359 
4360  Assert(b->boolop == AND_EXPR);
4361  foreach(lc, b->args)
4362  {
4364  leftvars, rightvars);
4365  }
4366  }
4367  else if (IsA(qual, OpExpr))
4368  {
4369  /* Otherwise we should have an equality operator */
4370  OpExpr *op = (OpExpr *) qual;
4371  Var *var;
4372 
4373  if (list_length(op->args) != 2)
4374  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4375  /* Arguments should be Vars with perhaps implicit coercions */
4376  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4377  if (!IsA(var, Var))
4378  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4379  (int) nodeTag(var));
4380  *leftvars = lappend(*leftvars, var);
4381  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4382  if (!IsA(var, Var))
4383  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4384  (int) nodeTag(var));
4385  *rightvars = lappend(*rightvars, var);
4386  }
4387  else
4388  {
4389  /* Perhaps we have an implicit coercion to boolean? */
4390  Node *q = strip_implicit_coercions(qual);
4391 
4392  if (q != qual)
4393  flatten_join_using_qual(q, leftvars, rightvars);
4394  else
4395  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4396  (int) nodeTag(qual));
4397  }
4398 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Definition: nodes.h:510
Definition: primnodes.h:163
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:562
List * lappend(List *list, void *datum)
Definition: list.c:128
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:4352
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * args
Definition: primnodes.h:563
#define nodeTag(nodeptr)
Definition: nodes.h:515
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612
static char * flatten_reloptions ( Oid  relid)
static

Definition at line 10843 of file ruleutils.c.

References Anum_pg_class_reloptions, appendStringInfo(), appendStringInfoString(), buf, StringInfoData::data, DatumGetArrayTypeP, deconstruct_array(), elog, ERROR, HeapTupleIsValid, i, initStringInfo(), name, noptions, ObjectIdGetDatum, options, pfree(), quote_identifier(), ReleaseSysCache(), RELOID, SearchSysCache1(), simple_quote_literal(), SysCacheGetAttr(), TextDatumGetCString, TEXTOID, and value.

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

10844 {
10845  char *result = NULL;
10846  HeapTuple tuple;
10847  Datum reloptions;
10848  bool isnull;
10849 
10850  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10851  if (!HeapTupleIsValid(tuple))
10852  elog(ERROR, "cache lookup failed for relation %u", relid);
10853 
10854  reloptions = SysCacheGetAttr(RELOID, tuple,
10855  Anum_pg_class_reloptions, &isnull);
10856  if (!isnull)
10857  {
10859  Datum *options;
10860  int noptions;
10861  int i;
10862 
10863  initStringInfo(&buf);
10864 
10866  TEXTOID, -1, false, 'i',
10867  &options, NULL, &noptions);
10868 
10869  for (i = 0; i < noptions; i++)
10870  {
10871  char *option = TextDatumGetCString(options[i]);
10872  char *name;
10873  char *separator;
10874  char *value;
10875 
10876  /*
10877  * Each array element should have the form name=value. If the "="
10878  * is missing for some reason, treat it like an empty value.
10879  */
10880  name = option;
10881  separator = strchr(option, '=');
10882  if (separator)
10883  {
10884  *separator = '\0';
10885  value = separator + 1;
10886  }
10887  else
10888  value = "";
10889 
10890  if (i > 0)
10891  appendStringInfoString(&buf, ", ");
10892  appendStringInfo(&buf, "%s=", quote_identifier(name));
10893 
10894  /*
10895  * In general we need to quote the value; but to avoid unnecessary
10896  * clutter, do not quote if it is an identifier that would not
10897  * need quoting. (We could also allow numbers, but that is a bit
10898  * trickier than it looks --- for example, are leading zeroes
10899  * significant? We don't want to assume very much here about what
10900  * custom reloptions might mean.)
10901  */
10902  if (quote_identifier(value) == value)
10903  appendStringInfoString(&buf, value);
10904  else
10905  simple_quote_literal(&buf, value);
10906 
10907  pfree(option);
10908  }
10909 
10910  result = buf.data;
10911  }
10912 
10913  ReleaseSysCache(tuple);
10914 
10915  return result;
10916 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
#define TEXTOID
Definition: pg_type.h:324
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
void pfree(void *pointer)
Definition: mcxt.c:949
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9412
static struct @121 value
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
const char * name
Definition: encode.c:521
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
int i
#define elog
Definition: elog.h:219
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:246
char* generate_collation_name ( Oid  collid)

Definition at line 10798 of file ruleutils.c.

References CollationIsVisible(), COLLOID, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, quote_qualified_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by get_const_collation(), get_from_clause_coldeflist(), get_rule_expr(), pg_collation_for(), pg_get_indexdef_worker(), and pg_get_partkeydef_worker().

10799 {
10800  HeapTuple tp;
10801  Form_pg_collation colltup;
10802  char *collname;
10803  char *nspname;
10804  char *result;
10805 
10806  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
10807  if (!HeapTupleIsValid(tp))
10808  elog(ERROR, "cache lookup failed for collation %u", collid);
10809  colltup = (Form_pg_collation) GETSTRUCT(tp);
10810  collname = NameStr(colltup->collname);
10811 
10812  if (!CollationIsVisible(collid))
10813  nspname = get_namespace_name(colltup->collnamespace);
10814  else
10815  nspname = NULL;
10816 
10817  result = quote_qualified_identifier(nspname, collname);
10818 
10819  ReleaseSysCache(tp);
10820 
10821  return result;
10822 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2008
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10476
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:52
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
static char * generate_function_name ( Oid  funcid,
int  nargs,
List argnames,
Oid argtypes,
bool  has_variadic,
bool use_variadic_p,
ParseExprKind  special_exprkind 
)
static

Definition at line 10618 of file ruleutils.c.

References Assert, elog, ERROR, EXPR_KIND_GROUP_BY, func_get_detail(), FUNCDETAIL_AGGREGATE, FUNCDETAIL_NORMAL, FUNCDETAIL_NOTFOUND, FUNCDETAIL_WINDOWFUNC, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, InvalidOid, list_make1, makeString(), NameStr, NIL, ObjectIdGetDatum, OidIsValid, PROCOID, quote_qualified_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by get_agg_expr(), get_func_expr(), get_tablesample_def(), get_windowfunc_expr(), and pg_get_triggerdef_worker().

10621 {
10622  char *result;
10623  HeapTuple proctup;
10624  Form_pg_proc procform;
10625  char *proname;
10626  bool use_variadic;
10627  char *nspname;
10628  FuncDetailCode p_result;
10629  Oid p_funcid;
10630  Oid p_rettype;
10631  bool p_retset;
10632  int p_nvargs;
10633  Oid p_vatype;
10634  Oid *p_true_typeids;
10635  bool force_qualify = false;
10636 
10637  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10638  if (!HeapTupleIsValid(proctup))
10639  elog(ERROR, "cache lookup failed for function %u", funcid);
10640  procform = (Form_pg_proc) GETSTRUCT(proctup);
10641  proname = NameStr(procform->proname);
10642 
10643  /*
10644  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10645  * qualification in some special cases.
10646  */
10647  if (special_exprkind == EXPR_KIND_GROUP_BY)
10648  {
10649  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10650  force_qualify = true;
10651  }
10652 
10653  /*
10654  * Determine whether VARIADIC should be printed. We must do this first
10655  * since it affects the lookup rules in func_get_detail().
10656  *
10657  * Currently, we always print VARIADIC if the function has a merged
10658  * variadic-array argument. Note that this is always the case for
10659  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10660  *
10661  * In principle, if VARIADIC wasn't originally specified and the array
10662  * actual argument is deconstructable, we could print the array elements
10663  * separately and not print VARIADIC, thus more nearly reproducing the
10664  * original input. For the moment that seems like too much complication
10665  * for the benefit, and anyway we do not know whether VARIADIC was
10666  * originally specified if it's a non-ANY type.
10667  */
10668  if (use_variadic_p)
10669  {
10670  /* Parser should not have set funcvariadic unless fn is variadic */
10671  Assert(!has_variadic || OidIsValid(procform->provariadic));
10672  use_variadic = has_variadic;
10673  *use_variadic_p = use_variadic;
10674  }
10675  else
10676  {
10677  Assert(!has_variadic);
10678  use_variadic = false;
10679  }
10680 
10681  /*
10682  * The idea here is to schema-qualify only if the parser would fail to
10683  * resolve the correct function given the unqualified func name with the
10684  * specified argtypes and VARIADIC flag. But if we already decided to
10685  * force qualification, then we can skip the lookup and pretend we didn't
10686  * find it.
10687  */
10688  if (!force_qualify)
10689  p_result = func_get_detail(list_make1(makeString(proname)),
10690  NIL, argnames, nargs, argtypes,
10691  !use_variadic, true,
10692  &p_funcid, &p_rettype,
10693  &p_retset, &p_nvargs, &p_vatype,
10694  &p_true_typeids, NULL);
10695  else
10696  {
10697  p_result = FUNCDETAIL_NOTFOUND;
10698  p_funcid = InvalidOid;
10699  }
10700 
10701  if ((p_result == FUNCDETAIL_NORMAL ||
10702  p_result == FUNCDETAIL_AGGREGATE ||
10703  p_result == FUNCDETAIL_WINDOWFUNC) &&
10704  p_funcid == funcid)
10705  nspname = NULL;
10706  else
10707  nspname = get_namespace_name(procform->pronamespace);
10708 
10709  result = quote_qualified_identifier(nspname, proname);
10710 
10711  ReleaseSysCache(proctup);
10712 
10713  return result;
10714 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
#define list_make1(x1)
Definition: pg_list.h:139
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10476
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1283
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
static char * generate_operator_name ( Oid  operid,
Oid  arg1,
Oid  arg2 
)
static

Definition at line 10728 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, StringInfoData::data, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, initStringInfo(), left_oper(), list_make1, makeString(), NameStr, ObjectIdGetDatum, oper(), OPEROID, oprid(), quote_identifier(), ReleaseSysCache(), right_oper(), and SearchSysCache1().

Referenced by get_oper_expr(), get_rule_expr(), get_rule_orderby(), get_simple_binary_op_name(), get_sublink_expr(), and pg_get_indexdef_worker().

10729 {
10731  HeapTuple opertup;
10732  Form_pg_operator operform;
10733  char *oprname;
10734  char *nspname;
10735  Operator p_result;
10736 
10737  initStringInfo(&buf);
10738 
10739  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10740  if (!HeapTupleIsValid(opertup))
10741  elog(ERROR, "cache lookup failed for operator %u", operid);
10742  operform = (Form_pg_operator) GETSTRUCT(opertup);
10743  oprname = NameStr(operform->oprname);
10744 
10745  /*
10746  * The idea here is to schema-qualify only if the parser would fail to
10747  * resolve the correct operator given the unqualified op name with the
10748  * specified argtypes.
10749  */
10750  switch (operform->oprkind)
10751  {
10752  case 'b':
10753  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10754  true, -1);
10755  break;
10756  case 'l':
10757  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10758  true, -1);
10759  break;
10760  case 'r':
10761  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10762  true, -1);
10763  break;
10764  default:
10765  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10766  p_result = NULL; /* keep compiler quiet */
10767  break;
10768  }
10769 
10770  if (p_result != NULL && oprid(p_result) == operid)
10771  nspname = NULL;
10772  else
10773  {
10774  nspname = get_namespace_name(operform->oprnamespace);
10775  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10776  }
10777 
10778  appendStringInfoString(&buf, oprname);
10779 
10780  if (nspname)
10781  appendStringInfoChar(&buf, ')');
10782 
10783  if (p_result != NULL)
10784  ReleaseSysCache(p_result);
10785 
10786  ReleaseSysCache(opertup);
10787 
10788  return buf.data;
10789 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define list_make1(x1)
Definition: pg_list.h:139
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:604
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:525
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377
static char * generate_qualified_relation_name ( Oid  relid)
static

Definition at line 10576 of file ruleutils.c.

References elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, quote_qualified_identifier(), ReleaseSysCache(), RELOID, and SearchSysCache1().

Referenced by pg_get_constraintdef_worker(), and pg_get_serial_sequence().

10577 {
10578  HeapTuple tp;
10579  Form_pg_class reltup;
10580  char *relname;
10581  char *nspname;
10582  char *result;
10583 
10584  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10585  if (!HeapTupleIsValid(tp))
10586  elog(ERROR, "cache lookup failed for relation %u", relid);
10587  reltup = (Form_pg_class) GETSTRUCT(tp);
10588  relname = NameStr(reltup->relname);
10589 
10590  nspname = get_namespace_name(reltup->relnamespace);
10591  if (!nspname)
10592  elog(ERROR, "cache lookup failed for namespace %u",
10593  reltup->relnamespace);
10594 
10595  result = quote_qualified_identifier(nspname, relname);
10596 
10597  ReleaseSysCache(tp);
10598 
10599  return result;
10600 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10476
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
static char * generate_relation_name ( Oid  relid,
List namespaces 
)
static

Definition at line 10516 of file ruleutils.c.

References CommonTableExpr::ctename, deparse_namespace::ctes, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, lfirst, NameStr, ObjectIdGetDatum, quote_qualified_identifier(), RelationIsVisible(), ReleaseSysCache(), RELOID, and SearchSysCache1().

Referenced by get_delete_query_def(), get_from_clause_item(), get_insert_query_def(), get_rule_expr(), get_update_query_def(), make_ruledef(), pg_get_constraintdef_worker(), pg_get_indexdef_worker(), pg_get_statisticsobj_worker(), and pg_get_triggerdef_worker().

10517 {
10518  HeapTuple tp;
10519  Form_pg_class reltup;
10520  bool need_qual;
10521  ListCell *nslist;
10522  char *relname;
10523  char *nspname;
10524  char *result;
10525 
10526  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10527  if (!HeapTupleIsValid(tp))
10528  elog(ERROR, "cache lookup failed for relation %u", relid);
10529  reltup = (Form_pg_class) GETSTRUCT(tp);
10530  relname = NameStr(reltup->relname);
10531 
10532  /* Check for conflicting CTE name */
10533  need_qual = false;
10534  foreach(nslist, namespaces)
10535  {
10536  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10537  ListCell *ctlist;
10538 
10539  foreach(ctlist, dpns->ctes)
10540  {
10541  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10542 
10543  if (strcmp(cte->ctename, relname) == 0)
10544  {
10545  need_qual = true;
10546  break;
10547  }
10548  }
10549  if (need_qual)
10550  break;
10551  }
10552 
10553  /* Otherwise, qualify the name if not visible in search path */
10554  if (!need_qual)
10555  need_qual = !RelationIsVisible(relid);
10556 
10557  if (need_qual)
10558  nspname = get_namespace_name(reltup->relnamespace);
10559  else
10560  nspname = NULL;
10561 
10562  result = quote_qualified_identifier(nspname, relname);
10563 
10564  ReleaseSysCache(tp);
10565 
10566  return result;
10567 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10476
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
bool RelationIsVisible(Oid relid)
Definition: namespace.c:682
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
static void get_agg_combine_expr ( Node node,
deparse_context context,
void *  private 
)
static

Definition at line 9108 of file ruleutils.c.

References elog, ERROR, get_agg_expr(), and IsA.

Referenced by get_agg_expr().

9109 {
9110  Aggref *aggref;
9111  Aggref *original_aggref = private;
9112 
9113  if (!IsA(node, Aggref))
9114  elog(ERROR, "combining Aggref does not point to an Aggref");
9115 
9116  aggref = (Aggref *) node;
9117  get_agg_expr(aggref, context, original_aggref);
9118 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9002
#define elog
Definition: elog.h:219
static void get_agg_expr ( Aggref aggref,
deparse_context context,
Aggref original_aggref 
)
static

Definition at line 9002 of file ruleutils.c.

References Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggkind, AGGKIND_IS_ORDERED_SET, Aggref::aggorder, Aggref::aggsplit, Aggref::aggstar, Aggref::aggvariadic, appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, Aggref::args, Assert, buf, deparse_context::buf, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_SKIPFINAL, TargetEntry::expr, FUNC_MAX_ARGS, generate_function_name(), get_agg_combine_expr(), get_aggregate_argtypes(), get_rule_expr(), get_rule_orderby(), i, IsA, lfirst, linitial_node, list_length(), NIL, TargetEntry::resjunk, resolve_special_varno(), and deparse_context::special_exprkind.

Referenced by get_agg_combine_expr(), and get_rule_expr().

9004 {
9005  StringInfo buf = context->buf;
9006  Oid argtypes[FUNC_MAX_ARGS];
9007  int nargs;
9008  bool use_variadic;
9009 
9010  /*
9011  * For a combining aggregate, we look up and deparse the corresponding
9012  * partial aggregate instead. This is necessary because our input
9013  * argument list has been replaced; the new argument list always has just
9014  * one element, which will point to a partial Aggref that supplies us with
9015  * transition states to combine.
9016  */
9017  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9018  {
9019  TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
9020 
9021  Assert(list_length(aggref->args) == 1);
9022  resolve_special_varno((Node *) tle->expr, context, original_aggref,
9024  return;
9025  }
9026 
9027  /*
9028  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9029  * to avoid printing this when recursing from the code just above.
9030  */
9031  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9032  appendStringInfoString(buf, "PARTIAL ");
9033 
9034  /* Extract the argument types as seen by the parser */
9035  nargs = get_aggregate_argtypes(aggref, argtypes);
9036 
9037  /* Print the aggregate name, schema-qualified if needed */
9038  appendStringInfo(buf, "%s(%s",
9039  generate_function_name(aggref->aggfnoid, nargs,
9040  NIL, argtypes,
9041  aggref->aggvariadic,
9042  &use_variadic,
9043  context->special_exprkind),
9044  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9045 
9046  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9047  {
9048  /*
9049  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9050  * worry about inserting VARIADIC. So we can just dump the direct
9051  * args as-is.
9052  */
9053  Assert(!aggref->aggvariadic);
9054  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9055  Assert(aggref->aggorder != NIL);
9056  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9057  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9058  }
9059  else
9060  {
9061  /* aggstar can be set only in zero-argument aggregates */
9062  if (aggref->aggstar)
9063  appendStringInfoChar(buf, '*');
9064  else
9065  {
9066  ListCell *l;
9067  int i;
9068 
9069  i = 0;
9070  foreach(l, aggref->args)
9071  {
9072  TargetEntry *tle = (TargetEntry *) lfirst(l);
9073  Node *arg = (Node *) tle->expr;
9074 
9075  Assert(!IsA(arg, NamedArgExpr));
9076  if (tle->resjunk)
9077  continue;
9078  if (i++ > 0)
9079  appendStringInfoString(buf, ", ");
9080  if (use_variadic && i == nargs)
9081  appendStringInfoString(buf, "VARIADIC ");
9082  get_rule_expr(arg, context, true);
9083  }
9084  }
9085 
9086  if (aggref->aggorder != NIL)
9087  {
9088  appendStringInfoString(buf, " ORDER BY ");
9089  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9090  }
9091  }
9092 
9093  if (aggref->aggfilter != NULL)
9094  {
9095  appendStringInfoString(buf, ") FILTER (WHERE ");
9096  get_rule_expr((Node *) aggref->aggfilter, context, false);
9097  }
9098 
9099  appendStringInfoChar(buf, ')');
9100 }
List * aggdistinct
Definition: primnodes.h:303
#define NIL
Definition: pg_list.h:69
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10618
bool aggvariadic
Definition: primnodes.h:306
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6602
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5714
Definition: nodes.h:510
List * args
Definition: primnodes.h:301
bool aggstar
Definition: primnodes.h:305
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:114
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:769
#define FUNC_MAX_ARGS
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:133
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1375
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * aggorder
Definition: primnodes.h:302
List * aggdirectargs
Definition: primnodes.h:300
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
Oid aggfnoid
Definition: primnodes.h:294
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:9108
#define Assert(condition)
Definition: c.h:681
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1368
AggSplit aggsplit
Definition: primnodes.h:310
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:770
Expr * aggfilter
Definition: primnodes.h:304
StringInfo buf
Definition: ruleutils.c:108
int i
void * arg
char aggkind
Definition: primnodes.h:308
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1801
static void get_basic_select_query ( Query query,
deparse_context context,
TupleDesc  resultDesc 
)
static

Definition at line 5207 of file ruleutils.c.

References appendContextKeyword(), appendStringInfoChar(), appendStringInfoString(), buf, deparse_context::buf, Query::distinctClause, EXPR_KIND_GROUP_BY, get_from_clause(), get_rule_expr(), get_rule_groupingset(), get_rule_sortgroupclause(), get_rule_windowclause(), get_simple_values_rte(), get_target_list(), get_values_def(), Query::groupClause, Query::groupingSets, Query::hasDistinctOn, Query::havingQual, deparse_context::indentLevel, Query::jointree, lfirst, NIL, PRETTY_INDENT, PRETTYINDENT_STD, FromExpr::quals, deparse_context::special_exprkind, Query::targetList, SortGroupClause::tleSortGroupRef, RangeTblEntry::values_lists, and Query::windowClause.

Referenced by get_select_query_def().

5209 {
5210  StringInfo buf = context->buf;
5211  RangeTblEntry *values_rte;
5212  char *sep;
5213  ListCell *l;
5214 
5215  if (PRETTY_INDENT(context))
5216  {
5217  context->indentLevel += PRETTYINDENT_STD;
5218  appendStringInfoChar(buf, ' ');
5219  }
5220 
5221  /*
5222  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5223  * VALUES part. This reverses what transformValuesClause() did at parse
5224  * time.
5225  */
5226  values_rte = get_simple_values_rte(query);
5227  if (values_rte)
5228  {
5229  get_values_def(values_rte->values_lists, context);
5230  return;
5231  }
5232 
5233  /*
5234  * Build up the query string - first we say SELECT
5235  */
5236  appendStringInfoString(buf, "SELECT");
5237 
5238  /* Add the DISTINCT clause if given */
5239  if (query->distinctClause != NIL)
5240  {
5241  if (query->hasDistinctOn)
5242  {
5243  appendStringInfoString(buf, " DISTINCT ON (");
5244  sep = "";
5245  foreach(l, query->distinctClause)
5246  {
5247  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5248 
5249  appendStringInfoString(buf, sep);
5251  false, context);
5252  sep = ", ";
5253  }
5254  appendStringInfoChar(buf, ')');
5255  }
5256  else
5257  appendStringInfoString(buf, " DISTINCT");
5258  }
5259 
5260  /* Then we tell what to select (the targetlist) */
5261  get_target_list(query->targetList, context, resultDesc);
5262 
5263  /* Add the FROM clause if needed */
5264  get_from_clause(query, " FROM ", context);
5265 
5266  /* Add the WHERE clause if given */
5267  if (query->jointree->quals != NULL)
5268  {
5269  appendContextKeyword(context, " WHERE ",
5271  get_rule_expr(query->jointree->quals, context, false);
5272  }
5273 
5274  /* Add the GROUP BY clause if given */
5275  if (query->groupClause != NULL || query->groupingSets != NULL)
5276  {
5277  ParseExprKind save_exprkind;
5278 
5279  appendContextKeyword(context, " GROUP BY ",
5281 
5282  save_exprkind = context->special_exprkind;
5284 
5285  if (query->groupingSets == NIL)
5286  {
5287  sep = "";
5288  foreach(l, query->groupClause)
5289  {
5290  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5291 
5292  appendStringInfoString(buf, sep);
5294  false, context);
5295  sep = ", ";
5296  }
5297  }
5298  else
5299  {
5300  sep = "";
5301  foreach(l, query->groupingSets)
5302  {
5303  GroupingSet *grp = lfirst(l);
5304 
5305  appendStringInfoString(buf, sep);
5306  get_rule_groupingset(grp, query->targetList, true, context);
5307  sep = ", ";
5308  }
5309  }
5310 
5311  context->special_exprkind = save_exprkind;
5312  }
5313 
5314  /* Add the HAVING clause if given */
5315  if (query->havingQual != NULL)
5316  {
5317  appendContextKeyword(context, " HAVING ",
5319  get_rule_expr(query->havingQual, context, false);
5320  }
5321 
5322  /* Add the WINDOW clause if needed */
5323  if (query->windowClause != NIL)
5324  get_rule_windowclause(query, context);
5325 }
#define NIL
Definition: pg_list.h:69
FromExpr * jointree
Definition: parsenodes.h:136
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5334
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5598
Index tleSortGroupRef
Definition: parsenodes.h:1190
List * groupingSets
Definition: parsenodes.h:148
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9682
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5772
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:1010
Node * quals
Definition: primnodes.h:1472
bool hasDistinctOn
Definition: parsenodes.h:127
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
List * distinctClause
Definition: parsenodes.h:154
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7495
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5654
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4923
List * groupClause
Definition: parsenodes.h:146
StringInfo buf
Definition: ruleutils.c:108
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:5151
Node * havingQual
Definition: parsenodes.h:150
static void get_coercion_expr ( Node arg,
deparse_context context,
Oid  resulttype,
int32  resulttypmod,
Node parentNode 
)
static

Definition at line 9201 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), buf, deparse_context::buf, format_type_with_typemod(), get_const_expr(), get_rule_expr_paren(), IsA, and PRETTY_PAREN.

Referenced by get_func_expr(), and get_rule_expr().

9204 {
9205  StringInfo buf = context->buf;
9206 
9207  /*
9208  * Since parse_coerce.c doesn't immediately collapse application of
9209  * length-coercion functions to constants, what we'll typically see in
9210  * such cases is a Const with typmod -1 and a length-coercion function
9211  * right above it. Avoid generating redundant output. However, beware of
9212  * suppressing casts when the user actually wrote something like
9213  * 'foo'::text::char(3).
9214  *
9215  * Note: it might seem that we are missing the possibility of needing to
9216  * print a COLLATE clause for such a Const. However, a Const could only
9217  * have nondefault collation in a post-constant-folding tree, in which the
9218  * length coercion would have been folded too. See also the special
9219  * handling of CollateExpr in coerce_to_target_type(): any collation
9220  * marking will be above the coercion node, not below it.
9221  */
9222  if (arg && IsA(arg, Const) &&
9223  ((Const *) arg)->consttype == resulttype &&
9224  ((Const *) arg)->consttypmod == -1)
9225  {
9226  /* Show the constant without normal ::typename decoration */
9227  get_const_expr((Const *) arg, context, -1);
9228  }
9229  else
9230  {
9231  if (!PRETTY_PAREN(context))
9232  appendStringInfoChar(buf, '(');
9233  get_rule_expr_paren(arg, context, false, parentNode);
9234  if (!PRETTY_PAREN(context))
9235  appendStringInfoChar(buf, ')');
9236  }
9237  appendStringInfo(buf, "::%s",
9238  format_type_with_typemod(resulttype, resulttypmod));
9239 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7568
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9257
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
StringInfo buf
Definition: ruleutils.c:108
static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

Definition at line 10103 of file ruleutils.c.

References appendStringInfoChar(), appendStringInfoString(), buf, deparse_context::buf, i, deparse_columns::new_colnames, deparse_columns::num_new_cols, deparse_columns::printaliases, and quote_identifier().

Referenced by get_from_clause_item().

10104 {
10105  StringInfo buf = context->buf;
10106  int i;
10107  bool first = true;
10108 
10109  /* Don't print aliases if not needed */
10110  if (!colinfo->printaliases)
10111  return;
10112 
10113  for (i = 0; i < colinfo->num_new_cols; i++)
10114  {
10115  char *colname = colinfo->new_colnames[i];
10116 
10117  if (first)
10118  {
10119  appendStringInfoChar(buf, '(');
10120  first = false;
10121  }
10122  else
10123  appendStringInfoString(buf, ", ");
10125  }
10126  if (!first)
10127  appendStringInfoChar(buf, ')');
10128 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: ruleutils.c:108
int i
char ** new_colnames
Definition: ruleutils.c:242
static void get_const_collation ( Const constval,
deparse_context context 
)
static

Definition at line 9392 of file ruleutils.c.

References appendStringInfo(), buf, deparse_context::buf, Const::constcollid, Const::consttype, generate_collation_name(), get_typcollation(), and OidIsValid.

Referenced by get_const_expr().

9393 {
9394  StringInfo buf = context->buf;
9395 
9396  if (OidIsValid(constval->constcollid))
9397  {
9398  Oid typcollation = get_typcollation(constval->consttype);
9399 
9400  if (constval->constcollid != typcollation)
9401  {
9402  appendStringInfo(buf, " COLLATE %s",
9404  }
9405  }
9406 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10798
Oid consttype
Definition: primnodes.h:192
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
Oid constcollid
Definition: primnodes.h:194
static char * buf
Definition: pg_test_fsync.c:67
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2781
StringInfo buf
Definition: ruleutils.c:108
static void get_const_expr ( Const constval,
deparse_context context,
int  showtype 
)
static

Definition at line 9257 of file ruleutils.c.

References appendStringInfo(), appendStringInfoString(), BITOID, BOOLOID, buf, deparse_context::buf, Const::constisnull, Const::consttype, Const::consttypmod, Const::constvalue, format_type_with_typemod(), get_const_collation(), getTypeOutputInfo(), INT4OID, NUMERICOID, OidOutputFunctionCall(), pfree(), simple_quote_literal(), UNKNOWNOID, and VARBITOID.

Referenced by get_coercion_expr(), get_range_partbound_string(), get_rule_expr(), and get_rule_sortgroupclause().

9258 {
9259  StringInfo buf = context->buf;
9260  Oid typoutput;
9261  bool typIsVarlena;
9262  char *extval;
9263  bool needlabel = false;
9264 
9265  if (constval->constisnull)
9266  {
9267  /*
9268  * Always label the type of a NULL constant to prevent misdecisions
9269  * about type when reparsing.
9270  */
9271  appendStringInfoString(buf, "NULL");
9272  if (showtype >= 0)
9273  {
9274  appendStringInfo(buf, "::%s",
9276  constval->consttypmod));
9277  get_const_collation(constval, context);
9278  }
9279  return;
9280  }
9281 
9282  getTypeOutputInfo(constval->consttype,
9283  &typoutput, &typIsVarlena);
9284 
9285  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9286 
9287  switch (constval->consttype)
9288  {
9289  case INT4OID:
9290 
9291  /*
9292  * INT4 can be printed without any decoration, unless it is
9293  * negative; in that case print it as '-nnn'::integer to ensure
9294  * that the output will re-parse as a constant, not as a constant
9295  * plus operator. In most cases we could get away with printing
9296  * (-nnn) instead, because of the way that gram.y handles negative
9297  * literals; but that doesn't work for INT_MIN, and it doesn't
9298  * seem that much prettier anyway.
9299  */
9300  if (extval[0] != '-')
9301  appendStringInfoString(buf, extval);
9302  else
9303  {
9304  appendStringInfo(buf, "'%s'", extval);
9305  needlabel = true; /* we must attach a cast */
9306  }
9307  break;
9308 
9309  case NUMERICOID:
9310 
9311  /*
9312  * NUMERIC can be printed without quotes if it looks like a float
9313  * constant (not an integer, and not Infinity or NaN) and doesn't
9314  * have a leading sign (for the same reason as for INT4).
9315  */
9316  if (isdigit((unsigned char) extval[0]) &&
9317  strcspn(extval, "eE.") != strlen(extval))
9318  {
9319  appendStringInfoString(buf, extval);
9320  }
9321  else
9322  {
9323  appendStringInfo(buf, "'%s'", extval);
9324  needlabel = true; /* we must attach a cast */
9325  }
9326  break;
9327 
9328  case BITOID:
9329  case VARBITOID:
9330  appendStringInfo(buf, "B'%s'", extval);
9331  break;
9332 
9333  case BOOLOID:
9334  if (strcmp(extval, "t") == 0)
9335  appendStringInfoString(buf, "true");
9336  else
9337  appendStringInfoString(buf, "false");
9338  break;
9339 
9340  default:
9341  simple_quote_literal(buf, extval);
9342  break;
9343  }
9344 
9345  pfree(extval);
9346 
9347  if (showtype < 0)
9348  return;
9349 
9350  /*
9351  * For showtype == 0, append ::typename unless the constant will be
9352  * implicitly typed as the right type when it is read in.
9353  *
9354  * XXX this code has to be kept in sync with the behavior of the parser,
9355  * especially make_const.
9356  */
9357  switch (constval->consttype)
9358  {
9359  case BOOLOID:
9360  case UNKNOWNOID:
9361  /* These types can be left unlabeled */
9362  needlabel = false;
9363  break;
9364  case INT4OID:
9365  /* We determined above whether a label is needed */
9366  break;
9367  case NUMERICOID:
9368 
9369  /*
9370  * Float-looking constants will be typed as numeric, which we
9371  * checked above; but if there's a nondefault typmod we need to
9372  * show it.
9373  */
9374  needlabel |= (constval->consttypmod >= 0);
9375  break;
9376  default:
9377  needlabel = true;
9378  break;
9379  }
9380  if (needlabel || showtype > 0)
9381  appendStringInfo(buf, "::%s",
9383  constval->consttypmod));
9384 
9385  get_const_collation(constval, context);
9386 }
Datum constvalue
Definition: primnodes.h:196
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2632
#define NUMERICOID
Definition: pg_type.h:554
#define INT4OID
Definition: pg_type.h:316
#define VARBITOID
Definition: pg_type.h:546
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:192
void pfree(void *pointer)
Definition: mcxt.c:949
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9412
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9392
static char * buf
Definition: pg_test_fsync.c:67
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
#define BITOID
Definition: pg_type.h:542
#define BOOLOID
Definition: pg_type.h:288
#define UNKNOWNOID
Definition: pg_type.h:431
int32 consttypmod
Definition: primnodes.h:193
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
StringInfo buf
Definition: ruleutils.c:108
bool constisnull
Definition: primnodes.h:197
static void get_delete_query_def ( Query query,
deparse_context context 
)
static

Definition at line 6323 of file ruleutils.c.

References RangeTblEntry::alias, Alias::aliasname, appendContextKeyword(), appendStringInfo(), appendStringInfoChar(), Assert, buf, deparse_context::buf, generate_relation_name(), get_from_clause(), get_rule_expr(), get_target_list(), get_with_clause(), deparse_context::indentLevel, Query::jointree, NIL, only_marker, PRETTY_INDENT, PRETTYINDENT_STD, FromExpr::quals, quote_identifier(), RangeTblEntry::relid, Query::resultRelation, Query::returningList, rt_fetch, Query::rtable, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by get_query_def().

6324 {
6325  StringInfo buf = context->buf;
6326  RangeTblEntry *rte;
6327 
6328  /* Insert the WITH clause if given */
6329  get_with_clause(query, context);
6330 
6331  /*
6332  * Start the query with DELETE FROM relname
6333  */
6334  rte = rt_fetch(query->resultRelation, query->rtable);
6335  Assert(rte->rtekind == RTE_RELATION);
6336  if (PRETTY_INDENT(context))
6337  {
6338  appendStringInfoChar(buf, ' ');
6339  context->indentLevel += PRETTYINDENT_STD;
6340  }
6341  appendStringInfo(buf, "DELETE FROM %s%s",
6342  only_marker(rte),
6344  if (rte->alias != NULL)
6345  appendStringInfo(buf, " %s",
6347 
6348  /* Add the USING clause if given */
6349  get_from_clause(query, " USING ", context);
6350 
6351  /* Add a WHERE clause if given */
6352  if (query->jointree->quals != NULL)
6353  {
6354  appendContextKeyword(context, " WHERE ",
6356  get_rule_expr(query->jointree->quals, context, false);
6357  }
6358 
6359  /* Add RETURNING if present */
6360  if (query->returningList)
6361  {
6362  appendContextKeyword(context, " RETURNING",
6364  get_target_list(query->returningList, context, NULL);
6365  }
6366 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4966
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
Alias * alias
Definition: parsenodes.h:1048
FromExpr * jointree
Definition: parsenodes.h:136
int resultRelation
Definition: parsenodes.h:120
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5334
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9682
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
Node * quals
Definition: primnodes.h:1472
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10516
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
List * rtable
Definition: parsenodes.h:135
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7495
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define Assert(condition)
Definition: c.h:681
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:466
RTEKind rtekind
Definition: parsenodes.h:945
StringInfo buf
Definition: ruleutils.c:108
static void get_from_clause ( Query query,
const char *  prefix,
deparse_context context 
)
static

Definition at line 9682 of file ruleutils.c.

References appendContextKeyword(), appendStringInfoString(), buf, deparse_context::buf, StringInfoData::data, FromExpr::fromlist, get_from_clause_item(), RangeTblEntry::inFromCl, initStringInfo(), IsA, Query::jointree, StringInfoData::len, lfirst, pfree(), PRETTY_INDENT, PRETTYINDENT_STD, PRETTYINDENT_VAR, removeStringInfoSpaces(), rt_fetch, Query::rtable, and deparse_context::wrapColumn.

Referenced by get_basic_select_query(), get_delete_query_def(), and get_update_query_def().

9683 {
9684  StringInfo buf = context->buf;
9685  bool first = true;
9686  ListCell *l;
9687 
9688  /*
9689  * We use the query's jointree as a guide to what to print. However, we
9690  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9691  * only appear at the top level of the jointree, so it's sufficient to
9692  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9693  * for NEW and OLD.
9694  */
9695  foreach(l, query->jointree->fromlist)
9696  {
9697  Node *jtnode = (Node *) lfirst(l);
9698 
9699  if (IsA(jtnode, RangeTblRef))
9700  {
9701  int varno = ((RangeTblRef *) jtnode)->rtindex;
9702  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9703 
9704  if (!rte->inFromCl)
9705  continue;
9706  }
9707 
9708  if (first)
9709  {
9710  appendContextKeyword(context, prefix,
9712  first = false;
9713 
9714  get_from_clause_item(jtnode, query, context);
9715  }
9716  else
9717  {
9718  StringInfoData itembuf;
9719 
9720  appendStringInfoString(buf, ", ");
9721 
9722  /*
9723  * Put the new FROM item's text into itembuf so we can decide
9724  * after we've got it whether or not it needs to go on a new line.
9725  */
9726  initStringInfo(&itembuf);
9727  context->buf = &itembuf;
9728 
9729  get_from_clause_item(jtnode, query, context);
9730 
9731  /* Restore context's output buffer */
9732  context->buf = buf;
9733 
9734  /* Consider line-wrapping if enabled */
9735  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9736  {
9737  /* Does the new item start with a new line? */
9738  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9739  {
9740  /* If so, we shouldn't add anything */
9741  /* instead, remove any trailing spaces currently in buf */
9743  }
9744  else
9745  {
9746  char *trailing_nl;
9747 
9748  /* Locate the start of the current line in the buffer */
9749  trailing_nl = strrchr(buf->data, '\n');
9750  if (trailing_nl == NULL)
9751  trailing_nl = buf->data;
9752  else
9753  trailing_nl++;
9754 
9755  /*
9756  * Add a newline, plus some indentation, if the new item
9757  * would cause an overflow.
9758  */
9759  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9760  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9763  }
9764  }
9765 
9766  /* Add the new item */
9767  appendStringInfoString(buf, itembuf.data);
9768 
9769  /* clean up */
9770  pfree(itembuf.data);
9771  }
9772  }
9773 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
FromExpr * jointree
Definition: parsenodes.h:136
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
Definition: nodes.h:510
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
List * fromlist
Definition: primnodes.h:1471
void pfree(void *pointer)
Definition: mcxt.c:949
List * rtable
Definition: parsenodes.h:135
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7495
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7549
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9776
static void get_from_clause_coldeflist ( RangeTblFunction rtfunc,
deparse_columns colinfo,
deparse_context context 
)
static

Definition at line 10143 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, buf, deparse_context::buf, deparse_columns::colnames, format_type_with_typemod(), forthree, RangeTblFunction::funccolcollations, RangeTblFunction::funccolnames, RangeTblFunction::funccoltypes, RangeTblFunction::funccoltypmods, generate_collation_name(), get_typcollation(), i, lfirst, lfirst_int, lfirst_oid, list_head(), lnext, OidIsValid, quote_identifier(), and strVal.

Referenced by get_from_clause_item().

10146 {
10147  StringInfo buf = context->buf;
10148  ListCell *l1;
10149  ListCell *l2;
10150  ListCell *l3;
10151  ListCell *l4;
10152  int i;
10153 
10154  appendStringInfoChar(buf, '(');
10155 
10156  /* there's no forfour(), so must chase one list the hard way */
10157  i = 0;
10158  l4 = list_head(rtfunc->funccolnames);
10159  forthree(l1, rtfunc->funccoltypes,
10160  l2, rtfunc->funccoltypmods,
10161  l3, rtfunc->funccolcollations)
10162  {
10163  Oid atttypid = lfirst_oid(l1);
10164  int32 atttypmod = lfirst_int(l2);
10165  Oid attcollation = lfirst_oid(l3);
10166  char *attname;
10167 
10168  if (colinfo)
10169  attname = colinfo->colnames[i];
10170  else
10171  attname = strVal(lfirst(l4));
10172 
10173  Assert(attname); /* shouldn't be any dropped columns here */
10174 
10175  if (i > 0)
10176  appendStringInfoString(buf, ", ");
10177  appendStringInfo(buf, "%s %s",
10178  quote_identifier(attname),
10179  format_type_with_typemod(atttypid, atttypmod));
10180  if (OidIsValid(attcollation) &&
10181  attcollation != get_typcollation(atttypid))
10182  appendStringInfo(buf, " COLLATE %s",
10183  generate_collation_name(attcollation));
10184 
10185  l4 = lnext(l4);
10186  i++;
10187  }
10188 
10189  appendStringInfoChar(buf, ')');
10190 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:203
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10798
signed int int32
Definition: c.h:246
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
List * funccoltypmods
Definition: parsenodes.h:1086
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2781
List * funccolcollations
Definition: parsenodes.h:1087
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
int i
#define lfirst_oid(lc)
Definition: pg_list.h:108
char ** colnames
Definition: ruleutils.c:225
static void get_from_clause_item ( Node jtnode,
Query query,
deparse_context context 
)
static

Definition at line 9776 of file ruleutils.c.

References RangeTblEntry::alias, JoinExpr::alias, Alias::aliasname, appendContextKeyword(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), generate_unaccent_rules::args, buf, deparse_context::buf, RangeTblEntry::ctename, deparse_columns_fetch, elog, ERROR, RangeTblFunction::funccolnames, RangeTblFunction::funcexpr, RangeTblEntry::funcordinality, RangeTblEntry::functions, generate_relation_name(), get_column_alias_list(), get_from_clause_coldeflist(), get_query_def(), get_relation_name(), get_rtable_name(), get_rule_expr(), get_rule_expr_funccall(), get_tablefunc(), get_tablesample_def(), get_values_def(), deparse_context::indentLevel, IsA, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JoinExpr::jointype, JoinExpr::larg, RangeTblEntry::lateral, lfirst, linitial, list_concat(), list_copy(), list_length(), deparse_context::namespaces, NIL, nodeTag, only_marker, PRETTY_PAREN, deparse_context::prettyFlags, PRETTYINDENT_JOIN, PRETTYINDENT_STD, deparse_columns::printaliases, JoinExpr::quals, quote_identifier(), JoinExpr::rarg, RangeTblEntry::relid, rt_fetch, Query::rtable, RTE_CTE, RTE_FUNCTION, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, JoinExpr::rtindex, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, JoinExpr::usingClause, deparse_columns::usingNames, RangeTblEntry::values_lists, and deparse_context::wrapColumn.

Referenced by get_from_clause().

9777 {
9778  StringInfo buf = context->buf;
9780 
9781  if (IsA(jtnode, RangeTblRef))
9782  {
9783  int varno = ((RangeTblRef *) jtnode)->rtindex;
9784  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9785  char *refname = get_rtable_name(varno, context);
9786  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9787  RangeTblFunction *rtfunc1 = NULL;
9788  bool printalias;
9789 
9790  if (rte->lateral)
9791  appendStringInfoString(buf, "LATERAL ");
9792 
9793  /* Print the FROM item proper */
9794  switch (rte->rtekind)
9795  {
9796  case RTE_RELATION:
9797  /* Normal relation RTE */
9798  appendStringInfo(buf, "%s%s",
9799  only_marker(rte),
9801  context->namespaces));
9802  break;
9803  case RTE_SUBQUERY:
9804  /* Subquery RTE */
9805  appendStringInfoChar(buf, '(');
9806  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9807  context->prettyFlags, context->wrapColumn,
9808  context->indentLevel);
9809  appendStringInfoChar(buf, ')');
9810  break;
9811  case RTE_FUNCTION:
9812  /* Function RTE */
9813  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9814 
9815  /*
9816  * Omit ROWS FROM() syntax for just one function, unless it
9817  * has both a coldeflist and WITH ORDINALITY. If it has both,
9818  * we must use ROWS FROM() syntax to avoid ambiguity about
9819  * whether the coldeflist includes the ordinality column.
9820  */
9821  if (list_length(rte->functions) == 1 &&
9822  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9823  {
9824  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
9825  /* we'll print the coldeflist below, if it has one */
9826  }
9827  else
9828  {
9829  bool all_unnest;
9830  ListCell *lc;
9831 
9832  /*
9833  * If all the function calls in the list are to unnest,
9834  * and none need a coldeflist, then collapse the list back
9835  * down to UNNEST(args). (If we had more than one
9836  * built-in unnest function, this would get more
9837  * difficult.)
9838  *
9839  * XXX This is pretty ugly, since it makes not-terribly-
9840  * future-proof assumptions about what the parser would do
9841  * with the output; but the alternative is to emit our
9842  * nonstandard ROWS FROM() notation for what might have
9843  * been a perfectly spec-compliant multi-argument
9844  * UNNEST().
9845  */
9846  all_unnest = true;
9847  foreach(lc, rte->functions)
9848  {
9849  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9850 
9851  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9852  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9853  rtfunc->funccolnames != NIL)
9854  {
9855  all_unnest = false;
9856  break;
9857  }
9858  }
9859 
9860  if (all_unnest)
9861  {
9862  List *allargs = NIL;
9863 
9864  foreach(lc, rte->functions)
9865  {
9866  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9867  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9868 
9869  allargs = list_concat(allargs, list_copy(args));
9870  }
9871 
9872  appendStringInfoString(buf, "UNNEST(");
9873  get_rule_expr((Node *) allargs, context, true);
9874  appendStringInfoChar(buf, ')');
9875  }
9876  else
9877  {
9878  int funcno = 0;
9879 
9880  appendStringInfoString(buf, "ROWS FROM(");
9881  foreach(lc, rte->functions)
9882  {
9883  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9884 
9885  if (funcno > 0)
9886  appendStringInfoString(buf, ", ");
9887  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
9888  if (rtfunc->funccolnames != NIL)
9889  {
9890  /* Reconstruct the column definition list */
9891  appendStringInfoString(buf, " AS ");
9893  NULL,
9894  context);
9895  }
9896  funcno++;
9897  }
9898  appendStringInfoChar(buf, ')');
9899  }
9900  /* prevent printing duplicate coldeflist below */
9901  rtfunc1 = NULL;
9902  }
9903  if (rte->funcordinality)
9904  appendStringInfoString(buf, " WITH ORDINALITY");
9905  break;
9906  case RTE_TABLEFUNC:
9907  get_tablefunc(rte->tablefunc, context, true);
9908  break;
9909  case RTE_VALUES:
9910  /* Values list RTE */
9911  appendStringInfoChar(buf, '(');
9912  get_values_def(rte->values_lists, context);
9913  appendStringInfoChar(buf, ')');
9914  break;
9915  case RTE_CTE:
9917  break;
9918  default:
9919  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9920  break;
9921  }
9922 
9923  /* Print the relation alias, if needed */
9924  printalias = false;
9925  if (rte->alias != NULL)
9926  {
9927  /* Always print alias if user provided one */
9928  printalias = true;
9929  }
9930  else if (colinfo->printaliases)
9931  {
9932  /* Always print alias if we need to print column aliases */
9933  printalias = true;
9934  }
9935  else if (rte->rtekind == RTE_RELATION)
9936  {
9937  /*
9938  * No need to print alias if it's same as relation name (this
9939  * would normally be the case, but not if set_rtable_names had to
9940  * resolve a conflict).
9941  */
9942  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9943  printalias = true;
9944  }
9945  else if (rte->rtekind == RTE_FUNCTION)
9946  {
9947  /*
9948  * For a function RTE, always print alias. This covers possible
9949  * renaming of the function and/or instability of the
9950  * FigureColname rules for things that aren't simple functions.
9951  * Note we'd need to force it anyway for the columndef list case.
9952  */
9953  printalias = true;
9954  }
9955  else if (rte->rtekind == RTE_VALUES)
9956  {
9957  /* Alias is syntactically required for VALUES */
9958  printalias = true;
9959  }
9960  else if (rte->rtekind == RTE_CTE)
9961  {
9962  /*
9963  * No need to print alias if it's same as CTE name (this would
9964  * normally be the case, but not if set_rtable_names had to
9965  * resolve a conflict).
9966  */
9967  if (strcmp(refname, rte->ctename) != 0)
9968  printalias = true;
9969  }
9970  if (printalias)
9971  appendStringInfo(buf, " %s", quote_identifier(refname));
9972 
9973  /* Print the column definitions or aliases, if needed */
9974  if (rtfunc1 && rtfunc1->funccolnames != NIL)
9975  {
9976  /* Reconstruct the columndef list, which is also the aliases */
9977  get_from_clause_coldeflist(rtfunc1, colinfo, context);
9978  }
9979  else
9980  {
9981  /* Else print column aliases as needed */
9982  get_column_alias_list(colinfo, context);
9983  }
9984 
9985  /* Tablesample clause must go after any alias */
9986  if (rte->rtekind == RTE_RELATION && rte->tablesample)
9987  get_tablesample_def(rte->tablesample, context);
9988  }
9989  else if (IsA(jtnode, JoinExpr))
9990  {
9991  JoinExpr *j = (JoinExpr *) jtnode;
9992  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
9993  bool need_paren_on_right;
9994 
9995  need_paren_on_right = PRETTY_PAREN(context) &&
9996  !IsA(j->rarg, RangeTblRef) &&
9997  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
9998 
9999  if (!PRETTY_PAREN(context) || j->alias != NULL)
10000  appendStringInfoChar(buf, '(');
10001 
10002  get_from_clause_item(j->larg, query, context);
10003 
10004  switch (j->jointype)
10005  {
10006  case JOIN_INNER:
10007  if (j->quals)
10008  appendContextKeyword(context, " JOIN ",
10012  else
10013  appendContextKeyword(context, " CROSS JOIN ",
10017  break;
10018  case JOIN_LEFT:
10019  appendContextKeyword(context, " LEFT JOIN ",
10023  break;
10024  case JOIN_FULL:
10025  appendContextKeyword(context, " FULL JOIN ",
10029  break;
10030  case JOIN_RIGHT:
10031  appendContextKeyword(context, " RIGHT JOIN ",
10035  break;
10036  default:
10037  elog(ERROR, "unrecognized join type: %d",
10038  (int) j->jointype);
10039  }
10040 
10041  if (need_paren_on_right)
10042  appendStringInfoChar(buf, '(');
10043  get_from_clause_item(j->rarg, query, context);
10044  if (need_paren_on_right)
10045  appendStringInfoChar(buf, ')');
10046 
10047  if (j->usingClause)
10048  {
10049  ListCell *lc;
10050  bool first = true;
10051 
10052  appendStringInfoString(buf, " USING (");
10053  /* Use the assigned names, not what's in usingClause */
10054  foreach(lc, colinfo->usingNames)
10055  {
10056  char *colname = (char *) lfirst(lc);
10057 
10058  if (first)
10059  first = false;
10060  else
10061  appendStringInfoString(buf, ", ");
10063  }
10064  appendStringInfoChar(buf, ')');
10065  }
10066  else if (j->quals)
10067  {
10068  appendStringInfoString(buf, " ON ");
10069  if (!PRETTY_PAREN(context))
10070  appendStringInfoChar(buf, '(');
10071  get_rule_expr(j->quals, context, false);
10072  if (!PRETTY_PAREN(context))
10073  appendStringInfoChar(buf, ')');
10074  }
10075  else if (j->jointype != JOIN_INNER)
10076  {
10077  /* If we didn't say CROSS JOIN above, we must provide an ON */
10078  appendStringInfoString(buf, " ON TRUE");
10079  }
10080 
10081  if (!PRETTY_PAREN(context) || j->alias != NULL)
10082  appendStringInfoChar(buf, ')');
10083 
10084  /* Yes, it's correct to put alias after the right paren ... */
10085  if (j->alias != NULL)
10086  {
10087  appendStringInfo(buf, " %s",
10089  get_column_alias_list(colinfo, context);
10090  }
10091  }
10092  else
10093  elog(ERROR, "unrecognized node type: %d",
10094  (int) nodeTag(jtnode));
10095 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10496
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
Alias * alias
Definition: parsenodes.h:1048
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:510
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool funcordinality
Definition: parsenodes.h:1000
List * values_lists
Definition: parsenodes.h:1010
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10516
Node * larg
Definition: primnodes.h:1451
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10196
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:271
TableFunc * tablefunc
Definition: parsenodes.h:1005
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7495
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:275
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
List * usingClause
Definition: primnodes.h:1453
Node * quals
Definition: primnodes.h:1454
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9564
Node * rarg
Definition: primnodes.h:1452
Alias * alias
Definition: primnodes.h:1455
JoinType jointype
Definition: primnodes.h:1449
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:999
#define only_marker(rte)
Definition: ruleutils.c:466
static int list_length(const List *l)
Definition: pg_list.h:89
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4850
#define nodeTag(nodeptr)
Definition: nodes.h:515
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4923
RTEKind rtekind
Definition: parsenodes.h:945
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10103
char * ctename
Definition: parsenodes.h:1015
Query * subquery
Definition: parsenodes.h:968
StringInfo buf
Definition: ruleutils.c:108
#define elog
Definition: elog.h:219
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10143
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8806
int rtindex
Definition: primnodes.h:1456
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:963
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4406
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9776
static void get_func_expr ( FuncExpr expr,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 8917 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, FuncExpr::args, buf, deparse_context::buf, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, ereport, errcode(), errmsg(), ERROR, exprIsLengthCoercion(), exprType(), FUNC_MAX_ARGS, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcvariadic, generate_function_name(), get_coercion_expr(), get_rule_expr(), get_rule_expr_paren(), IsA, lappend(), lfirst, linitial, list_length(), lnext, NIL, and deparse_context::special_exprkind.

Referenced by get_rule_expr().

8919 {
8920  StringInfo buf = context->buf;
8921  Oid funcoid = expr->funcid;
8922  Oid argtypes[FUNC_MAX_ARGS];
8923  int nargs;
8924  List *argnames;
8925  bool use_variadic;
8926  ListCell *l;
8927 
8928  /*
8929  * If the function call came from an implicit coercion, then just show the
8930  * first argument --- unless caller wants to see implicit coercions.
8931  */
8932  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8933  {
8934  get_rule_expr_paren((Node *) linitial(expr->args), context,
8935  false, (Node *) expr);
8936  return;
8937  }
8938 
8939  /*
8940  * If the function call came from a cast, then show the first argument
8941  * plus an explicit cast operation.
8942  */
8943  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8945  {
8946  Node *arg = linitial(expr->args);
8947  Oid rettype = expr->funcresulttype;
8948  int32 coercedTypmod;
8949 
8950  /* Get the typmod if this is a length-coercion function */
8951  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8952 
8953  get_coercion_expr(arg, context,
8954  rettype, coercedTypmod,
8955  (Node *) expr);
8956 
8957  return;
8958  }
8959 
8960  /*
8961  * Normal function: display as proname(args). First we need to extract
8962  * the argument datatypes.
8963  */
8964  if (list_length(expr->args) > FUNC_MAX_ARGS)
8965  ereport(ERROR,
8966  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8967  errmsg("too many arguments")));
8968  nargs = 0;
8969  argnames = NIL;
8970  foreach(l, expr->args)
8971  {
8972  Node *arg = (Node *) lfirst(l);
8973 
8974  if (IsA(arg, NamedArgExpr))
8975  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8976  argtypes[nargs] = exprType(arg);
8977  nargs++;
8978  }
8979 
8980  appendStringInfo(buf, "%s(",
8981  generate_function_name(funcoid, nargs,
8982  argnames, argtypes,
8983  expr->funcvariadic,
8984  &use_variadic,
8985  context->special_exprkind));
8986  nargs = 0;
8987  foreach(l, expr->args)
8988  {
8989  if (nargs++ > 0)
8990  appendStringInfoString(buf, ", ");
8991  if (use_variadic && lnext(l) == NULL)
8992  appendStringInfoString(buf, "VARIADIC ");
8993  get_rule_expr((Node *) lfirst(l), context, true);
8994  }
8995  appendStringInfoChar(buf, ')');
8996 }
Oid funcresulttype
Definition: primnodes.h:450
#define NIL
Definition: pg_list.h:69
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10618
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7568
List * args
Definition: primnodes.h:457
Definition: nodes.h:510
int errcode(int sqlerrcode)
Definition: elog.c:575
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:513
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:454
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:9201
ParseExprKind special_exprkind
Definition: ruleutils.c:116
List * lappend(List *list, void *datum)
Definition: list.c:128
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
StringInfo buf
Definition: ruleutils.c:108
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:452
static void get_insert_query_def ( Query query,
deparse_context context 
)
static

Definition at line 5905 of file ruleutils.c.

References OnConflictExpr::action, RangeTblEntry::alias, Alias::aliasname, appendContextKeyword(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, Assert, buf, deparse_context::buf, OnConflictExpr::constraint, elog, ERROR, TargetEntry::expr, generate_relation_name(), get_constraint_name(), get_query_def(), get_relid_attribute_name(), get_rule_expr(), get_target_list(), get_update_query_targetlist_def(), get_values_def(), get_with_clause(), deparse_context::indentLevel, lappend(), lfirst, NIL, OidIsValid, Query::onConflict, ONCONFLICT_NOTHING, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, Query::override, OVERRIDING_SYSTEM_VALUE, OVERRIDING_USER_VALUE, PRETTY_INDENT, deparse_context::prettyFlags, PRETTYINDENT_STD, processIndirection(), quote_identifier(), RangeTblEntry::relid, TargetEntry::resjunk, TargetEntry::resno, Query::resultRelation, Query::returningList, rt_fetch, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::subquery, Query::targetList, RangeTblEntry::values_lists, deparse_context::varprefix, and deparse_context::wrapColumn.

Referenced by get_query_def().

5906 {
5907  StringInfo buf = context->buf;
5908  RangeTblEntry *select_rte = NULL;
5909  RangeTblEntry *values_rte = NULL;
5910  RangeTblEntry *rte;
5911  char *sep;
5912  ListCell *l;
5913  List *strippedexprs;
5914 
5915  /* Insert the WITH clause if given */
5916  get_with_clause(query, context);
5917 
5918  /*
5919  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5920  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5921  */
5922  foreach(l, query->rtable)
5923  {
5924  rte = (RangeTblEntry *) lfirst(l);
5925 
5926  if (rte->rtekind == RTE_SUBQUERY)
5927  {
5928  if (select_rte)
5929  elog(ERROR, "too many subquery RTEs in INSERT");
5930  select_rte = rte;
5931  }
5932 
5933  if (rte->rtekind == RTE_VALUES)
5934  {
5935  if (values_rte)
5936  elog(ERROR, "too many values RTEs in INSERT");
5937  values_rte = rte;
5938  }
5939  }
5940  if (select_rte && values_rte)
5941  elog(ERROR, "both subquery and values RTEs in INSERT");
5942 
5943  /*
5944  * Start the query with INSERT INTO relname
5945  */
5946  rte = rt_fetch(query->resultRelation, query->rtable);
5947  Assert(rte->rtekind == RTE_RELATION);
5948 
5949  if (PRETTY_INDENT(context))
5950  {
5951  context->indentLevel += PRETTYINDENT_STD;
5952  appendStringInfoChar(buf, ' ');
5953  }
5954  appendStringInfo(buf, "INSERT INTO %s ",
5956  /* INSERT requires AS keyword for target alias */
5957  if (rte->alias != NULL)
5958  appendStringInfo(buf, "AS %s ",
5960 
5961  /*
5962  * Add the insert-column-names list. Any indirection decoration needed on
5963  * the column names can be inferred from the top targetlist.
5964  */
5965  strippedexprs = NIL;
5966  sep = "";
5967  if (query->targetList)
5968  appendStringInfoChar(buf, '(');
5969  foreach(l, query->targetList)
5970  {
5971  TargetEntry *tle = (TargetEntry *) lfirst(l);
5972 
5973  if (tle->resjunk)
5974  continue; /* ignore junk entries */
5975 
5976  appendStringInfoString(buf, sep);
5977  sep = ", ";
5978 
5979  /*
5980  * Put out name of target column; look in the catalogs, not at
5981  * tle->resname, since resname will fail to track RENAME.
5982  */
5985  tle->resno)));
5986 
5987  /*
5988  * Print any indirection needed (subfields or subscripts), and strip
5989  * off the top-level nodes representing the indirection assignments.
5990  * Add the stripped expressions to strippedexprs. (If it's a
5991  * single-VALUES statement, the stripped expressions are the VALUES to
5992  * print below. Otherwise they're just Vars and not really
5993  * interesting.)
5994  */
5995  strippedexprs = lappend(strippedexprs,
5996  processIndirection((Node *) tle->expr,
5997  context));
5998  }
5999  if (query->targetList)
6000  appendStringInfoString(buf, ") ");
6001 
6002  if (query->override)
6003  {
6004  if (query->override == OVERRIDING_SYSTEM_VALUE)
6005  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6006  else if (query->override == OVERRIDING_USER_VALUE)
6007  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6008  }
6009 
6010  if (select_rte)
6011  {
6012  /* Add the SELECT */
6013  get_query_def(select_rte->subquery, buf, NIL, NULL,
6014  context->prettyFlags, context->wrapColumn,
6015  context->indentLevel);
6016  }
6017  else if (values_rte)
6018  {
6019  /* Add the multi-VALUES expression lists */
6020  get_values_def(values_rte->values_lists, context);
6021  }
6022  else if (strippedexprs)
6023  {
6024  /* Add the single-VALUES expression list */
6025  appendContextKeyword(context, "VALUES (",
6027  get_rule_expr((Node *) strippedexprs, context, false);
6028  appendStringInfoChar(buf, ')');
6029  }
6030  else
6031  {
6032  /* No expressions, so it must be DEFAULT VALUES */
6033  appendStringInfoString(buf, "DEFAULT VALUES");
6034  }
6035 
6036  /* Add ON CONFLICT if present */
6037  if (query->onConflict)
6038  {
6039  OnConflictExpr *confl = query->onConflict;
6040 
6041  appendStringInfoString(buf, " ON CONFLICT");
6042 
6043  if (confl->arbiterElems)
6044  {
6045  /* Add the single-VALUES expression list */
6046  appendStringInfoChar(buf, '(');
6047  get_rule_expr((Node *) confl->arbiterElems, context, false);
6048  appendStringInfoChar(buf, ')');
6049 
6050  /* Add a WHERE clause (for partial indexes) if given */
6051  if (confl->arbiterWhere != NULL)
6052  {
6053  bool save_varprefix;
6054 
6055  /*
6056  * Force non-prefixing of Vars, since parser assumes that they
6057  * belong to target relation. WHERE clause does not use
6058  * InferenceElem, so this is separately required.
6059  */
6060  save_varprefix = context->varprefix;
6061  context->varprefix = false;
6062 
6063  appendContextKeyword(context, " WHERE ",
6065  get_rule_expr(confl->arbiterWhere, context, false);
6066 
6067  context->varprefix = save_varprefix;
6068  }
6069  }
6070  else if (OidIsValid(confl->constraint))
6071  {
6072  char *constraint = get_constraint_name(confl->constraint);
6073 
6074  if (!constraint)
6075  elog(ERROR, "cache lookup failed for constraint %u",
6076  confl->constraint);
6077  appendStringInfo(buf, " ON CONSTRAINT %s",
6078  quote_identifier(constraint));
6079  }
6080 
6081  if (confl->action == ONCONFLICT_NOTHING)
6082  {
6083  appendStringInfoString(buf, " DO NOTHING");
6084  }
6085  else
6086  {
6087  appendStringInfoString(buf, " DO UPDATE SET ");
6088  /* Deparse targetlist */
6090  context, rte);
6091 
6092  /* Add a WHERE clause if given */
6093  if (confl->onConflictWhere != NULL)
6094  {
6095  appendContextKeyword(context, " WHERE ",
6097  get_rule_expr(confl->onConflictWhere, context, false);
6098  }
6099  }
6100  }
6101 
6102  /* Add RETURNING if present */
6103  if (query->returningList)
6104  {
6105  appendContextKeyword(context, " RETURNING",
6107  get_target_list(query->returningList, context, NULL);
6108  }
6109 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4966
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
Alias * alias
Definition: parsenodes.h:1048
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:997
OnConflictExpr * onConflict
Definition: parsenodes.h:142
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10283
int resultRelation
Definition: parsenodes.h:120
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5334
Definition: nodes.h:510
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6172
#define OidIsValid(objectId)
Definition: c.h:532
List * values_lists
Definition: parsenodes.h:1010
List * targetList
Definition: parsenodes.h:138
List * arbiterElems
Definition: primnodes.h:1490
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10516
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1375
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7495
AttrNumber resno
Definition: primnodes.h:1369
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1487
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
OverridingKind override
Definition: parsenodes.h:140
#define Assert(condition)
Definition: c.h:681
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1368
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4850
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4923
RTEKind rtekind
Definition: parsenodes.h:945
Node * arbiterWhere
Definition: primnodes.h:1492
Query * subquery
Definition: parsenodes.h:968
StringInfo buf
Definition: ruleutils.c:108
List * onConflictSet
Definition: primnodes.h:1496
#define elog
Definition: elog.h:219
Node * onConflictWhere
Definition: primnodes.h:1497
Definition: pg_list.h:45
static const char* get_name_for_var_field ( Var var,
int  fieldno,
int  levelsup,
deparse_context context 
)
static

Definition at line 6687 of file ruleutils.c.

References Alias::aliasname, Assert, RowExpr::colnames, RangeTblEntry::ctelevelsup, RangeTblEntry::ctename, CommonTableExpr::ctename, CommonTableExpr::ctequery, deparse_namespace::ctes, elog, RangeTblEntry::eref, ERROR, TargetEntry::expr, exprType(), exprTypmod(), find_param_referent(), get_expr_result_type(), get_rte_attribute_name(), get_tle_by_resno(), GetCTETargetList, deparse_namespace::index_tlist, INDEX_VAR, deparse_namespace::inner_planstate, deparse_namespace::inner_tlist, INNER_VAR, InvalidAttrNumber, IsA, RangeTblEntry::joinaliasvars, lcons(), lfirst, list_copy_tail(), list_delete_first(), list_length(), list_nth(), lookup_rowtype_tupdesc_copy(), deparse_context::namespaces, NameStr, NIL, deparse_namespace::outer_planstate, deparse_namespace::outer_tlist, OUTER_VAR, pop_ancestor_plan(), pop_child_plan(), push_ancestor_plan(), push_child_plan(), RECORDOID, TargetEntry::resjunk, rt_fetch, deparse_namespace::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, set_deparse_for_query(), strVal, RangeTblEntry::subquery, Query::targetList, TupleDescAttr, TYPEFUNC_COMPOSITE, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

Referenced by get_rule_expr().

6689 {
6690  RangeTblEntry *rte;
6691  AttrNumber attnum;
6692  int netlevelsup;
6693  deparse_namespace *dpns;
6695  Node *expr;
6696 
6697  /*
6698  * If it's a RowExpr that was expanded from a whole-row Var, use the
6699  * column names attached to it.
6700  */
6701  if (IsA(var, RowExpr))
6702  {
6703  RowExpr *r = (RowExpr *) var;
6704 
6705  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6706  return strVal(list_nth(r->colnames, fieldno - 1));
6707  }
6708 
6709  /*
6710  * If it's a Param of type RECORD, try to find what the Param refers to.
6711  */
6712  if (IsA(var, Param))
6713  {
6714  Param *param = (Param *) var;
6715  ListCell *ancestor_cell;
6716 
6717  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6718  if (expr)
6719  {
6720  /* Found a match, so recurse to decipher the field name */
6721  deparse_namespace save_dpns;
6722  const char *result;
6723 
6724  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6725  result = get_name_for_var_field((Var *) expr, fieldno,
6726  0, context);
6727  pop_ancestor_plan(dpns, &save_dpns);
6728  return result;
6729  }
6730  }
6731 
6732  /*
6733  * If it's a Var of type RECORD, we have to find what the Var refers to;
6734  * if not, we can use get_expr_result_type. If that fails, we try
6735  * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
6736  * an acceptable message.
6737  */
6738  if (!IsA(var, Var) ||
6739  var->vartype != RECORDOID)
6740  {
6741  if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6742  tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
6743  exprTypmod((Node *) var));
6744  Assert(tupleDesc);
6745  /* Got the tupdesc, so we can extract the field name */
6746  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6747  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
6748  }
6749 
6750  /* Find appropriate nesting depth */
6751  netlevelsup = var->varlevelsup + levelsup;
6752  if (netlevelsup >= list_length(context->namespaces))
6753  elog(ERROR, "bogus varlevelsup: %d offset %d",
6754  var->varlevelsup, levelsup);
6755  dpns = (deparse_namespace *) list_nth(context->namespaces,
6756  netlevelsup);
6757 
6758  /*
6759  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6760  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6761  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6762  */
6763  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6764  {
6765  rte = rt_fetch(var->varno, dpns->rtable);
6766  attnum = var->varattno;
6767  }
6768  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6769  {
6770  TargetEntry *tle;
6771  deparse_namespace save_dpns;
6772  const char *result;
6773 
6774  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6775  if (!tle)
6776  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6777 
6778  Assert(netlevelsup == 0);
6779  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6780 
6781  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6782  levelsup, context);
6783 
6784  pop_child_plan(dpns, &save_dpns);
6785  return result;
6786  }
6787  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6788  {
6789  TargetEntry *tle;
6790  deparse_namespace save_dpns;
6791  const char *result;
6792 
6793  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6794  if (!tle)
6795  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6796 
6797  Assert(netlevelsup == 0);
6798  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6799 
6800  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6801  levelsup, context);
6802 
6803  pop_child_plan(dpns, &save_dpns);
6804  return result;
6805  }
6806  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6807  {
6808  TargetEntry *tle;
6809  const char *result;
6810 
6811  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6812  if (!tle)
6813  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6814 
6815  Assert(netlevelsup == 0);
6816 
6817  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6818  levelsup, context);
6819 
6820  return result;
6821  }
6822  else
6823  {
6824  elog(ERROR, "bogus varno: %d", var->varno);
6825  return NULL; /* keep compiler quiet */
6826  }
6827 
6828  if (attnum == InvalidAttrNumber)
6829  {
6830  /* Var is whole-row reference to RTE, so select the right field */
6831  return get_rte_attribute_name(rte, fieldno);
6832  }
6833 
6834  /*
6835  * This part has essentially the same logic as the parser's
6836  * expandRecordVariable() function, but we are dealing with a different
6837  * representation of the input context, and we only need one field name
6838  * not a TupleDesc. Also, we need special cases for finding subquery and
6839  * CTE subplans when deparsing Plan trees.
6840  */
6841  expr = (Node *) var; /* default if we can't drill down */
6842 
6843  switch (rte->rtekind)
6844  {
6845  case RTE_RELATION:
6846  case RTE_VALUES:
6847  case RTE_NAMEDTUPLESTORE:
6848 
6849  /*
6850  * This case should not occur: a column of a table, values list,
6851  * or ENR shouldn't have type RECORD. Fall through and fail (most
6852  * likely) at the bottom.
6853  */
6854  break;
6855  case RTE_SUBQUERY:
6856  /* Subselect-in-FROM: examine sub-select's output expr */
6857  {
6858  if (rte->subquery)
6859  {
6861  attnum);
6862 
6863  if (ste == NULL || ste->resjunk)
6864  elog(ERROR, "subquery %s does not have attribute %d",
6865  rte->eref->aliasname, attnum);
6866  expr = (Node *) ste->expr;
6867  if (IsA(expr, Var))
6868  {
6869  /*
6870  * Recurse into the sub-select to see what its Var
6871  * refers to. We have to build an additional level of
6872  * namespace to keep in step with varlevelsup in the
6873  * subselect.
6874  */
6875  deparse_namespace mydpns;
6876  const char *result;
6877 
6878  set_deparse_for_query(&mydpns, rte->subquery,
6879  context->namespaces);
6880 
6881  context->namespaces = lcons(&mydpns,
6882  context->namespaces);
6883 
6884  result = get_name_for_var_field((Var *) expr, fieldno,
6885  0, context);
6886 
6887  context->namespaces =
6888  list_delete_first(context->namespaces);
6889 
6890  return result;
6891  }
6892  /* else fall through to inspect the expression */
6893  }
6894  else
6895  {
6896  /*
6897  * We're deparsing a Plan tree so we don't have complete
6898  * RTE entries (in particular, rte->subquery is NULL). But
6899  * the only place we'd see a Var directly referencing a
6900  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6901  * look into the child plan's tlist instead.
6902  */
6903  TargetEntry *tle;
6904  deparse_namespace save_dpns;
6905  const char *result;
6906 
6907  if (!dpns->inner_planstate)
6908  elog(ERROR, "failed to find plan for subquery %s",
6909  rte->eref->aliasname);
6910  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6911  if (!tle)
6912  elog(ERROR, "bogus varattno for subquery var: %d",
6913  attnum);
6914  Assert(netlevelsup == 0);
6915  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6916 
6917  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6918  levelsup, context);
6919 
6920  pop_child_plan(dpns, &save_dpns);
6921  return result;
6922  }
6923  }
6924  break;
6925  case RTE_JOIN:
6926  /* Join RTE --- recursively inspect the alias variable */
6927  if (rte->joinaliasvars == NIL)
6928  elog(ERROR, "cannot decompile join alias var in plan tree");
6929  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
6930  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
6931  Assert(expr != NULL);
6932  /* we intentionally don't strip implicit coercions here */
6933  if (IsA(expr, Var))
6934  return get_name_for_var_field((Var *) expr, fieldno,
6935  var->varlevelsup + levelsup,
6936  context);
6937  /* else fall through to inspect the expression */
6938  break;
6939  case RTE_FUNCTION:
6940  case RTE_TABLEFUNC:
6941 
6942  /*
6943  * We couldn't get here unless a function is declared with one of
6944  * its result columns as RECORD, which is not allowed.
6945  */
6946  break;
6947  case RTE_CTE:
6948  /* CTE reference: examine subquery's output expr */
6949  {
6950  CommonTableExpr *cte = NULL;
6951  Index ctelevelsup;
6952  ListCell *lc;
6953 
6954  /*
6955  * Try to find the referenced CTE using the namespace stack.
6956  */
6957  ctelevelsup = rte->ctelevelsup + netlevelsup;
6958  if (ctelevelsup >= list_length(context->namespaces))
6959  lc = NULL;
6960  else
6961  {
6962  deparse_namespace *ctedpns;
6963 
6964  ctedpns = (deparse_namespace *)
6965  list_nth(context->namespaces, ctelevelsup);
6966  foreach(lc, ctedpns->ctes)
6967  {
6968  cte = (CommonTableExpr *) lfirst(lc);
6969  if (strcmp(cte->ctename, rte->ctename) == 0)
6970  break;
6971  }
6972  }
6973  if (lc != NULL)
6974  {
6975  Query *ctequery = (Query *) cte->ctequery;
6977  attnum);
6978 
6979  if (ste == NULL || ste->resjunk)
6980  elog(ERROR, "subquery %s does not have attribute %d",
6981  rte->eref->aliasname, attnum);
6982  expr = (Node *) ste->expr;
6983  if (IsA(expr, Var))
6984  {
6985  /*
6986  * Recurse into the CTE to see what its Var refers to.
6987  * We have to build an additional level of namespace
6988  * to keep in step with varlevelsup in the CTE.
6989  * Furthermore it could be an outer CTE, so we may
6990  * have to delete some levels of namespace.
6991  */
6992  List *save_nslist = context->namespaces;
6993  List *new_nslist;
6994  deparse_namespace mydpns;
6995  const char *result;
6996 
6997  set_deparse_for_query(&mydpns, ctequery,
6998  context->namespaces);
6999 
7000  new_nslist = list_copy_tail(context->namespaces,
7001  ctelevelsup);
7002  context->namespaces = lcons(&mydpns, new_nslist);
7003 
7004  result = get_name_for_var_field((Var *) expr, fieldno,
7005  0, context);
7006 
7007  context->namespaces = save_nslist;
7008 
7009  return result;
7010  }
7011  /* else fall through to inspect the expression */
7012  }
7013  else
7014  {
7015  /*
7016  * We're deparsing a Plan tree so we don't have a CTE
7017  * list. But the only place we'd see a Var directly
7018  * referencing a CTE RTE is in a CteScan plan node, and we
7019  * can look into the subplan's tlist instead.
7020  */
7021  TargetEntry *tle;
7022  deparse_namespace save_dpns;
7023  const char *result;
7024 
7025  if (!dpns->inner_planstate)
7026  elog(ERROR, "failed to find plan for CTE %s",
7027  rte->eref->aliasname);
7028  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7029  if (!tle)
7030  elog(ERROR, "bogus varattno for subquery var: %d",
7031  attnum);
7032  Assert(netlevelsup == 0);
7033  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7034 
7035  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7036  levelsup, context);
7037 
7038  pop_child_plan(dpns, &save_dpns);
7039  return result;
7040  }
7041  }
7042  break;
7043  }
7044 
7045  /*
7046  * We now have an expression we can't expand any more, so see if
7047  * get_expr_result_type() can do anything with it. If not, pass to
7048  * lookup_rowtype_tupdesc() which will probably fail, but will give an
7049  * appropriate error message while failing.
7050  */
7051  if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
7052  tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
7053  exprTypmod(expr));
7054  Assert(tupleDesc);
7055  /* Got the tupdesc, so we can extract the field name */
7056  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7057  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7058 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
List * joinaliasvars
Definition: parsenodes.h:989
Index varlevelsup
Definition: primnodes.h:173
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7069
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
Definition: nodes.h:510
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:168
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4570
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:160
Definition: primnodes.h:163
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:227
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1375
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:999
Oid vartype
Definition: primnodes.h:170
void * list_nth(const List *list, int n)
Definition: list.c:410
static void push_child_plan(deparse_namespace *dpns, PlanState *ps, deparse_namespace *save_dpns)
Definition: ruleutils.c:4500
#define RECORDOID
Definition: pg_type.h:680
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:166
List * outer_tlist
Definition: ruleutils.c:161
unsigned int Index
Definition: c.h:359
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6687
#define INNER_VAR
Definition: primnodes.h:153
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
List * lcons(void *datum, List *list)
Definition: list.c:259
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4517
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1368
PlanState * outer_planstate
Definition: ruleutils.c:159
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
Index ctelevelsup
Definition: parsenodes.h:1016
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3338
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:945
char * ctename
Definition: parsenodes.h:1015
Query * subquery
Definition: parsenodes.h:968
List * index_tlist
Definition: ruleutils.c:163
List * inner_tlist
Definition: ruleutils.c:162
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4547
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1049
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define GetCTETargetList(cte)
Definition: parsenodes.h:1384
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:154
List * list_delete_first(List *list)
Definition: list.c:666
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1613
static void get_opclass_name ( Oid  opclass,
Oid  actual_datatype,
StringInfo  buf 
)
static

Definition at line 10240 of file ruleutils.c.

References appendStringInfo(), CLAOID, elog, ERROR, get_namespace_name(), GetDefaultOpClass(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OidIsValid, OpclassIsVisible(), quote_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by get_rule_expr(), pg_get_indexdef_worker(), and pg_get_partkeydef_worker().

10242 {
10243  HeapTuple ht_opc;
10244  Form_pg_opclass opcrec;
10245  char *opcname;
10246  char *nspname;
10247 
10248  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10249  if (!HeapTupleIsValid(ht_opc))
10250  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10251  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10252 
10253  if (!OidIsValid(actual_datatype) ||
10254  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10255  {
10256  /* Okay, we need the opclass name. Do we need to qualify it? */
10257  opcname = NameStr(opcrec->opcname);
10258  if (OpclassIsVisible(opclass))
10259  appendStringInfo(buf, " %s", quote_identifier(opcname));
10260  else
10261  {
10262  nspname = get_namespace_name(opcrec->opcnamespace);
10263  appendStringInfo(buf, " %s.%s",
10264  quote_identifier(nspname),
10265  quote_identifier(opcname));
10266  }
10267  }
10268  ReleaseSysCache(ht_opc);
10269 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1390
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10390
#define OidIsValid(objectId)
Definition: c.h:532
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1793
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
static void get_oper_expr ( OpExpr expr,
deparse_context context 
)
static

Definition at line 8856 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), arg, generate_unaccent_rules::args, OpExpr::args, buf, deparse_context::buf, elog, ERROR, exprType(), generate_operator_name(), get_rule_expr_paren(), GETSTRUCT, HeapTupleIsValid, InvalidOid, linitial, list_length(), lsecond, ObjectIdGetDatum, OPEROID, OpExpr::opno, PRETTY_PAREN, ReleaseSysCache(), and SearchSysCache1().

Referenced by get_rule_expr().

8857 {
8858  StringInfo buf = context->buf;
8859  Oid opno = expr->opno;
8860  List *args = expr->args;
8861 
8862  if (!PRETTY_PAREN(context))
8863  appendStringInfoChar(buf, '(');
8864  if (list_length(args) == 2)
8865  {
8866  /* binary operator */
8867  Node *arg1 = (Node *) linitial(args);
8868  Node *arg2 = (Node *) lsecond(args);
8869 
8870  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8871  appendStringInfo(buf, " %s ",
8873  exprType(arg1),
8874  exprType(arg2)));
8875  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8876  }
8877  else
8878  {
8879  /* unary operator --- but which side? */
8880  Node *arg = (Node *) linitial(args);
8881  HeapTuple tp;
8882  Form_pg_operator optup;
8883 
8885  if (!HeapTupleIsValid(tp))
8886  elog(ERROR, "cache lookup failed for operator %u", opno);
8887  optup = (Form_pg_operator) GETSTRUCT(tp);
8888  switch (optup->oprkind)
8889  {
8890  case 'l':
8891  appendStringInfo(buf, "%s ",
8893  InvalidOid,
8894  exprType(arg)));
8895  get_rule_expr_paren(arg, context, true, (Node *) expr);
8896  break;
8897  case 'r':
8898  get_rule_expr_paren(arg, context, true, (Node *) expr);
8899  appendStringInfo(buf, " %s",
8901  exprType(arg),
8902  InvalidOid));
8903  break;
8904  default:
8905  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8906  }
8907  ReleaseSysCache(tp);
8908  }
8909  if (!PRETTY_PAREN(context))
8910  appendStringInfoChar(buf, ')');
8911 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7568
Definition: nodes.h:510
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:116
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10728
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
StringInfo buf
Definition: ruleutils.c:108
void * arg
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
static void get_parameter ( Param param,
deparse_context context 
)
static

Definition at line 7189 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), deparse_context::buf, find_param_referent(), get_rule_expr(), IsA, Param::paramid, pop_ancestor_plan(), push_ancestor_plan(), and deparse_context::varprefix.

Referenced by get_rule_expr().

7190 {
7191  Node *expr;
7192  deparse_namespace *dpns;
7193  ListCell *ancestor_cell;
7194 
7195  /*
7196  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7197  * the parameter was computed. Note that failing to find a referent isn't
7198  * an error, since the Param might well be a subplan output rather than an
7199  * input.
7200  */
7201  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7202  if (expr)
7203  {
7204  /* Found a match, so print it */
7205  deparse_namespace save_dpns;
7206  bool save_varprefix;
7207  bool need_paren;
7208 
7209  /* Switch attention to the ancestor plan node */
7210  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7211 
7212  /*
7213  * Force prefixing of Vars, since they won't belong to the relation
7214  * being scanned in the original plan node.
7215  */
7216  save_varprefix = context->varprefix;
7217  context->varprefix = true;
7218 
7219  /*
7220  * A Param's expansion is typically a Var, Aggref, or upper-level
7221  * Param, which wouldn't need extra parentheses. Otherwise, insert
7222  * parens to ensure the expression looks atomic.
7223  */
7224  need_paren = !(IsA(expr, Var) ||
7225  IsA(expr, Aggref) ||
7226  IsA(expr, Param));
7227  if (need_paren)
7228  appendStringInfoChar(context->buf, '(');
7229 
7230  get_rule_expr(expr, context, false);
7231 
7232  if (need_paren)
7233  appendStringInfoChar(context->buf, ')');
7234 
7235  context->varprefix = save_varprefix;
7236 
7237  pop_ancestor_plan(dpns, &save_dpns);
7238 
7239  return;
7240  }
7241 
7242  /*
7243  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7244  */
7245  appendStringInfo(context->buf, "$%d", param->paramid);
7246 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7069
Definition: nodes.h:510
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4570
Definition: primnodes.h:163
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7600
int paramid
Definition: primnodes.h:245
StringInfo buf
Definition: ruleutils.c:108
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4547
static void get_query_def ( Query query,
StringInfo  buf,
List parentnamespace,
TupleDesc  resultDesc,
int  prettyFlags,
int  wrapColumn,
int  startIndent 
)
static

Definition at line 4850 of file ruleutils.c.

References AcquireRewriteLocks(), appendStringInfoString(), buf, deparse_context::buf, CHECK_FOR_INTERRUPTS, check_stack_depth(), CMD_DELETE, CMD_INSERT, CMD_NOTHING, CMD_SELECT, CMD_UPDATE, CMD_UTILITY, Query::commandType, elog, ERROR, EXPR_KIND_NONE, get_delete_query_def(), get_insert_query_def(), get_select_query_def(), get_update_query_def(), get_utility_query_def(), deparse_context::indentLevel, lcons(), list_copy(), list_length(), deparse_context::namespaces, NIL, deparse_context::prettyFlags, Query::rtable, set_deparse_for_query(), deparse_context::special_exprkind, deparse_context::varprefix, deparse_context::windowClause, deparse_context::windowTList, and deparse_context::wrapColumn.

Referenced by get_from_clause_item(), get_insert_query_def(), get_setop_query(), get_sublink_expr(), get_with_clause(), make_ruledef(), and make_viewdef().

4853 {
4854  deparse_context context;
4855  deparse_namespace dpns;
4856 
4857  /* Guard against excessively long or deeply-nested queries */
4860 
4861  /*
4862  * Before we begin to examine the query, acquire locks on referenced
4863  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4864  * consistent results. Note we assume it's OK to scribble on the passed
4865  * querytree!
4866  *
4867  * We are only deparsing the query (we are not about to execute it), so we
4868  * only need AccessShareLock on the relations it mentions.
4869  */
4870  AcquireRewriteLocks(query, false, false);
4871 
4872  context.buf = buf;
4873  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4874  context.windowClause = NIL;
4875  context.windowTList = NIL;
4876  context.varprefix = (parentnamespace != NIL ||
4877  list_length(query->rtable) != 1);
4878  context.prettyFlags = prettyFlags;
4879  context.wrapColumn = wrapColumn;
4880  context.indentLevel = startIndent;
4881  context.special_exprkind = EXPR_KIND_NONE;
4882 
4883  set_deparse_for_query(&dpns, query, parentnamespace);
4884 
4885  switch (query->commandType)
4886  {
4887  case CMD_SELECT:
4888  get_select_query_def(query, &context, resultDesc);
4889  break;
4890 
4891  case CMD_UPDATE:
4892  get_update_query_def(query, &context);
4893  break;
4894 
4895  case CMD_INSERT:
4896  get_insert_query_def(query, &context);
4897  break;
4898 
4899  case CMD_DELETE:
4900  get_delete_query_def(query, &context);
4901  break;
4902 
4903  case CMD_NOTHING:
4904  appendStringInfoString(buf, "NOTHING");
4905  break;
4906 
4907  case CMD_UTILITY:
4908  get_utility_query_def(query, &context);
4909  break;
4910 
4911  default:
4912  elog(ERROR, "unrecognized query command type: %d",
4913  query->commandType);
4914  break;
4915  }
4916 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
List * list_copy(const List *oldlist)
Definition: list.c:1160
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5905
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6117
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6374
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5034
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void check_stack_depth(void)
Definition: postgres.c:3150
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:116
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6323
List * windowTList
Definition: ruleutils.c:111
CmdType commandType
Definition: parsenodes.h:110
List * lcons(void *datum, List *list)
Definition: list.c:259
List * windowClause
Definition: ruleutils.c:110
static int list_length(const List *l)
Definition: pg_list.h:89
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3338
StringInfo buf
Definition: ruleutils.c:108
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
char* get_range_partbound_string ( List bound_datums)

Definition at line 10923 of file ruleutils.c.

References appendStringInfoChar(), appendStringInfoString(), buf, deparse_context::buf, castNode, StringInfoData::data, get_const_expr(), PartitionRangeDatum::kind, lfirst, makeStringInfo(), PARTITION_RANGE_DATUM_MAXVALUE, PARTITION_RANGE_DATUM_MINVALUE, val, and PartitionRangeDatum::value.

Referenced by check_new_partition_bound(), and get_rule_expr().

10924 {
10925  deparse_context context;
10927  ListCell *cell;
10928  char *sep;
10929 
10930  memset(&context, 0, sizeof(deparse_context));
10931  context.buf = buf;
10932 
10933  appendStringInfoString(buf, "(");
10934  sep = "";
10935  foreach(cell, bound_datums)
10936  {
10937  PartitionRangeDatum *datum =
10939 
10940  appendStringInfoString(buf, sep);
10941  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
10942  appendStringInfoString(buf, "MINVALUE");
10943  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
10944  appendStringInfoString(buf, "MAXVALUE");
10945  else
10946  {
10947  Const *val = castNode(Const, datum->value);
10948 
10949  get_const_expr(val, &context, -1);
10950  }
10951  sep = ", ";
10952  }
10953  appendStringInfoChar(buf, ')');
10954 
10955  return buf->data;
10956 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
PartitionRangeDatumKind kind
Definition: parsenodes.h:828
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9257
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
long val
Definition: informix.c:689
static char * get_relation_name ( Oid  relid)
static

Definition at line 10496 of file ruleutils.c.

References elog, ERROR, and get_rel_name().

Referenced by get_from_clause_item(), pg_get_constraintdef_worker(), pg_get_indexdef_worker(), pg_get_partition_constraintdef(), and pg_get_partkeydef_worker().

10497 {
10498  char *relname = get_rel_name(relid);
10499 
10500  if (!relname)
10501  elog(ERROR, "cache lookup failed for relation %u", relid);
10502  return relname;
10503 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
static char * get_rtable_name ( int  rtindex,
deparse_context context 
)
static

Definition at line 4406 of file ruleutils.c.

References Assert, linitial, list_length(), list_nth(), deparse_context::namespaces, and deparse_namespace::rtable_names.

Referenced by get_from_clause_item(), and get_select_query_def().

4407 {
4409 
4410  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4411  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4412 }
List * namespaces
Definition: ruleutils.c:109
List * rtable_names
Definition: ruleutils.c:150
#define linitial(l)
Definition: pg_list.h:111
void * list_nth(const List *list, int n)
Definition: list.c:410
#define Assert(condition)
Definition: c.h:681
static int list_length(const List *l)
Definition: pg_list.h:89
static void get_rule_expr ( Node node,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 7600 of file ruleutils.c.

References AND_EXPR, appendContextKeyword(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, NamedArgExpr::arg, FieldSelect::arg, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CollateExpr::arg, CaseExpr::arg, NullTest::arg, BooleanTest::arg, CoerceToDomain::arg, XmlExpr::arg_names, NullTest::argisrow, generate_unaccent_rules::args, GroupingFunc::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, CaseExpr::args, RowExpr::args, CoalesceExpr::args, MinMaxExpr::args, XmlExpr::args, ArrayExpr::array_typeid, Assert, BoolExpr::boolop, BooleanTest::booltesttype, buf, deparse_context::buf, castNode, CHECK_FOR_INTERRUPTS, check_stack_depth(), COERCE_EXPLICIT_CALL, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, CoerceViaIO::coerceformat, ArrayCoerceExpr::coerceformat, CoerceToDomain::coercionformat, CollateExpr::collOid, Const::constisnull, Const::constvalue, convert(), ConvertRowtypeExpr::convertformat, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, DatumGetBool, DatumGetInt32, CaseExpr::defresult, ArrayExpr::elements, elog, ERROR, CaseWhen::expr, InferenceElem::expr, EXPR_SUBLINK, exprType(), exprTypmod(), FieldSelect::fieldnum, forboth, format_type_with_typemod(), generate_collation_name(), generate_operator_name(), generate_relation_name(), get_agg_expr(), get_base_element_type(), get_coercion_expr(), get_const_expr(), get_func_expr(), get_name_for_var_field(), get_opclass_input_type(), get_opclass_name(), get_oper_expr(), get_parameter(), get_range_partbound_string(), get_rule_expr_paren(), get_rule_expr_toplevel(), get_sublink_expr(), get_tablefunc(), get_variable(), get_windowfunc_expr(), i, InferenceElem::infercollid, InferenceElem::inferopclass, PartitionBoundSpec::is_default, IS_DOCUMENT, IS_FALSE, IS_GREATEST, IS_LEAST, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IS_XMLCONCAT, IS_XMLELEMENT, IS_XMLFOREST, IS_XMLPARSE, IS_XMLPI, IS_XMLROOT, IS_XMLSERIALIZE, IsA, RowCompareExpr::largs, lfirst, lfirst_node, linitial, linitial_oid, list_head(), list_length(), PartitionBoundSpec::listdatums, lnext, lookup_rowtype_tupdesc(), PartitionBoundSpec::lowerdatums, lsecond, lsecond_node, lthird_node, map_xml_name_to_sql_identifier(), NamedArgExpr::name, XmlExpr::name, XmlExpr::named_args, tupleDesc::natts, FieldStore::newvals, NIL, nodeTag, NOT_EXPR, NullTest::nulltesttype, MinMaxExpr::op, SQLValueFunction::op, XmlExpr::op, ScalarArrayOpExpr::opno, RowCompareExpr::opnos, OR_EXPR, PARTITION_STRATEGY_LIST, PARTITION_STRATEGY_RANGE, SubPlan::plan_name, PRETTY_INDENT, PRETTY_PAREN, PRETTYINDENT_VAR, printSubscripts(), processIndirection(), quote_identifier(), RowCompareExpr::rargs, RECORDOID, ArrayRef::refassgnexpr, ArrayRef::refexpr, RelabelType::relabelformat, ReleaseTupleDesc, CaseWhen::result, RelabelType::resulttype, CoerceViaIO::resulttype, ArrayCoerceExpr::resulttype, ConvertRowtypeExpr::resulttype, CoerceToDomain::resulttype, RelabelType::resulttypmod, ArrayCoerceExpr::resulttypmod, CoerceToDomain::resulttypmod, RowExpr::row_format, RowExpr::row_typeid, NextValueExpr::seqid, simple_quote_literal(), splan, PartitionBoundSpec::strategy, strip_implicit_coercions(), strVal, AlternativeSubPlan::subplans, SVFOP_CURRENT_CATALOG, SVFOP_CURRENT_DATE, SVFOP_CURRENT_ROLE, SVFOP_CURRENT_SCHEMA, SVFOP_CURRENT_TIME, SVFOP_CURRENT_TIME_N, SVFOP_CURRENT_TIMESTAMP, SVFOP_CURRENT_TIMESTAMP_N, SVFOP_CURRENT_USER, SVFOP_LOCALTIME, SVFOP_LOCALTIME_N, SVFOP_LOCALTIMESTAMP, SVFOP_LOCALTIMESTAMP_N, SVFOP_SESSION_USER, SVFOP_USER, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_CollateExpr, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_GroupingFunc, T_InferenceElem, T_List, T_MinMaxExpr, T_NamedArgExpr, T_NextValueExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_PartitionBoundSpec, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SetToDefault, T_SQLValueFunction, T_SubLink, T_SubPlan, T_TableFunc, T_Var, T_WindowFunc, T_XmlExpr, TupleDescAttr, XmlExpr::type, type_is_rowtype(), SQLValueFunction::typmod, XmlExpr::typmod, PartitionBoundSpec::upperdatums, SubPlan::useHashTable, ScalarArrayOpExpr::useOr, val, deparse_context::varprefix, XML_STANDALONE_NO, XML_STANDALONE_NO_VALUE, XML_STANDALONE_YES, XmlExpr::xmloption, and XMLOPTION_DOCUMENT.

Referenced by deparse_expression_pretty(), get_agg_expr(), get_basic_select_query(), get_delete_query_def(), get_from_clause_item(), get_func_expr(), get_insert_query_def(), get_parameter(), get_rule_expr_funccall(), get_rule_expr_paren(), get_rule_expr_toplevel(), get_rule_sortgroupclause(), get_rule_windowspec(), get_select_query_def(), get_special_variable(), get_sublink_expr(), get_tablefunc(), get_tablesample_def(), get_target_list(), get_update_query_def(), get_update_query_targetlist_def(), get_variable(), get_windowfunc_expr(), make_ruledef(), pg_get_triggerdef_worker(), and printSubscripts().

7602 {
7603  StringInfo buf = context->buf;
7604 
7605  if (node == NULL)
7606  return;
7607 
7608  /* Guard against excessively long or deeply-nested queries */
7611 
7612  /*
7613  * Each level of get_rule_expr must emit an indivisible term
7614  * (parenthesized if necessary) to ensure result is reparsed into the same
7615  * expression tree. The only exception is that when the input is a List,
7616  * we emit the component items comma-separated with no surrounding
7617  * decoration; this is convenient for most callers.
7618  */
7619  switch (nodeTag(node))
7620  {
7621  case T_Var:
7622  (void) get_variable((Var *) node, 0, false, context);
7623  break;
7624 
7625  case T_Const:
7626  get_const_expr((Const *) node, context, 0);
7627  break;
7628 
7629  case T_Param:
7630  get_parameter((Param *) node, context);
7631  break;
7632 
7633  case T_Aggref:
7634  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7635  break;
7636 
7637  case T_GroupingFunc:
7638  {
7639  GroupingFunc *gexpr = (GroupingFunc *) node;
7640 
7641  appendStringInfoString(buf, "GROUPING(");
7642  get_rule_expr((Node *) gexpr->args, context, true);
7643  appendStringInfoChar(buf, ')');
7644  }
7645  break;
7646 
7647  case T_WindowFunc:
7648  get_windowfunc_expr((WindowFunc *) node, context);
7649  break;
7650 
7651  case T_ArrayRef:
7652  {
7653  ArrayRef *aref = (ArrayRef *) node;
7654  bool need_parens;
7655 
7656  /*
7657  * If the argument is a CaseTestExpr, we must be inside a
7658  * FieldStore, ie, we are assigning to an element of an array
7659  * within a composite column. Since we already punted on
7660  * displaying the FieldStore's target information, just punt
7661  * here too, and display only the assignment source
7662  * expression.
7663  */
7664  if (IsA(aref->refexpr, CaseTestExpr))
7665  {
7666  Assert(aref->refassgnexpr);
7667  get_rule_expr((Node *) aref->refassgnexpr,
7668  context, showimplicit);
7669  break;
7670  }
7671 
7672  /*
7673  * Parenthesize the argument unless it's a simple Var or a
7674  * FieldSelect. (In particular, if it's another ArrayRef, we
7675  * *must* parenthesize to avoid confusion.)
7676  */
7677  need_parens = !IsA(aref->refexpr, Var) &&
7678  !IsA(aref->refexpr, FieldSelect);
7679  if (need_parens)
7680  appendStringInfoChar(buf, '(');
7681  get_rule_expr((Node *) aref->refexpr, context, showimplicit);
7682  if (need_parens)
7683  appendStringInfoChar(buf, ')');
7684 
7685  /*
7686  * If there's a refassgnexpr, we want to print the node in the
7687  * format "array[subscripts] := refassgnexpr". This is not
7688  * legal SQL, so decompilation of INSERT or UPDATE statements
7689  * should always use processIndirection as part of the
7690  * statement-level syntax. We should only see this when
7691  * EXPLAIN tries to print the targetlist of a plan resulting
7692  * from such a statement.
7693  */
7694  if (aref->refassgnexpr)
7695  {
7696  Node *refassgnexpr;
7697 
7698  /*
7699  * Use processIndirection to print this node's subscripts
7700  * as well as any additional field selections or
7701  * subscripting in immediate descendants. It returns the
7702  * RHS expr that is actually being "assigned".
7703  */
7704  refassgnexpr = processIndirection(node, context);
7705  appendStringInfoString(buf, " := ");
7706  get_rule_expr(refassgnexpr, context, showimplicit);
7707  }
7708  else
7709  {
7710  /* Just an ordinary array fetch, so print subscripts */
7711  printSubscripts(aref, context);
7712  }
7713  }
7714