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/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_statisticsext_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_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_statisticsextdef (PG_FUNCTION_ARGS)
 
Datum pg_get_partkeydef (PG_FUNCTION_ARGS)
 
char * pg_get_partkeydef_columns (Oid relid, bool pretty)
 
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)
 

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 462 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 82 of file ruleutils.c.

Referenced by get_from_clause_item().

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 85 of file ruleutils.c.

Referenced by appendContextKeyword().

#define PRETTYINDENT_VAR   4

Definition at line 83 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 7428 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().

7430 {
7431  StringInfo buf = context->buf;
7432 
7433  if (PRETTY_INDENT(context))
7434  {
7435  int indentAmount;
7436 
7437  context->indentLevel += indentBefore;
7438 
7439  /* remove any trailing spaces currently in the buffer ... */
7441  /* ... then add a newline and some spaces */
7442  appendStringInfoChar(buf, '\n');
7443 
7444  if (context->indentLevel < PRETTYINDENT_LIMIT)
7445  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7446  else
7447  {
7448  /*
7449  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7450  * to conserve horizontal space by reducing the per-level
7451  * indentation. For best results the scale factor here should
7452  * divide all the indent amounts that get added to indentLevel
7453  * (PRETTYINDENT_STD, etc). It's important that the indentation
7454  * not grow unboundedly, else deeply-nested trees use O(N^2)
7455  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7456  */
7457  indentAmount = PRETTYINDENT_LIMIT +
7458  (context->indentLevel - PRETTYINDENT_LIMIT) /
7459  (PRETTYINDENT_STD / 2);
7460  indentAmount %= PRETTYINDENT_LIMIT;
7461  /* scale/wrap logic affects indentLevel, but not indentPlus */
7462  indentAmount += indentPlus;
7463  }
7464  appendStringInfoSpaces(buf, indentAmount);
7465 
7466  appendStringInfoString(buf, str);
7467 
7468  context->indentLevel += indentAfter;
7469  if (context->indentLevel < 0)
7470  context->indentLevel = 0;
7471  }
7472  else
7473  appendStringInfoString(buf, str);
7474 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:96
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7482
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:219
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:85
#define Max(x, y)
Definition: c.h:800
StringInfo buf
Definition: ruleutils.c:107
static bool colname_is_unique ( char *  colname,
deparse_namespace dpns,
deparse_columns colinfo 
)
static

Definition at line 4063 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().

4065 {
4066  int i;
4067  ListCell *lc;
4068 
4069  /* Check against already-assigned column aliases within RTE */
4070  for (i = 0; i < colinfo->num_cols; i++)
4071  {
4072  char *oldname = colinfo->colnames[i];
4073 
4074  if (oldname && strcmp(oldname, colname) == 0)
4075  return false;
4076  }
4077 
4078  /*
4079  * If we're building a new_colnames array, check that too (this will be
4080  * partially but not completely redundant with the previous checks)
4081  */
4082  for (i = 0; i < colinfo->num_new_cols; i++)
4083  {
4084  char *oldname = colinfo->new_colnames[i];
4085 
4086  if (oldname && strcmp(oldname, colname) == 0)
4087  return false;
4088  }
4089 
4090  /* Also check against USING-column names that must be globally unique */
4091  foreach(lc, dpns->using_names)
4092  {
4093  char *oldname = (char *) lfirst(lc);
4094 
4095  if (strcmp(oldname, colname) == 0)
4096  return false;
4097  }
4098 
4099  /* Also check against names already assigned for parent-join USING cols */
4100  foreach(lc, colinfo->parentUsing)
4101  {
4102  char *oldname = (char *) lfirst(lc);
4103 
4104  if (strcmp(oldname, colname) == 0)
4105  return false;
4106  }
4107 
4108  return true;
4109 }
List * using_names
Definition: ruleutils.c:154
#define lfirst(lc)
Definition: pg_list.h:106
int i
List * parentUsing
Definition: ruleutils.c:248
char ** new_colnames
Definition: ruleutils.c:241
char ** colnames
Definition: ruleutils.c:224
static void decompile_column_index_array ( Datum  column_index_array,
Oid  relId,
StringInfo  buf 
)
static

Definition at line 2126 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2128 {
2129  Datum *keys;
2130  int nKeys;
2131  int j;
2132 
2133  /* Extract data from array of int16 */
2134  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2135  INT2OID, 2, true, 's',
2136  &keys, NULL, &nKeys);
2137 
2138  for (j = 0; j < nKeys; j++)
2139  {
2140  char *colName;
2141 
2142  colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
2143 
2144  if (j == 0)
2146  else
2147  appendStringInfo(buf, ", %s", quote_identifier(colName));
2148  }
2149 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define INT2OID
Definition: pg_type.h:308
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
#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
#define NULL
Definition: c.h:229
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define DatumGetArrayTypeP(X)
Definition: array.h:242
List* deparse_context_for ( const char *  aliasname,
Oid  relid 
)

Definition at line 3006 of file ruleutils.c.

References RangeTblEntry::alias, deparse_namespace::ctes, RangeTblEntry::eref, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, list_make1, makeAlias(), makeNode, NIL, NULL, 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_partkeydef_worker(), StoreAttrDefault(), StoreRelCheck(), and transformPartitionBound().

3007 {
3008  deparse_namespace *dpns;
3009  RangeTblEntry *rte;
3010 
3011  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3012 
3013  /* Build a minimal RTE for the rel */
3014  rte = makeNode(RangeTblEntry);
3015  rte->rtekind = RTE_RELATION;
3016  rte->relid = relid;
3017  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3018  rte->alias = makeAlias(aliasname, NIL);
3019  rte->eref = rte->alias;
3020  rte->lateral = false;
3021  rte->inh = false;
3022  rte->inFromCl = true;
3023 
3024  /* Build one-element rtable */
3025  dpns->rtable = list_make1(rte);
3026  dpns->ctes = NIL;
3027  set_rtable_names(dpns, NIL, NULL);
3029 
3030  /* Return a one-deep namespace stack */
3031  return list_make1(dpns);
3032 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:1015
#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:3150
void * palloc0(Size size)
Definition: mcxt.c:878
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3363
RTEKind rtekind
Definition: parsenodes.h:929
Alias * eref
Definition: parsenodes.h:1016
#define RELKIND_RELATION
Definition: pg_class.h:160
List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

Definition at line 3048 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().

3049 {
3050  deparse_namespace *dpns;
3051 
3052  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3053 
3054  /* Initialize fields that stay the same across the whole plan tree */
3055  dpns->rtable = rtable;
3056  dpns->rtable_names = rtable_names;
3057  dpns->ctes = NIL;
3058 
3059  /*
3060  * Set up column name aliases. We will get rather bogus results for join
3061  * RTEs, but that doesn't matter because plan trees don't contain any join
3062  * alias Vars.
3063  */
3065 
3066  /* Return a one-deep namespace stack */
3067  return list_make1(dpns);
3068 }
#define NIL
Definition: pg_list.h:69
List * rtable_names
Definition: ruleutils.c:149
#define list_make1(x1)
Definition: pg_list.h:139
void * palloc0(Size size)
Definition: mcxt.c:878
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3363
char* deparse_expression ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit 
)

Definition at line 2947 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().

2949 {
2950  return deparse_expression_pretty(expr, dpcontext, forceprefix,
2951  showimplicit, 0, 0);
2952 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:2974
static char * deparse_expression_pretty ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit,
int  prettyFlags,
int  startIndent 
)
static

Definition at line 2974 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(), and pg_get_partkeydef_worker().

2977 {
2979  deparse_context context;
2980 
2981  initStringInfo(&buf);
2982  context.buf = &buf;
2983  context.namespaces = dpcontext;
2984  context.windowClause = NIL;
2985  context.windowTList = NIL;
2986  context.varprefix = forceprefix;
2987  context.prettyFlags = prettyFlags;
2988  context.wrapColumn = WRAP_COLUMN_DEFAULT;
2989  context.indentLevel = startIndent;
2990  context.special_exprkind = EXPR_KIND_NONE;
2991 
2992  get_rule_expr(expr, &context, showimplicit);
2993 
2994  return buf.data;
2995 }
List * namespaces
Definition: ruleutils.c:108
#define NIL
Definition: pg_list.h:69
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:92
static char * buf
Definition: pg_test_fsync.c:66
ParseExprKind special_exprkind
Definition: ruleutils.c:115
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
List * windowTList
Definition: ruleutils.c:110
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
List * windowClause
Definition: ruleutils.c:109
StringInfo buf
Definition: ruleutils.c:107
static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

Definition at line 4161 of file ruleutils.c.

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

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

4162 {
4163  if (n > colinfo->num_cols)
4164  {
4165  if (colinfo->colnames == NULL)
4166  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4167  else
4168  {
4169  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4170  n * sizeof(char *));
4171  memset(colinfo->colnames + colinfo->num_cols, 0,
4172  (n - colinfo->num_cols) * sizeof(char *));
4173  }
4174  colinfo->num_cols = n;
4175  }
4176 }
void * palloc0(Size size)
Definition: mcxt.c:878
#define NULL
Definition: c.h:229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
char ** colnames
Definition: ruleutils.c:224
static Node * find_param_referent ( Param param,
deparse_context context,
deparse_namespace **  dpns_p,
ListCell **  ancestor_cell_p 
)
static

Definition at line 7003 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, NULL, 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().

7005 {
7006  /* Initialize output parameters to prevent compiler warnings */
7007  *dpns_p = NULL;
7008  *ancestor_cell_p = NULL;
7009 
7010  /*
7011  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7012  * SubPlan argument. This will necessarily be in some ancestor of the
7013  * current expression's PlanState.
7014  */
7015  if (param->paramkind == PARAM_EXEC)
7016  {
7017  deparse_namespace *dpns;
7018  PlanState *child_ps;
7019  bool in_same_plan_level;
7020  ListCell *lc;
7021 
7022  dpns = (deparse_namespace *) linitial(context->namespaces);
7023  child_ps = dpns->planstate;
7024  in_same_plan_level = true;
7025 
7026  foreach(lc, dpns->ancestors)
7027  {
7028  PlanState *ps = (PlanState *) lfirst(lc);
7029  ListCell *lc2;
7030 
7031  /*
7032  * NestLoops transmit params to their inner child only; also, once
7033  * we've crawled up out of a subplan, this couldn't possibly be
7034  * the right match.
7035  */
7036  if (IsA(ps, NestLoopState) &&
7037  child_ps == innerPlanState(ps) &&
7038  in_same_plan_level)
7039  {
7040  NestLoop *nl = (NestLoop *) ps->plan;
7041 
7042  foreach(lc2, nl->nestParams)
7043  {
7044  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7045 
7046  if (nlp->paramno == param->paramid)
7047  {
7048  /* Found a match, so return it */
7049  *dpns_p = dpns;
7050  *ancestor_cell_p = lc;
7051  return (Node *) nlp->paramval;
7052  }
7053  }
7054  }
7055 
7056  /*
7057  * Check to see if we're crawling up from a subplan.
7058  */
7059  foreach(lc2, ps->subPlan)
7060  {
7061  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7062  SubPlan *subplan = sstate->subplan;
7063  ListCell *lc3;
7064  ListCell *lc4;
7065 
7066  if (child_ps != sstate->planstate)
7067  continue;
7068 
7069  /* Matched subplan, so check its arguments */
7070  forboth(lc3, subplan->parParam, lc4, subplan->args)
7071  {
7072  int paramid = lfirst_int(lc3);
7073  Node *arg = (Node *) lfirst(lc4);
7074 
7075  if (paramid == param->paramid)
7076  {
7077  /* Found a match, so return it */
7078  *dpns_p = dpns;
7079  *ancestor_cell_p = lc;
7080  return arg;
7081  }
7082  }
7083 
7084  /* Keep looking, but we are emerging from a subplan. */
7085  in_same_plan_level = false;
7086  break;
7087  }
7088 
7089  /*
7090  * Likewise check to see if we're emerging from an initplan.
7091  * Initplans never have any parParams, so no need to search that
7092  * list, but we need to know if we should reset
7093  * in_same_plan_level.
7094  */
7095  foreach(lc2, ps->initPlan)
7096  {
7097  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7098 
7099  if (child_ps != sstate->planstate)
7100  continue;
7101 
7102  /* No parameters to be had here. */
7103  Assert(sstate->subplan->parParam == NIL);
7104 
7105  /* Keep looking, but we are emerging from an initplan. */
7106  in_same_plan_level = false;
7107  break;
7108  }
7109 
7110  /* No luck, crawl up to next ancestor */
7111  child_ps = ps;
7112  }
7113  }
7114 
7115  /* No referent found */
7116  return NULL;
7117 }
List * namespaces
Definition: ruleutils.c:108
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
List * nestParams
Definition: plannodes.h:677
List * initPlan
Definition: execnodes.h:820
List * subPlan
Definition: execnodes.h:822
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:509
Var * paramval
Definition: plannodes.h:684
#define linitial(l)
Definition: pg_list.h:111
struct PlanState * planstate
Definition: execnodes.h:726
SubPlan * subplan
Definition: execnodes.h:725
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:803
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:245
List * parParam
Definition: primnodes.h:708
PlanState * planstate
Definition: ruleutils.c:156
void * arg
#define innerPlanState(node)
Definition: execnodes.h:844
List * args
Definition: primnodes.h:709
static void flatten_join_using_qual ( Node qual,
List **  leftvars,
List **  rightvars 
)
static

Definition at line 4312 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().

4313 {
4314  if (IsA(qual, BoolExpr))
4315  {
4316  /* Handle AND nodes by recursion */
4317  BoolExpr *b = (BoolExpr *) qual;
4318  ListCell *lc;
4319 
4320  Assert(b->boolop == AND_EXPR);
4321  foreach(lc, b->args)
4322  {
4324  leftvars, rightvars);
4325  }
4326  }
4327  else if (IsA(qual, OpExpr))
4328  {
4329  /* Otherwise we should have an equality operator */
4330  OpExpr *op = (OpExpr *) qual;
4331  Var *var;
4332 
4333  if (list_length(op->args) != 2)
4334  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4335  /* Arguments should be Vars with perhaps implicit coercions */
4336  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4337  if (!IsA(var, Var))
4338  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4339  (int) nodeTag(var));
4340  *leftvars = lappend(*leftvars, var);
4341  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4342  if (!IsA(var, Var))
4343  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4344  (int) nodeTag(var));
4345  *rightvars = lappend(*rightvars, var);
4346  }
4347  else
4348  {
4349  /* Perhaps we have an implicit coercion to boolean? */
4350  Node *q = strip_implicit_coercions(qual);
4351 
4352  if (q != qual)
4353  flatten_join_using_qual(q, leftvars, rightvars);
4354  else
4355  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4356  (int) nodeTag(qual));
4357  }
4358 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Definition: nodes.h:509
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:561
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:4312
#define Assert(condition)
Definition: c.h:675
#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:562
#define nodeTag(nodeptr)
Definition: nodes.h:514
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612
static char * flatten_reloptions ( Oid  relid)
static

Definition at line 10707 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

10708 {
10709  char *result = NULL;
10710  HeapTuple tuple;
10711  Datum reloptions;
10712  bool isnull;
10713 
10714  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10715  if (!HeapTupleIsValid(tuple))
10716  elog(ERROR, "cache lookup failed for relation %u", relid);
10717 
10718  reloptions = SysCacheGetAttr(RELOID, tuple,
10719  Anum_pg_class_reloptions, &isnull);
10720  if (!isnull)
10721  {
10723  Datum *options;
10724  int noptions;
10725  int i;
10726 
10727  initStringInfo(&buf);
10728 
10730  TEXTOID, -1, false, 'i',
10731  &options, NULL, &noptions);
10732 
10733  for (i = 0; i < noptions; i++)
10734  {
10735  char *option = TextDatumGetCString(options[i]);
10736  char *name;
10737  char *separator;
10738  char *value;
10739 
10740  /*
10741  * Each array element should have the form name=value. If the "="
10742  * is missing for some reason, treat it like an empty value.
10743  */
10744  name = option;
10745  separator = strchr(option, '=');
10746  if (separator)
10747  {
10748  *separator = '\0';
10749  value = separator + 1;
10750  }
10751  else
10752  value = "";
10753 
10754  if (i > 0)
10755  appendStringInfoString(&buf, ", ");
10756  appendStringInfo(&buf, "%s=", quote_identifier(name));
10757 
10758  /*
10759  * In general we need to quote the value; but to avoid unnecessary
10760  * clutter, do not quote if it is an identifier that would not
10761  * need quoting. (We could also allow numbers, but that is a bit
10762  * trickier than it looks --- for example, are leading zeroes
10763  * significant? We don't want to assume very much here about what
10764  * custom reloptions might mean.)
10765  */
10766  if (quote_identifier(value) == value)
10767  appendStringInfoString(&buf, value);
10768  else
10769  simple_quote_literal(&buf, value);
10770 
10771  pfree(option);
10772  }
10773 
10774  result = buf.data;
10775  }
10776 
10777  ReleaseSysCache(tuple);
10778 
10779  return result;
10780 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
#define TEXTOID
Definition: pg_type.h:324
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
void pfree(void *pointer)
Definition: mcxt.c:950
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#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:9303
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:3475
int i
#define elog
Definition: elog.h:219
static struct @121 value
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:242
char* generate_collation_name ( Oid  collid)

Definition at line 10662 of file ruleutils.c.

References CollationIsVisible(), COLLOID, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, NULL, ObjectIdGetDatum, quote_qualified_identifier(), ReleaseSysCache(), result, 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().

10663 {
10664  HeapTuple tp;
10665  Form_pg_collation colltup;
10666  char *collname;
10667  char *nspname;
10668  char *result;
10669 
10670  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
10671  if (!HeapTupleIsValid(tp))
10672  elog(ERROR, "cache lookup failed for collation %u", collid);
10673  colltup = (Form_pg_collation) GETSTRUCT(tp);
10674  collname = NameStr(colltup->collname);
10675 
10676  if (!CollationIsVisible(collid))
10677  nspname = get_namespace_name(colltup->collnamespace);
10678  else
10679  nspname = NULL;
10680 
10681  result = quote_qualified_identifier(nspname, collname);
10682 
10683  ReleaseSysCache(tp);
10684 
10685  return result;
10686 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
bool CollationIsVisible(Oid collid)
Definition: namespace.c:1965
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10340
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#define NameStr(name)
Definition: c.h:499
#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 10482 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, NULL, ObjectIdGetDatum, OidIsValid, PROCOID, quote_qualified_identifier(), ReleaseSysCache(), result, and SearchSysCache1.

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

10485 {
10486  char *result;
10487  HeapTuple proctup;
10488  Form_pg_proc procform;
10489  char *proname;
10490  bool use_variadic;
10491  char *nspname;
10492  FuncDetailCode p_result;
10493  Oid p_funcid;
10494  Oid p_rettype;
10495  bool p_retset;
10496  int p_nvargs;
10497  Oid p_vatype;
10498  Oid *p_true_typeids;
10499  bool force_qualify = false;
10500 
10501  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10502  if (!HeapTupleIsValid(proctup))
10503  elog(ERROR, "cache lookup failed for function %u", funcid);
10504  procform = (Form_pg_proc) GETSTRUCT(proctup);
10505  proname = NameStr(procform->proname);
10506 
10507  /*
10508  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10509  * qualification in some special cases.
10510  */
10511  if (special_exprkind == EXPR_KIND_GROUP_BY)
10512  {
10513  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10514  force_qualify = true;
10515  }
10516 
10517  /*
10518  * Determine whether VARIADIC should be printed. We must do this first
10519  * since it affects the lookup rules in func_get_detail().
10520  *
10521  * Currently, we always print VARIADIC if the function has a merged
10522  * variadic-array argument. Note that this is always the case for
10523  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10524  *
10525  * In principle, if VARIADIC wasn't originally specified and the array
10526  * actual argument is deconstructable, we could print the array elements
10527  * separately and not print VARIADIC, thus more nearly reproducing the
10528  * original input. For the moment that seems like too much complication
10529  * for the benefit, and anyway we do not know whether VARIADIC was
10530  * originally specified if it's a non-ANY type.
10531  */
10532  if (use_variadic_p)
10533  {
10534  /* Parser should not have set funcvariadic unless fn is variadic */
10535  Assert(!has_variadic || OidIsValid(procform->provariadic));
10536  use_variadic = has_variadic;
10537  *use_variadic_p = use_variadic;
10538  }
10539  else
10540  {
10541  Assert(!has_variadic);
10542  use_variadic = false;
10543  }
10544 
10545  /*
10546  * The idea here is to schema-qualify only if the parser would fail to
10547  * resolve the correct function given the unqualified func name with the
10548  * specified argtypes and VARIADIC flag. But if we already decided to
10549  * force qualification, then we can skip the lookup and pretend we didn't
10550  * find it.
10551  */
10552  if (!force_qualify)
10553  p_result = func_get_detail(list_make1(makeString(proname)),
10554  NIL, argnames, nargs, argtypes,
10555  !use_variadic, true,
10556  &p_funcid, &p_rettype,
10557  &p_retset, &p_nvargs, &p_vatype,
10558  &p_true_typeids, NULL);
10559  else
10560  {
10561  p_result = FUNCDETAIL_NOTFOUND;
10562  p_funcid = InvalidOid;
10563  }
10564 
10565  if ((p_result == FUNCDETAIL_NORMAL ||
10566  p_result == FUNCDETAIL_AGGREGATE ||
10567  p_result == FUNCDETAIL_WINDOWFUNC) &&
10568  p_funcid == funcid)
10569  nspname = NULL;
10570  else
10571  nspname = get_namespace_name(procform->pronamespace);
10572 
10573  result = quote_qualified_identifier(nspname, proname);
10574 
10575  ReleaseSysCache(proctup);
10576 
10577  return result;
10578 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#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:3038
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10340
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:1264
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static char * generate_operator_name ( Oid  operid,
Oid  arg1,
Oid  arg2 
)
static

Definition at line 10592 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, NULL, 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().

10593 {
10595  HeapTuple opertup;
10596  Form_pg_operator operform;
10597  char *oprname;
10598  char *nspname;
10599  Operator p_result;
10600 
10601  initStringInfo(&buf);
10602 
10603  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10604  if (!HeapTupleIsValid(opertup))
10605  elog(ERROR, "cache lookup failed for operator %u", operid);
10606  operform = (Form_pg_operator) GETSTRUCT(opertup);
10607  oprname = NameStr(operform->oprname);
10608 
10609  /*
10610  * The idea here is to schema-qualify only if the parser would fail to
10611  * resolve the correct operator given the unqualified op name with the
10612  * specified argtypes.
10613  */
10614  switch (operform->oprkind)
10615  {
10616  case 'b':
10617  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10618  true, -1);
10619  break;
10620  case 'l':
10621  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10622  true, -1);
10623  break;
10624  case 'r':
10625  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10626  true, -1);
10627  break;
10628  default:
10629  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10630  p_result = NULL; /* keep compiler quiet */
10631  break;
10632  }
10633 
10634  if (p_result != NULL && oprid(p_result) == operid)
10635  nspname = NULL;
10636  else
10637  {
10638  nspname = get_namespace_name(operform->oprnamespace);
10639  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10640  }
10641 
10642  appendStringInfoString(&buf, oprname);
10643 
10644  if (nspname)
10645  appendStringInfoChar(&buf, ')');
10646 
10647  if (p_result != NULL)
10648  ReleaseSysCache(p_result);
10649 
10650  ReleaseSysCache(opertup);
10651 
10652  return buf.data;
10653 }
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:10254
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define list_make1(x1)
Definition: pg_list.h:139
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#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:189
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
static char * buf
Definition: pg_test_fsync.c:66
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
#define NameStr(name)
Definition: c.h:499
#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 10440 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_serial_sequence().

10441 {
10442  HeapTuple tp;
10443  Form_pg_class reltup;
10444  char *relname;
10445  char *nspname;
10446  char *result;
10447 
10448  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10449  if (!HeapTupleIsValid(tp))
10450  elog(ERROR, "cache lookup failed for relation %u", relid);
10451  reltup = (Form_pg_class) GETSTRUCT(tp);
10452  relname = NameStr(reltup->relname);
10453 
10454  nspname = get_namespace_name(reltup->relnamespace);
10455  if (!nspname)
10456  elog(ERROR, "cache lookup failed for namespace %u",
10457  reltup->relnamespace);
10458 
10459  result = quote_qualified_identifier(nspname, relname);
10460 
10461  ReleaseSysCache(tp);
10462 
10463  return result;
10464 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10340
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static char * generate_relation_name ( Oid  relid,
List namespaces 
)
static

Definition at line 10380 of file ruleutils.c.

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

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

10381 {
10382  HeapTuple tp;
10383  Form_pg_class reltup;
10384  bool need_qual;
10385  ListCell *nslist;
10386  char *relname;
10387  char *nspname;
10388  char *result;
10389 
10390  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10391  if (!HeapTupleIsValid(tp))
10392  elog(ERROR, "cache lookup failed for relation %u", relid);
10393  reltup = (Form_pg_class) GETSTRUCT(tp);
10394  relname = NameStr(reltup->relname);
10395 
10396  /* Check for conflicting CTE name */
10397  need_qual = false;
10398  foreach(nslist, namespaces)
10399  {
10400  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10401  ListCell *ctlist;
10402 
10403  foreach(ctlist, dpns->ctes)
10404  {
10405  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10406 
10407  if (strcmp(cte->ctename, relname) == 0)
10408  {
10409  need_qual = true;
10410  break;
10411  }
10412  }
10413  if (need_qual)
10414  break;
10415  }
10416 
10417  /* Otherwise, qualify the name if not visible in search path */
10418  if (!need_qual)
10419  need_qual = !RelationIsVisible(relid);
10420 
10421  if (need_qual)
10422  nspname = get_namespace_name(reltup->relnamespace);
10423  else
10424  nspname = NULL;
10425 
10426  result = quote_qualified_identifier(nspname, relname);
10427 
10428  ReleaseSysCache(tp);
10429 
10430  return result;
10431 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10340
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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:681
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static void get_agg_combine_expr ( Node node,
deparse_context context,
void *  private 
)
static

Definition at line 8999 of file ruleutils.c.

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

Referenced by get_agg_expr().

9000 {
9001  Aggref *aggref;
9002  Aggref *original_aggref = private;
9003 
9004  if (!IsA(node, Aggref))
9005  elog(ERROR, "combining Aggref does not point to an Aggref");
9006 
9007  aggref = (Aggref *) node;
9008  get_agg_expr(aggref, context, original_aggref);
9009 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:8893
#define elog
Definition: elog.h:219
static void get_agg_expr ( Aggref aggref,
deparse_context context,
Aggref original_aggref 
)
static

Definition at line 8893 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, NULL, TargetEntry::resjunk, resolve_special_varno(), and deparse_context::special_exprkind.

Referenced by get_agg_combine_expr(), and get_rule_expr().

8895 {
8896  StringInfo buf = context->buf;
8897  Oid argtypes[FUNC_MAX_ARGS];
8898  int nargs;
8899  bool use_variadic;
8900 
8901  /*
8902  * For a combining aggregate, we look up and deparse the corresponding
8903  * partial aggregate instead. This is necessary because our input
8904  * argument list has been replaced; the new argument list always has just
8905  * one element, which will point to a partial Aggref that supplies us with
8906  * transition states to combine.
8907  */
8908  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
8909  {
8910  TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
8911 
8912  Assert(list_length(aggref->args) == 1);
8913  resolve_special_varno((Node *) tle->expr, context, original_aggref,
8915  return;
8916  }
8917 
8918  /*
8919  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
8920  * to avoid printing this when recursing from the code just above.
8921  */
8922  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
8923  appendStringInfoString(buf, "PARTIAL ");
8924 
8925  /* Extract the argument types as seen by the parser */
8926  nargs = get_aggregate_argtypes(aggref, argtypes);
8927 
8928  /* Print the aggregate name, schema-qualified if needed */
8929  appendStringInfo(buf, "%s(%s",
8930  generate_function_name(aggref->aggfnoid, nargs,
8931  NIL, argtypes,
8932  aggref->aggvariadic,
8933  &use_variadic,
8934  context->special_exprkind),
8935  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
8936 
8937  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
8938  {
8939  /*
8940  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
8941  * worry about inserting VARIADIC. So we can just dump the direct
8942  * args as-is.
8943  */
8944  Assert(!aggref->aggvariadic);
8945  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
8946  Assert(aggref->aggorder != NIL);
8947  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
8948  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8949  }
8950  else
8951  {
8952  /* aggstar can be set only in zero-argument aggregates */
8953  if (aggref->aggstar)
8954  appendStringInfoChar(buf, '*');
8955  else
8956  {
8957  ListCell *l;
8958  int i;
8959 
8960  i = 0;
8961  foreach(l, aggref->args)
8962  {
8963  TargetEntry *tle = (TargetEntry *) lfirst(l);
8964  Node *arg = (Node *) tle->expr;
8965 
8966  Assert(!IsA(arg, NamedArgExpr));
8967  if (tle->resjunk)
8968  continue;
8969  if (i++ > 0)
8970  appendStringInfoString(buf, ", ");
8971  if (use_variadic && i == nargs)
8972  appendStringInfoString(buf, "VARIADIC ");
8973  get_rule_expr(arg, context, true);
8974  }
8975  }
8976 
8977  if (aggref->aggorder != NIL)
8978  {
8979  appendStringInfoString(buf, " ORDER BY ");
8980  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8981  }
8982  }
8983 
8984  if (aggref->aggfilter != NULL)
8985  {
8986  appendStringInfoString(buf, ") FILTER (WHERE ");
8987  get_rule_expr((Node *) aggref->aggfilter, context, false);
8988  }
8989 
8990  appendStringInfoChar(buf, ')');
8991 }
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:10482
bool aggvariadic
Definition: primnodes.h:306
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6536
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5659
Definition: nodes.h:509
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:767
#define FUNC_MAX_ARGS
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:129
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
bool resjunk
Definition: primnodes.h:1374
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
List * aggorder
Definition: primnodes.h:302
List * aggdirectargs
Definition: primnodes.h:300
ParseExprKind special_exprkind
Definition: ruleutils.c:115
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
Oid aggfnoid
Definition: primnodes.h:294
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:8999
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1367
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:768
Expr * aggfilter
Definition: primnodes.h:304
StringInfo buf
Definition: ruleutils.c:107
int i
void * arg
char aggkind
Definition: primnodes.h:308
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1786
static void get_basic_select_query ( Query query,
deparse_context context,
TupleDesc  resultDesc 
)
static

Definition at line 5152 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, NULL, 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().

5154 {
5155  StringInfo buf = context->buf;
5156  RangeTblEntry *values_rte;
5157  char *sep;
5158  ListCell *l;
5159 
5160  if (PRETTY_INDENT(context))
5161  {
5162  context->indentLevel += PRETTYINDENT_STD;
5163  appendStringInfoChar(buf, ' ');
5164  }
5165 
5166  /*
5167  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5168  * VALUES part. This reverses what transformValuesClause() did at parse
5169  * time.
5170  */
5171  values_rte = get_simple_values_rte(query);
5172  if (values_rte)
5173  {
5174  get_values_def(values_rte->values_lists, context);
5175  return;
5176  }
5177 
5178  /*
5179  * Build up the query string - first we say SELECT
5180  */
5181  appendStringInfoString(buf, "SELECT");
5182 
5183  /* Add the DISTINCT clause if given */
5184  if (query->distinctClause != NIL)
5185  {
5186  if (query->hasDistinctOn)
5187  {
5188  appendStringInfoString(buf, " DISTINCT ON (");
5189  sep = "";
5190  foreach(l, query->distinctClause)
5191  {
5192  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5193 
5194  appendStringInfoString(buf, sep);
5196  false, context);
5197  sep = ", ";
5198  }
5199  appendStringInfoChar(buf, ')');
5200  }
5201  else
5202  appendStringInfoString(buf, " DISTINCT");
5203  }
5204 
5205  /* Then we tell what to select (the targetlist) */
5206  get_target_list(query->targetList, context, resultDesc);
5207 
5208  /* Add the FROM clause if needed */
5209  get_from_clause(query, " FROM ", context);
5210 
5211  /* Add the WHERE clause if given */
5212  if (query->jointree->quals != NULL)
5213  {
5214  appendContextKeyword(context, " WHERE ",
5216  get_rule_expr(query->jointree->quals, context, false);
5217  }
5218 
5219  /* Add the GROUP BY clause if given */
5220  if (query->groupClause != NULL || query->groupingSets != NULL)
5221  {
5222  ParseExprKind save_exprkind;
5223 
5224  appendContextKeyword(context, " GROUP BY ",
5226 
5227  save_exprkind = context->special_exprkind;
5229 
5230  if (query->groupingSets == NIL)
5231  {
5232  sep = "";
5233  foreach(l, query->groupClause)
5234  {
5235  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5236 
5237  appendStringInfoString(buf, sep);
5239  false, context);
5240  sep = ", ";
5241  }
5242  }
5243  else
5244  {
5245  sep = "";
5246  foreach(l, query->groupingSets)
5247  {
5248  GroupingSet *grp = lfirst(l);
5249 
5250  appendStringInfoString(buf, sep);
5251  get_rule_groupingset(grp, query->targetList, true, context);
5252  sep = ", ";
5253  }
5254  }
5255 
5256  context->special_exprkind = save_exprkind;
5257  }
5258 
5259  /* Add the HAVING clause if given */
5260  if (query->havingQual != NULL)
5261  {
5262  appendContextKeyword(context, " HAVING ",
5264  get_rule_expr(query->havingQual, context, false);
5265  }
5266 
5267  /* Add the WINDOW clause if needed */
5268  if (query->windowClause != NIL)
5269  get_rule_windowclause(query, context);
5270 }
#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:5279
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5543
Index tleSortGroupRef
Definition: parsenodes.h:1157
List * groupingSets
Definition: parsenodes.h:148
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9573
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5717
#define PRETTY_INDENT(context)
Definition: ruleutils.c:96
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:989
Node * quals
Definition: primnodes.h:1471
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:189
static char * buf
Definition: pg_test_fsync.c:66
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7428
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5599
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
ParseExprKind special_exprkind
Definition: ruleutils.c:115
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
#define NULL
Definition: c.h:229
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4868
List * groupClause
Definition: parsenodes.h:146
StringInfo buf
Definition: ruleutils.c:107
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:5096
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 9092 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().

9095 {
9096  StringInfo buf = context->buf;
9097 
9098  /*
9099  * Since parse_coerce.c doesn't immediately collapse application of
9100  * length-coercion functions to constants, what we'll typically see in
9101  * such cases is a Const with typmod -1 and a length-coercion function
9102  * right above it. Avoid generating redundant output. However, beware of
9103  * suppressing casts when the user actually wrote something like
9104  * 'foo'::text::char(3).
9105  *
9106  * Note: it might seem that we are missing the possibility of needing to
9107  * print a COLLATE clause for such a Const. However, a Const could only
9108  * have nondefault collation in a post-constant-folding tree, in which the
9109  * length coercion would have been folded too. See also the special
9110  * handling of CollateExpr in coerce_to_target_type(): any collation
9111  * marking will be above the coercion node, not below it.
9112  */
9113  if (arg && IsA(arg, Const) &&
9114  ((Const *) arg)->consttype == resulttype &&
9115  ((Const *) arg)->consttypmod == -1)
9116  {
9117  /* Show the constant without normal ::typename decoration */
9118  get_const_expr((Const *) arg, context, -1);
9119  }
9120  else
9121  {
9122  if (!PRETTY_PAREN(context))
9123  appendStringInfoChar(buf, '(');
9124  get_rule_expr_paren(arg, context, false, parentNode);
9125  if (!PRETTY_PAREN(context))
9126  appendStringInfoChar(buf, ')');
9127  }
9128  appendStringInfo(buf, "::%s",
9129  format_type_with_typemod(resulttype, resulttypmod));
9130 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7501
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9148
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static char * buf
Definition: pg_test_fsync.c:66
#define PRETTY_PAREN(context)
Definition: ruleutils.c:95
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
StringInfo buf
Definition: ruleutils.c:107
static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

Definition at line 9989 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().

9990 {
9991  StringInfo buf = context->buf;
9992  int i;
9993  bool first = true;
9994 
9995  /* Don't print aliases if not needed */
9996  if (!colinfo->printaliases)
9997  return;
9998 
9999  for (i = 0; i < colinfo->num_new_cols; i++)
10000  {
10001  char *colname = colinfo->new_colnames[i];
10002 
10003  if (first)
10004  {
10005  appendStringInfoChar(buf, '(');
10006  first = false;
10007  }
10008  else
10009  appendStringInfoString(buf, ", ");
10011  }
10012  if (!first)
10013  appendStringInfoChar(buf, ')');
10014 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
StringInfo buf
Definition: ruleutils.c:107
int i
char ** new_colnames
Definition: ruleutils.c:241
static void get_const_collation ( Const constval,
deparse_context context 
)
static

Definition at line 9283 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().

9284 {
9285  StringInfo buf = context->buf;
9286 
9287  if (OidIsValid(constval->constcollid))
9288  {
9289  Oid typcollation = get_typcollation(constval->consttype);
9290 
9291  if (constval->constcollid != typcollation)
9292  {
9293  appendStringInfo(buf, " COLLATE %s",
9295  }
9296  }
9297 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10662
Oid consttype
Definition: primnodes.h:192
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
Oid constcollid
Definition: primnodes.h:194
static char * buf
Definition: pg_test_fsync.c:66
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2781
StringInfo buf
Definition: ruleutils.c:107
static void get_const_expr ( Const constval,
deparse_context context,
int  showtype 
)
static

Definition at line 9148 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_rule_expr(), and get_rule_sortgroupclause().

9149 {
9150  StringInfo buf = context->buf;
9151  Oid typoutput;
9152  bool typIsVarlena;
9153  char *extval;
9154  bool needlabel = false;
9155 
9156  if (constval->constisnull)
9157  {
9158  /*
9159  * Always label the type of a NULL constant to prevent misdecisions
9160  * about type when reparsing.
9161  */
9162  appendStringInfoString(buf, "NULL");
9163  if (showtype >= 0)
9164  {
9165  appendStringInfo(buf, "::%s",
9167  constval->consttypmod));
9168  get_const_collation(constval, context);
9169  }
9170  return;
9171  }
9172 
9173  getTypeOutputInfo(constval->consttype,
9174  &typoutput, &typIsVarlena);
9175 
9176  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9177 
9178  switch (constval->consttype)
9179  {
9180  case INT4OID:
9181 
9182  /*
9183  * INT4 can be printed without any decoration, unless it is
9184  * negative; in that case print it as '-nnn'::integer to ensure
9185  * that the output will re-parse as a constant, not as a constant
9186  * plus operator. In most cases we could get away with printing
9187  * (-nnn) instead, because of the way that gram.y handles negative
9188  * literals; but that doesn't work for INT_MIN, and it doesn't
9189  * seem that much prettier anyway.
9190  */
9191  if (extval[0] != '-')
9192  appendStringInfoString(buf, extval);
9193  else
9194  {
9195  appendStringInfo(buf, "'%s'", extval);
9196  needlabel = true; /* we must attach a cast */
9197  }
9198  break;
9199 
9200  case NUMERICOID:
9201 
9202  /*
9203  * NUMERIC can be printed without quotes if it looks like a float
9204  * constant (not an integer, and not Infinity or NaN) and doesn't
9205  * have a leading sign (for the same reason as for INT4).
9206  */
9207  if (isdigit((unsigned char) extval[0]) &&
9208  strcspn(extval, "eE.") != strlen(extval))
9209  {
9210  appendStringInfoString(buf, extval);
9211  }
9212  else
9213  {
9214  appendStringInfo(buf, "'%s'", extval);
9215  needlabel = true; /* we must attach a cast */
9216  }
9217  break;
9218 
9219  case BITOID:
9220  case VARBITOID:
9221  appendStringInfo(buf, "B'%s'", extval);
9222  break;
9223 
9224  case BOOLOID:
9225  if (strcmp(extval, "t") == 0)
9226  appendStringInfoString(buf, "true");
9227  else
9228  appendStringInfoString(buf, "false");
9229  break;
9230 
9231  default:
9232  simple_quote_literal(buf, extval);
9233  break;
9234  }
9235 
9236  pfree(extval);
9237 
9238  if (showtype < 0)
9239  return;
9240 
9241  /*
9242  * For showtype == 0, append ::typename unless the constant will be
9243  * implicitly typed as the right type when it is read in.
9244  *
9245  * XXX this code has to be kept in sync with the behavior of the parser,
9246  * especially make_const.
9247  */
9248  switch (constval->consttype)
9249  {
9250  case BOOLOID:
9251  case UNKNOWNOID:
9252  /* These types can be left unlabeled */
9253  needlabel = false;
9254  break;
9255  case INT4OID:
9256  /* We determined above whether a label is needed */
9257  break;
9258  case NUMERICOID:
9259 
9260  /*
9261  * Float-looking constants will be typed as numeric, which we
9262  * checked above; but if there's a nondefault typmod we need to
9263  * show it.
9264  */
9265  needlabel |= (constval->consttypmod >= 0);
9266  break;
9267  default:
9268  needlabel = true;
9269  break;
9270  }
9271  if (needlabel || showtype > 0)
9272  appendStringInfo(buf, "::%s",
9274  constval->consttypmod));
9275 
9276  get_const_collation(constval, context);
9277 }
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:950
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9303
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9283
static char * buf
Definition: pg_test_fsync.c:66
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:1747
StringInfo buf
Definition: ruleutils.c:107
bool constisnull
Definition: primnodes.h:197
static void get_delete_query_def ( Query query,
deparse_context context 
)
static

Definition at line 6257 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, NULL, 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().

6258 {
6259  StringInfo buf = context->buf;
6260  RangeTblEntry *rte;
6261 
6262  /* Insert the WITH clause if given */
6263  get_with_clause(query, context);
6264 
6265  /*
6266  * Start the query with DELETE FROM relname
6267  */
6268  rte = rt_fetch(query->resultRelation, query->rtable);
6269  Assert(rte->rtekind == RTE_RELATION);
6270  if (PRETTY_INDENT(context))
6271  {
6272  appendStringInfoChar(buf, ' ');
6273  context->indentLevel += PRETTYINDENT_STD;
6274  }
6275  appendStringInfo(buf, "DELETE FROM %s%s",
6276  only_marker(rte),
6278  if (rte->alias != NULL)
6279  appendStringInfo(buf, " %s",
6281 
6282  /* Add the USING clause if given */
6283  get_from_clause(query, " USING ", context);
6284 
6285  /* Add a WHERE clause if given */
6286  if (query->jointree->quals != NULL)
6287  {
6288  appendContextKeyword(context, " WHERE ",
6290  get_rule_expr(query->jointree->quals, context, false);
6291  }
6292 
6293  /* Add RETURNING if present */
6294  if (query->returningList)
6295  {
6296  appendContextKeyword(context, " RETURNING",
6298  get_target_list(query->returningList, context, NULL);
6299  }
6300 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4911
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
Alias * alias
Definition: parsenodes.h:1015
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:5279
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9573
#define PRETTY_INDENT(context)
Definition: ruleutils.c:96
Node * quals
Definition: primnodes.h:1471
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10380
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
List * rtable
Definition: parsenodes.h:135
static char * buf
Definition: pg_test_fsync.c:66
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7428
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:462
RTEKind rtekind
Definition: parsenodes.h:929
StringInfo buf
Definition: ruleutils.c:107
static void get_from_clause ( Query query,
const char *  prefix,
deparse_context context 
)
static

Definition at line 9573 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, NULL, 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().

9574 {
9575  StringInfo buf = context->buf;
9576  bool first = true;
9577  ListCell *l;
9578 
9579  /*
9580  * We use the query's jointree as a guide to what to print. However, we
9581  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9582  * only appear at the top level of the jointree, so it's sufficient to
9583  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9584  * for NEW and OLD.
9585  */
9586  foreach(l, query->jointree->fromlist)
9587  {
9588  Node *jtnode = (Node *) lfirst(l);
9589 
9590  if (IsA(jtnode, RangeTblRef))
9591  {
9592  int varno = ((RangeTblRef *) jtnode)->rtindex;
9593  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9594 
9595  if (!rte->inFromCl)
9596  continue;
9597  }
9598 
9599  if (first)
9600  {
9601  appendContextKeyword(context, prefix,
9603  first = false;
9604 
9605  get_from_clause_item(jtnode, query, context);
9606  }
9607  else
9608  {
9609  StringInfoData itembuf;
9610 
9611  appendStringInfoString(buf, ", ");
9612 
9613  /*
9614  * Put the new FROM item's text into itembuf so we can decide
9615  * after we've got it whether or not it needs to go on a new line.
9616  */
9617  initStringInfo(&itembuf);
9618  context->buf = &itembuf;
9619 
9620  get_from_clause_item(jtnode, query, context);
9621 
9622  /* Restore context's output buffer */
9623  context->buf = buf;
9624 
9625  /* Consider line-wrapping if enabled */
9626  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9627  {
9628  /* Does the new item start with a new line? */
9629  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9630  {
9631  /* If so, we shouldn't add anything */
9632  /* instead, remove any trailing spaces currently in buf */
9634  }
9635  else
9636  {
9637  char *trailing_nl;
9638 
9639  /* Locate the start of the current line in the buffer */
9640  trailing_nl = strrchr(buf->data, '\n');
9641  if (trailing_nl == NULL)
9642  trailing_nl = buf->data;
9643  else
9644  trailing_nl++;
9645 
9646  /*
9647  * Add a newline, plus some indentation, if the new item
9648  * would cause an overflow.
9649  */
9650  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9651  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9654  }
9655  }
9656 
9657  /* Add the new item */
9658  appendStringInfoString(buf, itembuf.data);
9659 
9660  /* clean up */
9661  pfree(itembuf.data);
9662  }
9663  }
9664 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
FromExpr * jointree
Definition: parsenodes.h:136
#define PRETTYINDENT_VAR
Definition: ruleutils.c:83
Definition: nodes.h:509
#define PRETTY_INDENT(context)
Definition: ruleutils.c:96
List * fromlist
Definition: primnodes.h:1470
void pfree(void *pointer)
Definition: mcxt.c:950
List * rtable
Definition: parsenodes.h:135
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7428
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7482
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:107
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9667
static void get_from_clause_coldeflist ( RangeTblFunction rtfunc,
deparse_columns colinfo,
deparse_context context 
)
static

Definition at line 10029 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().

10032 {
10033  StringInfo buf = context->buf;
10034  ListCell *l1;
10035  ListCell *l2;
10036  ListCell *l3;
10037  ListCell *l4;
10038  int i;
10039 
10040  appendStringInfoChar(buf, '(');
10041 
10042  /* there's no forfour(), so must chase one list the hard way */
10043  i = 0;
10044  l4 = list_head(rtfunc->funccolnames);
10045  forthree(l1, rtfunc->funccoltypes,
10046  l2, rtfunc->funccoltypmods,
10047  l3, rtfunc->funccolcollations)
10048  {
10049  Oid atttypid = lfirst_oid(l1);
10050  int32 atttypmod = lfirst_int(l2);
10051  Oid attcollation = lfirst_oid(l3);
10052  char *attname;
10053 
10054  if (colinfo)
10055  attname = colinfo->colnames[i];
10056  else
10057  attname = strVal(lfirst(l4));
10058 
10059  Assert(attname); /* shouldn't be any dropped columns here */
10060 
10061  if (i > 0)
10062  appendStringInfoString(buf, ", ");
10063  appendStringInfo(buf, "%s %s",
10064  quote_identifier(attname),
10065  format_type_with_typemod(atttypid, atttypmod));
10066  if (OidIsValid(attcollation) &&
10067  attcollation != get_typcollation(atttypid))
10068  appendStringInfo(buf, " COLLATE %s",
10069  generate_collation_name(attcollation));
10070 
10071  l4 = lnext(l4);
10072  i++;
10073  }
10074 
10075  appendStringInfoChar(buf, ')');
10076 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:189
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10662
signed int int32
Definition: c.h:256
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define lfirst_int(lc)
Definition: pg_list.h:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
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:201
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
List * funccoltypmods
Definition: parsenodes.h:1053
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2781
List * funccolcollations
Definition: parsenodes.h:1054
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:107
int i
#define lfirst_oid(lc)
Definition: pg_list.h:108
char ** colnames
Definition: ruleutils.c:224
static void get_from_clause_item ( Node jtnode,
Query query,
deparse_context context 
)
static

Definition at line 9667 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_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, NULL, 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().

9668 {
9669  StringInfo buf = context->buf;
9671 
9672  if (IsA(jtnode, RangeTblRef))
9673  {
9674  int varno = ((RangeTblRef *) jtnode)->rtindex;
9675  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9676  char *refname = get_rtable_name(varno, context);
9677  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9678  RangeTblFunction *rtfunc1 = NULL;
9679  bool printalias;
9680 
9681  if (rte->lateral)
9682  appendStringInfoString(buf, "LATERAL ");
9683 
9684  /* Print the FROM item proper */
9685  switch (rte->rtekind)
9686  {
9687  case RTE_RELATION:
9688  /* Normal relation RTE */
9689  appendStringInfo(buf, "%s%s",
9690  only_marker(rte),
9692  context->namespaces));
9693  break;
9694  case RTE_SUBQUERY:
9695  /* Subquery RTE */
9696  appendStringInfoChar(buf, '(');
9697  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9698  context->prettyFlags, context->wrapColumn,
9699  context->indentLevel);
9700  appendStringInfoChar(buf, ')');
9701  break;
9702  case RTE_FUNCTION:
9703  /* Function RTE */
9704  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9705 
9706  /*
9707  * Omit ROWS FROM() syntax for just one function, unless it
9708  * has both a coldeflist and WITH ORDINALITY. If it has both,
9709  * we must use ROWS FROM() syntax to avoid ambiguity about
9710  * whether the coldeflist includes the ordinality column.
9711  */
9712  if (list_length(rte->functions) == 1 &&
9713  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9714  {
9715  get_rule_expr(rtfunc1->funcexpr, context, true);
9716  /* we'll print the coldeflist below, if it has one */
9717  }
9718  else
9719  {
9720  bool all_unnest;
9721  ListCell *lc;
9722 
9723  /*
9724  * If all the function calls in the list are to unnest,
9725  * and none need a coldeflist, then collapse the list back
9726  * down to UNNEST(args). (If we had more than one
9727  * built-in unnest function, this would get more
9728  * difficult.)
9729  *
9730  * XXX This is pretty ugly, since it makes not-terribly-
9731  * future-proof assumptions about what the parser would do
9732  * with the output; but the alternative is to emit our
9733  * nonstandard ROWS FROM() notation for what might have
9734  * been a perfectly spec-compliant multi-argument
9735  * UNNEST().
9736  */
9737  all_unnest = true;
9738  foreach(lc, rte->functions)
9739  {
9740  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9741 
9742  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9743  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9744  rtfunc->funccolnames != NIL)
9745  {
9746  all_unnest = false;
9747  break;
9748  }
9749  }
9750 
9751  if (all_unnest)
9752  {
9753  List *allargs = NIL;
9754 
9755  foreach(lc, rte->functions)
9756  {
9757  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9758  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9759 
9760  allargs = list_concat(allargs, list_copy(args));
9761  }
9762 
9763  appendStringInfoString(buf, "UNNEST(");
9764  get_rule_expr((Node *) allargs, context, true);
9765  appendStringInfoChar(buf, ')');
9766  }
9767  else
9768  {
9769  int funcno = 0;
9770 
9771  appendStringInfoString(buf, "ROWS FROM(");
9772  foreach(lc, rte->functions)
9773  {
9774  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9775 
9776  if (funcno > 0)
9777  appendStringInfoString(buf, ", ");
9778  get_rule_expr(rtfunc->funcexpr, context, true);
9779  if (rtfunc->funccolnames != NIL)
9780  {
9781  /* Reconstruct the column definition list */
9782  appendStringInfoString(buf, " AS ");
9784  NULL,
9785  context);
9786  }
9787  funcno++;
9788  }
9789  appendStringInfoChar(buf, ')');
9790  }
9791  /* prevent printing duplicate coldeflist below */
9792  rtfunc1 = NULL;
9793  }
9794  if (rte->funcordinality)
9795  appendStringInfoString(buf, " WITH ORDINALITY");
9796  break;
9797  case RTE_TABLEFUNC:
9798  get_tablefunc(rte->tablefunc, context, true);
9799  break;
9800  case RTE_VALUES:
9801  /* Values list RTE */
9802  appendStringInfoChar(buf, '(');
9803  get_values_def(rte->values_lists, context);
9804  appendStringInfoChar(buf, ')');
9805  break;
9806  case RTE_CTE:
9808  break;
9809  default:
9810  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9811  break;
9812  }
9813 
9814  /* Print the relation alias, if needed */
9815  printalias = false;
9816  if (rte->alias != NULL)
9817  {
9818  /* Always print alias if user provided one */
9819  printalias = true;
9820  }
9821  else if (colinfo->printaliases)
9822  {
9823  /* Always print alias if we need to print column aliases */
9824  printalias = true;
9825  }
9826  else if (rte->rtekind == RTE_RELATION)
9827  {
9828  /*
9829  * No need to print alias if it's same as relation name (this
9830  * would normally be the case, but not if set_rtable_names had to
9831  * resolve a conflict).
9832  */
9833  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9834  printalias = true;
9835  }
9836  else if (rte->rtekind == RTE_FUNCTION)
9837  {
9838  /*
9839  * For a function RTE, always print alias. This covers possible
9840  * renaming of the function and/or instability of the
9841  * FigureColname rules for things that aren't simple functions.
9842  * Note we'd need to force it anyway for the columndef list case.
9843  */
9844  printalias = true;
9845  }
9846  else if (rte->rtekind == RTE_VALUES)
9847  {
9848  /* Alias is syntactically required for VALUES */
9849  printalias = true;
9850  }
9851  else if (rte->rtekind == RTE_CTE)
9852  {
9853  /*
9854  * No need to print alias if it's same as CTE name (this would
9855  * normally be the case, but not if set_rtable_names had to
9856  * resolve a conflict).
9857  */
9858  if (strcmp(refname, rte->ctename) != 0)
9859  printalias = true;
9860  }
9861  if (printalias)
9862  appendStringInfo(buf, " %s", quote_identifier(refname));
9863 
9864  /* Print the column definitions or aliases, if needed */
9865  if (rtfunc1 && rtfunc1->funccolnames != NIL)
9866  {
9867  /* Reconstruct the columndef list, which is also the aliases */
9868  get_from_clause_coldeflist(rtfunc1, colinfo, context);
9869  }
9870  else
9871  {
9872  /* Else print column aliases as needed */
9873  get_column_alias_list(colinfo, context);
9874  }
9875 
9876  /* Tablesample clause must go after any alias */
9877  if (rte->rtekind == RTE_RELATION && rte->tablesample)
9878  get_tablesample_def(rte->tablesample, context);
9879  }
9880  else if (IsA(jtnode, JoinExpr))
9881  {
9882  JoinExpr *j = (JoinExpr *) jtnode;
9883  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
9884  bool need_paren_on_right;
9885 
9886  need_paren_on_right = PRETTY_PAREN(context) &&
9887  !IsA(j->rarg, RangeTblRef) &&
9888  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
9889 
9890  if (!PRETTY_PAREN(context) || j->alias != NULL)
9891  appendStringInfoChar(buf, '(');
9892 
9893  get_from_clause_item(j->larg, query, context);
9894 
9895  switch (j->jointype)
9896  {
9897  case JOIN_INNER:
9898  if (j->quals)
9899  appendContextKeyword(context, " JOIN ",
9903  else
9904  appendContextKeyword(context, " CROSS JOIN ",
9908  break;
9909  case JOIN_LEFT:
9910  appendContextKeyword(context, " LEFT JOIN ",
9914  break;
9915  case JOIN_FULL:
9916  appendContextKeyword(context, " FULL JOIN ",
9920  break;
9921  case JOIN_RIGHT:
9922  appendContextKeyword(context, " RIGHT JOIN ",
9926  break;
9927  default:
9928  elog(ERROR, "unrecognized join type: %d",
9929  (int) j->jointype);
9930  }
9931 
9932  if (need_paren_on_right)
9933  appendStringInfoChar(buf, '(');
9934  get_from_clause_item(j->rarg, query, context);
9935  if (need_paren_on_right)
9936  appendStringInfoChar(buf, ')');
9937 
9938  if (j->usingClause)
9939  {
9940  ListCell *lc;
9941  bool first = true;
9942 
9943  appendStringInfoString(buf, " USING (");
9944  /* Use the assigned names, not what's in usingClause */
9945  foreach(lc, colinfo->usingNames)
9946  {
9947  char *colname = (char *) lfirst(lc);
9948 
9949  if (first)
9950  first = false;
9951  else
9952  appendStringInfoString(buf, ", ");
9954  }
9955  appendStringInfoChar(buf, ')');
9956  }
9957  else if (j->quals)
9958  {
9959  appendStringInfoString(buf, " ON ");
9960  if (!PRETTY_PAREN(context))
9961  appendStringInfoChar(buf, '(');
9962  get_rule_expr(j->quals, context, false);
9963  if (!PRETTY_PAREN(context))
9964  appendStringInfoChar(buf, ')');
9965  }
9966 
9967  if (!PRETTY_PAREN(context) || j->alias != NULL)
9968  appendStringInfoChar(buf, ')');
9969 
9970  /* Yes, it's correct to put alias after the right paren ... */
9971  if (j->alias != NULL)
9972  {
9973  appendStringInfo(buf, " %s",
9975  get_column_alias_list(colinfo, context);
9976  }
9977  }
9978  else
9979  elog(ERROR, "unrecognized node type: %d",
9980  (int) nodeTag(jtnode));
9981 }
List * namespaces
Definition: ruleutils.c:108
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10360
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:82
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
Alias * alias
Definition: parsenodes.h:1015
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:509
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool funcordinality
Definition: parsenodes.h:979
List * values_lists
Definition: parsenodes.h:989
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10380
Node * larg
Definition: primnodes.h:1450
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10082
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#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:270
TableFunc * tablefunc
Definition: parsenodes.h:984
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
#define PRETTY_PAREN(context)
Definition: ruleutils.c:95
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7428
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:274
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
List * usingClause
Definition: primnodes.h:1452
Node * quals
Definition: primnodes.h:1453
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9455
Node * rarg
Definition: primnodes.h:1451
Alias * alias
Definition: primnodes.h:1454
#define NULL
Definition: c.h:229
JoinType jointype
Definition: primnodes.h:1448
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:978
#define only_marker(rte)
Definition: ruleutils.c:462
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:4795
#define nodeTag(nodeptr)
Definition: nodes.h:514
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4868
RTEKind rtekind
Definition: parsenodes.h:929
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9989
char * ctename
Definition: parsenodes.h:994
Query * subquery
Definition: parsenodes.h:947
StringInfo buf
Definition: ruleutils.c:107
#define elog
Definition: elog.h:219
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10029
int rtindex
Definition: primnodes.h:1455
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:942
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4366
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9667
static void get_func_expr ( FuncExpr expr,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 8808 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, NULL, and deparse_context::special_exprkind.

Referenced by get_rule_expr().

8810 {
8811  StringInfo buf = context->buf;
8812  Oid funcoid = expr->funcid;
8813  Oid argtypes[FUNC_MAX_ARGS];
8814  int nargs;
8815  List *argnames;
8816  bool use_variadic;
8817  ListCell *l;
8818 
8819  /*
8820  * If the function call came from an implicit coercion, then just show the
8821  * first argument --- unless caller wants to see implicit coercions.
8822  */
8823  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8824  {
8825  get_rule_expr_paren((Node *) linitial(expr->args), context,
8826  false, (Node *) expr);
8827  return;
8828  }
8829 
8830  /*
8831  * If the function call came from a cast, then show the first argument
8832  * plus an explicit cast operation.
8833  */
8834  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8836  {
8837  Node *arg = linitial(expr->args);
8838  Oid rettype = expr->funcresulttype;
8839  int32 coercedTypmod;
8840 
8841  /* Get the typmod if this is a length-coercion function */
8842  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8843 
8844  get_coercion_expr(arg, context,
8845  rettype, coercedTypmod,
8846  (Node *) expr);
8847 
8848  return;
8849  }
8850 
8851  /*
8852  * Normal function: display as proname(args). First we need to extract
8853  * the argument datatypes.
8854  */
8855  if (list_length(expr->args) > FUNC_MAX_ARGS)
8856  ereport(ERROR,
8857  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8858  errmsg("too many arguments")));
8859  nargs = 0;
8860  argnames = NIL;
8861  foreach(l, expr->args)
8862  {
8863  Node *arg = (Node *) lfirst(l);
8864 
8865  if (IsA(arg, NamedArgExpr))
8866  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8867  argtypes[nargs] = exprType(arg);
8868  nargs++;
8869  }
8870 
8871  appendStringInfo(buf, "%s(",
8872  generate_function_name(funcoid, nargs,
8873  argnames, argtypes,
8874  expr->funcvariadic,
8875  &use_variadic,
8876  context->special_exprkind));
8877  nargs = 0;
8878  foreach(l, expr->args)
8879  {
8880  if (nargs++ > 0)
8881  appendStringInfoString(buf, ", ");
8882  if (use_variadic && lnext(l) == NULL)
8883  appendStringInfoString(buf, "VARIADIC ");
8884  get_rule_expr((Node *) lfirst(l), context, true);
8885  }
8886  appendStringInfoChar(buf, ')');
8887 }
Oid funcresulttype
Definition: primnodes.h:449
#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:10482
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7501
List * args
Definition: primnodes.h:456
Definition: nodes.h:509
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:256
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:453
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:448
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
#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:9092
ParseExprKind special_exprkind
Definition: ruleutils.c:115
List * lappend(List *list, void *datum)
Definition: list.c:128
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
#define NULL
Definition: c.h:229
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
#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:107
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:451
static void get_insert_query_def ( Query query,
deparse_context context 
)
static

Definition at line 5850 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, NULL, 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().

5851 {
5852  StringInfo buf = context->buf;
5853  RangeTblEntry *select_rte = NULL;
5854  RangeTblEntry *values_rte = NULL;
5855  RangeTblEntry *rte;
5856  char *sep;
5857  ListCell *l;
5858  List *strippedexprs;
5859 
5860  /* Insert the WITH clause if given */
5861  get_with_clause(query, context);
5862 
5863  /*
5864  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5865  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5866  */
5867  foreach(l, query->rtable)
5868  {
5869  rte = (RangeTblEntry *) lfirst(l);
5870 
5871  if (rte->rtekind == RTE_SUBQUERY)
5872  {
5873  if (select_rte)
5874  elog(ERROR, "too many subquery RTEs in INSERT");
5875  select_rte = rte;
5876  }
5877 
5878  if (rte->rtekind == RTE_VALUES)
5879  {
5880  if (values_rte)
5881  elog(ERROR, "too many values RTEs in INSERT");
5882  values_rte = rte;
5883  }
5884  }
5885  if (select_rte && values_rte)
5886  elog(ERROR, "both subquery and values RTEs in INSERT");
5887 
5888  /*
5889  * Start the query with INSERT INTO relname
5890  */
5891  rte = rt_fetch(query->resultRelation, query->rtable);
5892  Assert(rte->rtekind == RTE_RELATION);
5893 
5894  if (PRETTY_INDENT(context))
5895  {
5896  context->indentLevel += PRETTYINDENT_STD;
5897  appendStringInfoChar(buf, ' ');
5898  }
5899  appendStringInfo(buf, "INSERT INTO %s ",
5901  /* INSERT requires AS keyword for target alias */
5902  if (rte->alias != NULL)
5903  appendStringInfo(buf, "AS %s ",
5905 
5906  /*
5907  * Add the insert-column-names list. Any indirection decoration needed on
5908  * the column names can be inferred from the top targetlist.
5909  */
5910  strippedexprs = NIL;
5911  sep = "";
5912  if (query->targetList)
5913  appendStringInfoChar(buf, '(');
5914  foreach(l, query->targetList)
5915  {
5916  TargetEntry *tle = (TargetEntry *) lfirst(l);
5917 
5918  if (tle->resjunk)
5919  continue; /* ignore junk entries */
5920 
5921  appendStringInfoString(buf, sep);
5922  sep = ", ";
5923 
5924  /*
5925  * Put out name of target column; look in the catalogs, not at
5926  * tle->resname, since resname will fail to track RENAME.
5927  */
5930  tle->resno)));
5931 
5932  /*
5933  * Print any indirection needed (subfields or subscripts), and strip
5934  * off the top-level nodes representing the indirection assignments.
5935  * Add the stripped expressions to strippedexprs. (If it's a
5936  * single-VALUES statement, the stripped expressions are the VALUES to
5937  * print below. Otherwise they're just Vars and not really
5938  * interesting.)
5939  */
5940  strippedexprs = lappend(strippedexprs,
5941  processIndirection((Node *) tle->expr,
5942  context));
5943  }
5944  if (query->targetList)
5945  appendStringInfoString(buf, ") ");
5946 
5947  if (query->override)
5948  {
5949  if (query->override == OVERRIDING_SYSTEM_VALUE)
5950  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
5951  else if (query->override == OVERRIDING_USER_VALUE)
5952  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
5953  }
5954 
5955  if (select_rte)
5956  {
5957  /* Add the SELECT */
5958  get_query_def(select_rte->subquery, buf, NIL, NULL,
5959  context->prettyFlags, context->wrapColumn,
5960  context->indentLevel);
5961  }
5962  else if (values_rte)
5963  {
5964  /* Add the multi-VALUES expression lists */
5965  get_values_def(values_rte->values_lists, context);
5966  }
5967  else if (strippedexprs)
5968  {
5969  /* Add the single-VALUES expression list */
5970  appendContextKeyword(context, "VALUES (",
5972  get_rule_expr((Node *) strippedexprs, context, false);
5973  appendStringInfoChar(buf, ')');
5974  }
5975  else
5976  {
5977  /* No expressions, so it must be DEFAULT VALUES */
5978  appendStringInfoString(buf, "DEFAULT VALUES");
5979  }
5980 
5981  /* Add ON CONFLICT if present */
5982  if (query->onConflict)
5983  {
5984  OnConflictExpr *confl = query->onConflict;
5985 
5986  appendStringInfoString(buf, " ON CONFLICT");
5987 
5988  if (confl->arbiterElems)
5989  {
5990  /* Add the single-VALUES expression list */
5991  appendStringInfoChar(buf, '(');
5992  get_rule_expr((Node *) confl->arbiterElems, context, false);
5993  appendStringInfoChar(buf, ')');
5994 
5995  /* Add a WHERE clause (for partial indexes) if given */
5996  if (confl->arbiterWhere != NULL)
5997  {
5998  bool save_varprefix;
5999 
6000  /*
6001  * Force non-prefixing of Vars, since parser assumes that they
6002  * belong to target relation. WHERE clause does not use
6003  * InferenceElem, so this is separately required.
6004  */
6005  save_varprefix = context->varprefix;
6006  context->varprefix = false;
6007 
6008  appendContextKeyword(context, " WHERE ",
6010  get_rule_expr(confl->arbiterWhere, context, false);
6011 
6012  context->varprefix = save_varprefix;
6013  }
6014  }
6015  else if (OidIsValid(confl->constraint))
6016  {
6017  char *constraint = get_constraint_name(confl->constraint);
6018 
6019  if (!constraint)
6020  elog(ERROR, "cache lookup failed for constraint %u",
6021  confl->constraint);
6022  appendStringInfo(buf, " ON CONSTRAINT %s",
6023  quote_identifier(constraint));
6024  }
6025 
6026  if (confl->action == ONCONFLICT_NOTHING)
6027  {
6028  appendStringInfoString(buf, " DO NOTHING");
6029  }
6030  else
6031  {
6032  appendStringInfoString(buf, " DO UPDATE SET ");
6033  /* Deparse targetlist */
6035  context, rte);
6036 
6037  /* Add a WHERE clause if given */
6038  if (confl->onConflictWhere != NULL)
6039  {
6040  appendContextKeyword(context, " WHERE ",
6042  get_rule_expr(confl->onConflictWhere, context, false);
6043  }
6044  }
6045  }
6046 
6047  /* Add RETURNING if present */
6048  if (query->returningList)
6049  {
6050  appendContextKeyword(context, " RETURNING",
6052  get_target_list(query->returningList, context, NULL);
6053  }
6054 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4911
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
Alias * alias
Definition: parsenodes.h:1015
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:10166
int resultRelation
Definition: parsenodes.h:120
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5279
Definition: nodes.h:509
#define PRETTY_INDENT(context)
Definition: ruleutils.c:96
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6117
#define OidIsValid(objectId)
Definition: c.h:538
List * values_lists
Definition: parsenodes.h:989
List * targetList
Definition: parsenodes.h:138
List * arbiterElems
Definition: primnodes.h:1489
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10380
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
bool resjunk
Definition: primnodes.h:1374
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7428
AttrNumber resno
Definition: primnodes.h:1368
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:81
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1486
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
OverridingKind override
Definition: parsenodes.h:140
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1367
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4795
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4868
RTEKind rtekind
Definition: parsenodes.h:929
Node * arbiterWhere
Definition: primnodes.h:1491
Query * subquery
Definition: parsenodes.h:947
StringInfo buf
Definition: ruleutils.c:107
List * onConflictSet
Definition: primnodes.h:1495
#define elog
Definition: elog.h:219
Node * onConflictWhere
Definition: primnodes.h:1496
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 6621 of file ruleutils.c.

References Alias::aliasname, Assert, tupleDesc::attrs, 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, NULL, 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, result, 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, TYPEFUNC_COMPOSITE, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

Referenced by get_rule_expr().

6623 {
6624  RangeTblEntry *rte;
6625  AttrNumber attnum;
6626  int netlevelsup;
6627  deparse_namespace *dpns;
6629  Node *expr;
6630 
6631  /*
6632  * If it's a RowExpr that was expanded from a whole-row Var, use the
6633  * column names attached to it.
6634  */
6635  if (IsA(var, RowExpr))
6636  {
6637  RowExpr *r = (RowExpr *) var;
6638 
6639  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6640  return strVal(list_nth(r->colnames, fieldno - 1));
6641  }
6642 
6643  /*
6644  * If it's a Param of type RECORD, try to find what the Param refers to.
6645  */
6646  if (IsA(var, Param))
6647  {
6648  Param *param = (Param *) var;
6649  ListCell *ancestor_cell;
6650 
6651  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6652  if (expr)
6653  {
6654  /* Found a match, so recurse to decipher the field name */
6655  deparse_namespace save_dpns;
6656  const char *result;
6657 
6658  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6659  result = get_name_for_var_field((Var *) expr, fieldno,
6660  0, context);
6661  pop_ancestor_plan(dpns, &save_dpns);
6662  return result;
6663  }
6664  }
6665 
6666  /*
6667  * If it's a Var of type RECORD, we have to find what the Var refers to;
6668  * if not, we can use get_expr_result_type. If that fails, we try
6669  * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
6670  * an acceptable message.
6671  */
6672  if (!IsA(var, Var) ||
6673  var->vartype != RECORDOID)
6674  {
6675  if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6676  tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
6677  exprTypmod((Node *) var));
6678  Assert(tupleDesc);
6679  /* Got the tupdesc, so we can extract the field name */
6680  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6681  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6682  }
6683 
6684  /* Find appropriate nesting depth */
6685  netlevelsup = var->varlevelsup + levelsup;
6686  if (netlevelsup >= list_length(context->namespaces))
6687  elog(ERROR, "bogus varlevelsup: %d offset %d",
6688  var->varlevelsup, levelsup);
6689  dpns = (deparse_namespace *) list_nth(context->namespaces,
6690  netlevelsup);
6691 
6692  /*
6693  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6694  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6695  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6696  */
6697  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6698  {
6699  rte = rt_fetch(var->varno, dpns->rtable);
6700  attnum = var->varattno;
6701  }
6702  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6703  {
6704  TargetEntry *tle;
6705  deparse_namespace save_dpns;
6706  const char *result;
6707 
6708  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6709  if (!tle)
6710  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6711 
6712  Assert(netlevelsup == 0);
6713  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6714 
6715  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6716  levelsup, context);
6717 
6718  pop_child_plan(dpns, &save_dpns);
6719  return result;
6720  }
6721  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6722  {
6723  TargetEntry *tle;
6724  deparse_namespace save_dpns;
6725  const char *result;
6726 
6727  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6728  if (!tle)
6729  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6730 
6731  Assert(netlevelsup == 0);
6732  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6733 
6734  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6735  levelsup, context);
6736 
6737  pop_child_plan(dpns, &save_dpns);
6738  return result;
6739  }
6740  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6741  {
6742  TargetEntry *tle;
6743  const char *result;
6744 
6745  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6746  if (!tle)
6747  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6748 
6749  Assert(netlevelsup == 0);
6750 
6751  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6752  levelsup, context);
6753 
6754  return result;
6755  }
6756  else
6757  {
6758  elog(ERROR, "bogus varno: %d", var->varno);
6759  return NULL; /* keep compiler quiet */
6760  }
6761 
6762  if (attnum == InvalidAttrNumber)
6763  {
6764  /* Var is whole-row reference to RTE, so select the right field */
6765  return get_rte_attribute_name(rte, fieldno);
6766  }
6767 
6768  /*
6769  * This part has essentially the same logic as the parser's
6770  * expandRecordVariable() function, but we are dealing with a different
6771  * representation of the input context, and we only need one field name
6772  * not a TupleDesc. Also, we need special cases for finding subquery and
6773  * CTE subplans when deparsing Plan trees.
6774  */
6775  expr = (Node *) var; /* default if we can't drill down */
6776 
6777  switch (rte->rtekind)
6778  {
6779  case RTE_RELATION:
6780  case RTE_VALUES:
6781  case RTE_NAMEDTUPLESTORE:
6782 
6783  /*
6784  * This case should not occur: a column of a table or values list
6785  * shouldn't have type RECORD. Fall through and fail (most
6786  * likely) at the bottom.
6787  */
6788  break;
6789  case RTE_SUBQUERY:
6790  /* Subselect-in-FROM: examine sub-select's output expr */
6791  {
6792  if (rte->subquery)
6793  {
6795  attnum);
6796 
6797  if (ste == NULL || ste->resjunk)
6798  elog(ERROR, "subquery %s does not have attribute %d",
6799  rte->eref->aliasname, attnum);
6800  expr = (Node *) ste->expr;
6801  if (IsA(expr, Var))
6802  {
6803  /*
6804  * Recurse into the sub-select to see what its Var
6805  * refers to. We have to build an additional level of
6806  * namespace to keep in step with varlevelsup in the
6807  * subselect.
6808  */
6809  deparse_namespace mydpns;
6810  const char *result;
6811 
6812  set_deparse_for_query(&mydpns, rte->subquery,
6813  context->namespaces);
6814 
6815  context->namespaces = lcons(&mydpns,
6816  context->namespaces);
6817 
6818  result = get_name_for_var_field((Var *) expr, fieldno,
6819  0, context);
6820 
6821  context->namespaces =
6822  list_delete_first(context->namespaces);
6823 
6824  return result;
6825  }
6826  /* else fall through to inspect the expression */
6827  }
6828  else
6829  {
6830  /*
6831  * We're deparsing a Plan tree so we don't have complete
6832  * RTE entries (in particular, rte->subquery is NULL). But
6833  * the only place we'd see a Var directly referencing a
6834  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6835  * look into the child plan's tlist instead.
6836  */
6837  TargetEntry *tle;
6838  deparse_namespace save_dpns;
6839  const char *result;
6840 
6841  if (!dpns->inner_planstate)
6842  elog(ERROR, "failed to find plan for subquery %s",
6843  rte->eref->aliasname);
6844  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6845  if (!tle)
6846  elog(ERROR, "bogus varattno for subquery var: %d",
6847  attnum);
6848  Assert(netlevelsup == 0);
6849  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6850 
6851  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6852  levelsup, context);
6853 
6854  pop_child_plan(dpns, &save_dpns);
6855  return result;
6856  }
6857  }
6858  break;
6859  case RTE_JOIN:
6860  /* Join RTE --- recursively inspect the alias variable */
6861  if (rte->joinaliasvars == NIL)
6862  elog(ERROR, "cannot decompile join alias var in plan tree");
6863  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
6864  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
6865  Assert(expr != NULL);
6866  /* we intentionally don't strip implicit coercions here */
6867  if (IsA(expr, Var))
6868  return get_name_for_var_field((Var *) expr, fieldno,
6869  var->varlevelsup + levelsup,
6870  context);
6871  /* else fall through to inspect the expression */
6872  break;
6873  case RTE_FUNCTION:
6874  case RTE_TABLEFUNC:
6875 
6876  /*
6877  * We couldn't get here unless a function is declared with one of
6878  * its result columns as RECORD, which is not allowed.
6879  */
6880  break;
6881  case RTE_CTE:
6882  /* CTE reference: examine subquery's output expr */
6883  {
6884  CommonTableExpr *cte = NULL;
6885  Index ctelevelsup;
6886  ListCell *lc;
6887 
6888  /*
6889  * Try to find the referenced CTE using the namespace stack.
6890  */
6891  ctelevelsup = rte->ctelevelsup + netlevelsup;
6892  if (ctelevelsup >= list_length(context->namespaces))
6893  lc = NULL;
6894  else
6895  {
6896  deparse_namespace *ctedpns;
6897 
6898  ctedpns = (deparse_namespace *)
6899  list_nth(context->namespaces, ctelevelsup);
6900  foreach(lc, ctedpns->ctes)
6901  {
6902  cte = (CommonTableExpr *) lfirst(lc);
6903  if (strcmp(cte->ctename, rte->ctename) == 0)
6904  break;
6905  }
6906  }
6907  if (lc != NULL)
6908  {
6909  Query *ctequery = (Query *) cte->ctequery;
6911  attnum);
6912 
6913  if (ste == NULL || ste->resjunk)
6914  elog(ERROR, "subquery %s does not have attribute %d",
6915  rte->eref->aliasname, attnum);
6916  expr = (Node *) ste->expr;
6917  if (IsA(expr, Var))
6918  {
6919  /*
6920  * Recurse into the CTE to see what its Var refers to.
6921  * We have to build an additional level of namespace
6922  * to keep in step with varlevelsup in the CTE.
6923  * Furthermore it could be an outer CTE, so we may
6924  * have to delete some levels of namespace.
6925  */
6926  List *save_nslist = context->namespaces;
6927  List *new_nslist;
6928  deparse_namespace mydpns;
6929  const char *result;
6930 
6931  set_deparse_for_query(&mydpns, ctequery,
6932  context->namespaces);
6933 
6934  new_nslist = list_copy_tail(context->namespaces,
6935  ctelevelsup);
6936  context->namespaces = lcons(&mydpns, new_nslist);
6937 
6938  result = get_name_for_var_field((Var *) expr, fieldno,
6939  0, context);
6940 
6941  context->namespaces = save_nslist;
6942 
6943  return result;
6944  }
6945  /* else fall through to inspect the expression */
6946  }
6947  else
6948  {
6949  /*
6950  * We're deparsing a Plan tree so we don't have a CTE
6951  * list. But the only place we'd see a Var directly
6952  * referencing a CTE RTE is in a CteScan plan node, and we
6953  * can look into the subplan's tlist instead.
6954  */
6955  TargetEntry *tle;
6956  deparse_namespace save_dpns;
6957  const char *result;
6958 
6959  if (!dpns->inner_planstate)
6960  elog(ERROR, "failed to find plan for CTE %s",
6961  rte->eref->aliasname);
6962  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6963  if (!tle)
6964  elog(ERROR, "bogus varattno for subquery var: %d",
6965  attnum);
6966  Assert(netlevelsup == 0);
6967  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6968 
6969  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6970  levelsup, context);
6971 
6972  pop_child_plan(dpns, &save_dpns);
6973  return result;
6974  }
6975  }
6976  break;
6977  }
6978 
6979  /*
6980  * We now have an expression we can't expand any more, so see if
6981  * get_expr_result_type() can do anything with it. If not, pass to
6982  * lookup_rowtype_tupdesc() which will probably fail, but will give an
6983  * appropriate error message while failing.
6984  */
6985  if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6986  tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
6987  exprTypmod(expr));
6988  Assert(tupleDesc);
6989  /* Got the tupdesc, so we can extract the field name */
6990  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6991  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6992 }
List * namespaces
Definition: ruleutils.c:108
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * joinaliasvars
Definition: parsenodes.h:968
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:7003
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Definition: nodes.h:509
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:168
return result
Definition: formatting.c:1618
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4530
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:159
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:1374
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:998
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:4460
#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:160
unsigned int Index
Definition: c.h:365
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6621
#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:4477
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1367
PlanState * outer_planstate
Definition: ruleutils.c:158
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:995
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3300
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:929
char * ctename
Definition: parsenodes.h:994
Query * subquery
Definition: parsenodes.h:947
List * index_tlist
Definition: ruleutils.c:162
List * inner_tlist
Definition: ruleutils.c:161
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4507
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1016
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define GetCTETargetList(cte)
Definition: parsenodes.h:1351
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:1291
static void get_opclass_name ( Oid  opclass,
Oid  actual_datatype,
StringInfo  buf 
)
static

Definition at line 10126 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().

10128 {
10129  HeapTuple ht_opc;
10130  Form_pg_opclass opcrec;
10131  char *opcname;
10132  char *nspname;
10133 
10134  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10135  if (!HeapTupleIsValid(ht_opc))
10136  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10137  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10138 
10139  if (!OidIsValid(actual_datatype) ||
10140  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10141  {
10142  /* Okay, we need the opclass name. Do we need to qualify it? */
10143  opcname = NameStr(opcrec->opcname);
10144  if (OpclassIsVisible(opclass))
10145  appendStringInfo(buf, " %s", quote_identifier(opcname));
10146  else
10147  {
10148  nspname = get_namespace_name(opcrec->opcnamespace);
10149  appendStringInfo(buf, " %s.%s",
10150  quote_identifier(nspname),
10151  quote_identifier(opcname));
10152  }
10153  }
10154  ReleaseSysCache(ht_opc);
10155 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1378
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10254
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1792
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:499
#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 8747 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().

8748 {
8749  StringInfo buf = context->buf;
8750  Oid opno = expr->opno;
8751  List *args = expr->args;
8752 
8753  if (!PRETTY_PAREN(context))
8754  appendStringInfoChar(buf, '(');
8755  if (list_length(args) == 2)
8756  {
8757  /* binary operator */
8758  Node *arg1 = (Node *) linitial(args);
8759  Node *arg2 = (Node *) lsecond(args);
8760 
8761  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8762  appendStringInfo(buf, " %s ",
8764  exprType(arg1),
8765  exprType(arg2)));
8766  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8767  }
8768  else
8769  {
8770  /* unary operator --- but which side? */
8771  Node *arg = (Node *) linitial(args);
8772  HeapTuple tp;
8773  Form_pg_operator optup;
8774 
8776  if (!HeapTupleIsValid(tp))
8777  elog(ERROR, "cache lookup failed for operator %u", opno);
8778  optup = (Form_pg_operator) GETSTRUCT(tp);
8779  switch (optup->oprkind)
8780  {
8781  case 'l':
8782  appendStringInfo(buf, "%s ",
8784  InvalidOid,
8785  exprType(arg)));
8786  get_rule_expr_paren(arg, context, true, (Node *) expr);
8787  break;
8788  case 'r':
8789  get_rule_expr_paren(arg, context, true, (Node *) expr);
8790  appendStringInfo(buf, " %s",
8792  exprType(arg),
8793  InvalidOid));
8794  break;
8795  default:
8796  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8797  }
8798  ReleaseSysCache(tp);
8799  }
8800  if (!PRETTY_PAREN(context))
8801  appendStringInfoChar(buf, ')');
8802 }
#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:7501
Definition: nodes.h:509
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:116
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10592
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#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:66
#define PRETTY_PAREN(context)
Definition: ruleutils.c:95
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#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:107
void * arg
Oid opno
Definition: primnodes.h:495
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
Definition: pg_list.h:45
static void get_parameter ( Param param,
deparse_context context 
)
static

Definition at line 7123 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().

7124 {
7125  Node *expr;
7126  deparse_namespace *dpns;
7127  ListCell *ancestor_cell;
7128 
7129  /*
7130  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7131  * the parameter was computed. Note that failing to find a referent isn't
7132  * an error, since the Param might well be a subplan output rather than an
7133  * input.
7134  */
7135  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7136  if (expr)
7137  {
7138  /* Found a match, so print it */
7139  deparse_namespace save_dpns;
7140  bool save_varprefix;
7141  bool need_paren;
7142 
7143  /* Switch attention to the ancestor plan node */
7144  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7145 
7146  /*
7147  * Force prefixing of Vars, since they won't belong to the relation
7148  * being scanned in the original plan node.
7149  */
7150  save_varprefix = context->varprefix;
7151  context->varprefix = true;
7152 
7153  /*
7154  * A Param's expansion is typically a Var, Aggref, or upper-level
7155  * Param, which wouldn't need extra parentheses. Otherwise, insert
7156  * parens to ensure the expression looks atomic.
7157  */
7158  need_paren = !(IsA(expr, Var) ||
7159  IsA(expr, Aggref) ||
7160  IsA(expr, Param));
7161  if (need_paren)
7162  appendStringInfoChar(context->buf, '(');
7163 
7164  get_rule_expr(expr, context, false);
7165 
7166  if (need_paren)
7167  appendStringInfoChar(context->buf, ')');
7168 
7169  context->varprefix = save_varprefix;
7170 
7171  pop_ancestor_plan(dpns, &save_dpns);
7172 
7173  return;
7174  }
7175 
7176  /*
7177  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7178  */
7179  appendStringInfo(context->buf, "$%d", param->paramid);
7180 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7003
Definition: nodes.h:509
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4530
Definition: primnodes.h:163
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7533
int paramid
Definition: primnodes.h:245
StringInfo buf
Definition: ruleutils.c:107
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4507
static void get_query_def ( Query query,
StringInfo  buf,
List parentnamespace,
TupleDesc  resultDesc,
int  prettyFlags,
int  wrapColumn,
int  startIndent 
)
static

Definition at line 4795 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().

4798 {
4799  deparse_context context;
4800  deparse_namespace dpns;
4801 
4802  /* Guard against excessively long or deeply-nested queries */
4805 
4806  /*
4807  * Before we begin to examine the query, acquire locks on referenced
4808  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4809  * consistent results. Note we assume it's OK to scribble on the passed
4810  * querytree!
4811  *
4812  * We are only deparsing the query (we are not about to execute it), so we
4813  * only need AccessShareLock on the relations it mentions.
4814  */
4815  AcquireRewriteLocks(query, false, false);
4816 
4817  context.buf = buf;
4818  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4819  context.windowClause = NIL;
4820  context.windowTList = NIL;
4821  context.varprefix = (parentnamespace != NIL ||
4822  list_length(query->rtable) != 1);
4823  context.prettyFlags = prettyFlags;
4824  context.wrapColumn = wrapColumn;
4825  context.indentLevel = startIndent;
4826  context.special_exprkind = EXPR_KIND_NONE;
4827 
4828  set_deparse_for_query(&dpns, query, parentnamespace);
4829 
4830  switch (query->commandType)
4831  {
4832  case CMD_SELECT:
4833  get_select_query_def(query, &context, resultDesc);
4834  break;
4835 
4836  case CMD_UPDATE:
4837  get_update_query_def(query, &context);
4838  break;
4839 
4840  case CMD_INSERT:
4841  get_insert_query_def(query, &context);
4842  break;
4843 
4844  case CMD_DELETE:
4845  get_delete_query_def(query, &context);
4846  break;
4847 
4848  case CMD_NOTHING:
4849  appendStringInfoString(buf, "NOTHING");
4850  break;
4851 
4852  case CMD_UTILITY:
4853  get_utility_query_def(query, &context);
4854  break;
4855 
4856  default:
4857  elog(ERROR, "unrecognized query command type: %d",
4858  query->commandType);
4859  break;
4860  }
4861 }
List * namespaces
Definition: ruleutils.c:108
#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:5850
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6062
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:6308
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4979
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:66
void check_stack_depth(void)
Definition: postgres.c:3102
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:115
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6257
List * windowTList
Definition: ruleutils.c:110
CmdType commandType
Definition: parsenodes.h:110
List * lcons(void *datum, List *list)
Definition: list.c:259
List * windowClause
Definition: ruleutils.c:109
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:3300
StringInfo buf
Definition: ruleutils.c:107
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
static char * get_relation_name ( Oid  relid)
static

Definition at line 10360 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(), and pg_get_partkeydef_worker().

10361 {
10362  char *relname = get_rel_name(relid);
10363 
10364  if (!relname)
10365  elog(ERROR, "cache lookup failed for relation %u", relid);
10366  return relname;
10367 }
#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 4366 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().

4367 {
4369 
4370  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4371  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4372 }
List * namespaces
Definition: ruleutils.c:108
List * rtable_names
Definition: ruleutils.c:149
#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:675
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 7533 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, tupleDesc::attrs, BoolExpr::boolop, BooleanTest::booltesttype, buf, deparse_context::buf, 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(), 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_rule_expr_paren(), get_rule_expr_toplevel(), get_sublink_expr(), get_tablefunc(), get_variable(), get_windowfunc_expr(), i, InferenceElem::infercollid, InferenceElem::inferopclass, PartitionRangeDatum::infinite, 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, NULL, 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, 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_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, XmlExpr::type, type_is_rowtype(), SQLValueFunction::typmod, XmlExpr::typmod, PartitionBoundSpec::upperdatums, SubPlan::useHashTable, ScalarArrayOpExpr::useOr, val, PartitionRangeDatum::value, 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_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().

7535 {
7536  StringInfo buf = context->buf;
7537 
7538  if (node == NULL)
7539  return;
7540 
7541  /* Guard against excessively long or deeply-nested queries */
7544 
7545  /*
7546  * Each level of get_rule_expr must emit an indivisible term
7547  * (parenthesized if necessary) to ensure result is reparsed into the same
7548  * expression tree. The only exception is that when the input is a List,
7549  * we emit the component items comma-separated with no surrounding
7550  * decoration; this is convenient for most callers.
7551  */
7552  switch (nodeTag(node))
7553  {
7554  case T_Var:
7555  (void) get_variable((Var *) node, 0, false, context);
7556  break;
7557 
7558  case T_Const:
7559  get_const_expr((Const *) node, context, 0);
7560  break;
7561 
7562  case T_Param:
7563  get_parameter((Param *) node, context);
7564  break;
7565 
7566  case T_Aggref:
7567  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7568  break;
7569 
7570  case T_GroupingFunc:
7571  {
7572  GroupingFunc *gexpr = (GroupingFunc *) node;
7573 
7574  appendStringInfoString(buf, "GROUPING(");
7575  get_rule_expr((Node *) gexpr->args, context, true);
7576  appendStringInfoChar(buf, ')');
7577  }
7578  break;
7579 
7580  case T_WindowFunc:
7581  get_windowfunc_expr((WindowFunc *) node, context);
7582  break;
7583 
7584  case T_ArrayRef:
7585  {
7586  ArrayRef *aref = (ArrayRef *) node;
7587  bool need_parens;
7588 
7589  /*
7590  * If the argument is a CaseTestExpr, we must be inside a
7591  * FieldStore, ie, we are assigning to an element of an array
7592  * within a composite column. Since we already punted on
7593  * displaying the FieldStore's target information, just punt
7594  * here too, and display only the assignment source
7595  * expression.
7596  */
7597  if (IsA(aref->refexpr, CaseTestExpr))
7598  {
7599  Assert(aref->refassgnexpr);
7600  get_rule_expr((Node *) aref->refassgnexpr,
7601  context, showimplicit);
7602  break;
7603  }
7604 
7605  /*
7606  * Parenthesize the argument unless it's a simple Var or a
7607  * FieldSelect. (In particular, if it's another ArrayRef, we
7608  * *must* parenthesize to avoid confusion.)
7609  */
7610  need_parens = !IsA(aref->refexpr, Var) &&
7611  !IsA(aref->refexpr, FieldSelect);
7612  if (need_parens)
7613  appendStringInfoChar(buf, '(');
7614  get_rule_expr((Node *) aref->refexpr, context, showimplicit);
7615  if (need_parens)
7616  appendStringInfoChar(buf, ')');
7617 
7618  /*
7619  * If there's a refassgnexpr, we want to print the node in the
7620  * format "array[subscripts] := refassgnexpr". This is not
7621  * legal SQL, so decompilation of INSERT or UPDATE statements
7622  * should always use processIndirection as part of the
7623  * statement-level syntax. We should only see this when
7624  * EXPLAIN tries to print the targetlist of a plan resulting
7625  * from such a statement.
7626  */
7627  if (aref->refassgnexpr)
7628  {
7629  Node *refassgnexpr;
7630 
7631  /*
7632  * Use processIndirection to print this node's subscripts
7633  * as well as any additional field selections or
7634  * subscripting in immediate descendants. It returns the
7635  * RHS expr that is actually being "assigned".
7636  */
7637  refassgnexpr = processIndirection(node, context);
7638  appendStringInfoString(buf, " := ");
7639  get_rule_expr(refassgnexpr, context, showimplicit);
7640  }
7641  else
7642  {
7643  /* Just an ordinary array fetch, so print subscripts */
7644  printSubscripts(aref, context);
7645  }
7646  }
7647  break;
7648 
7649  case T_FuncExpr:
7650  get_func_expr((FuncExpr *) node, context, showimplicit);
7651  break;
7652 
7653  case T_NamedArgExpr:
7654  {
7655  NamedArgExpr *na = (NamedArgExpr *) node;
7656 
7657  appendStringInfo(buf, "%s => ", quote_identifier(na->name));
7658  get_rule_expr((Node *) na->arg, context, showimplicit);
7659  }
7660  break;
7661 
7662  case T_OpExpr:
7663  get_oper_expr((OpExpr *) node, context);
7664  break;
7665 
7666  case T_DistinctExpr:
7667  {
7668  DistinctExpr *expr = (DistinctExpr *) node;
7669  List *args = expr->args;
7670  Node *arg1 = (Node *) linitial(args);
7671  Node *arg2 = (Node *) lsecond(args);
7672 
7673  if (!PRETTY_PAREN(context))
7674  appendStringInfoChar(buf, '(');
7675  get_rule_expr_paren(arg1, context, true, node);
7676  appendStringInfoString(buf, " IS DISTINCT FROM ");
7677  get_rule_expr_paren(arg2, context, true, node);
7678  if (!PRETTY_PAREN(context))
7679  appendStringInfoChar(buf, ')');
7680  }
7681  break;
7682 
7683  case T_NullIfExpr: