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_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_partkeydef_worker (Oid relid, int prettyFlags)
 
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_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_partkeydef (PG_FUNCTION_ARGS)
 
Datum pg_get_constraintdef (PG_FUNCTION_ARGS)
 
Datum pg_get_constraintdef_ext (PG_FUNCTION_ARGS)
 
char * pg_get_constraintdef_command (Oid constraintId)
 
Datum pg_get_expr (PG_FUNCTION_ARGS)
 
Datum pg_get_expr_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_userbyid (PG_FUNCTION_ARGS)
 
Datum pg_get_serial_sequence (PG_FUNCTION_ARGS)
 
Datum pg_get_functiondef (PG_FUNCTION_ARGS)
 
Datum pg_get_function_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_identity_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_result (PG_FUNCTION_ARGS)
 
static bool is_input_argument (int nth, const char *argmodes)
 
Datum pg_get_function_arg_default (PG_FUNCTION_ARGS)
 
char * deparse_expression (Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
 
Listdeparse_context_for (const char *aliasname, Oid relid)
 
Listdeparse_context_for_plan_rtable (List *rtable, List *rtable_names)
 
Listset_deparse_context_planstate (List *dpcontext, Node *planstate, List *ancestors)
 
Listselect_rtable_names_for_explain (List *rtable, Bitmapset *rels_used)
 
static RangeTblEntryget_simple_values_rte (Query *query)
 
static const char * get_name_for_var_field (Var *var, int fieldno, int levelsup, deparse_context *context)
 
static void get_rule_expr_paren (Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
 
const char * quote_identifier (const char *ident)
 
char * quote_qualified_identifier (const char *qualifier, const char *ident)
 
char * generate_collation_name (Oid collid)
 

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 457 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 81 of file ruleutils.c.

Referenced by get_from_clause_item().

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 84 of file ruleutils.c.

Referenced by appendContextKeyword().

#define PRETTYINDENT_VAR   4

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

7267 {
7268  StringInfo buf = context->buf;
7269 
7270  if (PRETTY_INDENT(context))
7271  {
7272  int indentAmount;
7273 
7274  context->indentLevel += indentBefore;
7275 
7276  /* remove any trailing spaces currently in the buffer ... */
7278  /* ... then add a newline and some spaces */
7279  appendStringInfoChar(buf, '\n');
7280 
7281  if (context->indentLevel < PRETTYINDENT_LIMIT)
7282  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7283  else
7284  {
7285  /*
7286  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7287  * to conserve horizontal space by reducing the per-level
7288  * indentation. For best results the scale factor here should
7289  * divide all the indent amounts that get added to indentLevel
7290  * (PRETTYINDENT_STD, etc). It's important that the indentation
7291  * not grow unboundedly, else deeply-nested trees use O(N^2)
7292  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7293  */
7294  indentAmount = PRETTYINDENT_LIMIT +
7295  (context->indentLevel - PRETTYINDENT_LIMIT) /
7296  (PRETTYINDENT_STD / 2);
7297  indentAmount %= PRETTYINDENT_LIMIT;
7298  /* scale/wrap logic affects indentLevel, but not indentPlus */
7299  indentAmount += indentPlus;
7300  }
7301  appendStringInfoSpaces(buf, indentAmount);
7302 
7303  appendStringInfoString(buf, str);
7304 
7305  context->indentLevel += indentAfter;
7306  if (context->indentLevel < 0)
7307  context->indentLevel = 0;
7308  }
7309  else
7310  appendStringInfoString(buf, str);
7311 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7319
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
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:84
#define Max(x, y)
Definition: c.h:795
StringInfo buf
Definition: ruleutils.c:106
static bool colname_is_unique ( char *  colname,
deparse_namespace dpns,
deparse_columns colinfo 
)
static

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

3912 {
3913  int i;
3914  ListCell *lc;
3915 
3916  /* Check against already-assigned column aliases within RTE */
3917  for (i = 0; i < colinfo->num_cols; i++)
3918  {
3919  char *oldname = colinfo->colnames[i];
3920 
3921  if (oldname && strcmp(oldname, colname) == 0)
3922  return false;
3923  }
3924 
3925  /*
3926  * If we're building a new_colnames array, check that too (this will be
3927  * partially but not completely redundant with the previous checks)
3928  */
3929  for (i = 0; i < colinfo->num_new_cols; i++)
3930  {
3931  char *oldname = colinfo->new_colnames[i];
3932 
3933  if (oldname && strcmp(oldname, colname) == 0)
3934  return false;
3935  }
3936 
3937  /* Also check against USING-column names that must be globally unique */
3938  foreach(lc, dpns->using_names)
3939  {
3940  char *oldname = (char *) lfirst(lc);
3941 
3942  if (strcmp(oldname, colname) == 0)
3943  return false;
3944  }
3945 
3946  /* Also check against names already assigned for parent-join USING cols */
3947  foreach(lc, colinfo->parentUsing)
3948  {
3949  char *oldname = (char *) lfirst(lc);
3950 
3951  if (strcmp(oldname, colname) == 0)
3952  return false;
3953  }
3954 
3955  return true;
3956 }
List * using_names
Definition: ruleutils.c:153
#define lfirst(lc)
Definition: pg_list.h:106
int i
List * parentUsing
Definition: ruleutils.c:247
char ** new_colnames
Definition: ruleutils.c:240
char ** colnames
Definition: ruleutils.c:223
static void decompile_column_index_array ( Datum  column_index_array,
Oid  relId,
StringInfo  buf 
)
static

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

1976 {
1977  Datum *keys;
1978  int nKeys;
1979  int j;
1980 
1981  /* Extract data from array of int16 */
1982  deconstruct_array(DatumGetArrayTypeP(column_index_array),
1983  INT2OID, 2, true, 's',
1984  &keys, NULL, &nKeys);
1985 
1986  for (j = 0; j < nKeys; j++)
1987  {
1988  char *colName;
1989 
1990  colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1991 
1992  if (j == 0)
1994  else
1995  appendStringInfo(buf, ", %s", quote_identifier(colName));
1996  }
1997 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
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:452
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
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 2856 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().

2857 {
2858  deparse_namespace *dpns;
2859  RangeTblEntry *rte;
2860 
2861  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2862 
2863  /* Build a minimal RTE for the rel */
2864  rte = makeNode(RangeTblEntry);
2865  rte->rtekind = RTE_RELATION;
2866  rte->relid = relid;
2867  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
2868  rte->alias = makeAlias(aliasname, NIL);
2869  rte->eref = rte->alias;
2870  rte->lateral = false;
2871  rte->inh = false;
2872  rte->inFromCl = true;
2873 
2874  /* Build one-element rtable */
2875  dpns->rtable = list_make1(rte);
2876  dpns->ctes = NIL;
2877  set_rtable_names(dpns, NIL, NULL);
2879 
2880  /* Return a one-deep namespace stack */
2881  return list_make1(dpns);
2882 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:960
#define list_make1(x1)
Definition: pg_list.h:133
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:3000
void * palloc0(Size size)
Definition: mcxt.c:920
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3213
RTEKind rtekind
Definition: parsenodes.h:882
Alias * eref
Definition: parsenodes.h:961
#define RELKIND_RELATION
Definition: pg_class.h:160
List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

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

2899 {
2900  deparse_namespace *dpns;
2901 
2902  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2903 
2904  /* Initialize fields that stay the same across the whole plan tree */
2905  dpns->rtable = rtable;
2906  dpns->rtable_names = rtable_names;
2907  dpns->ctes = NIL;
2908 
2909  /*
2910  * Set up column name aliases. We will get rather bogus results for join
2911  * RTEs, but that doesn't matter because plan trees don't contain any join
2912  * alias Vars.
2913  */
2915 
2916  /* Return a one-deep namespace stack */
2917  return list_make1(dpns);
2918 }
#define NIL
Definition: pg_list.h:69
List * rtable_names
Definition: ruleutils.c:148
#define list_make1(x1)
Definition: pg_list.h:133
void * palloc0(Size size)
Definition: mcxt.c:920
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3213
char* deparse_expression ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit 
)

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

2799 {
2800  return deparse_expression_pretty(expr, dpcontext, forceprefix,
2801  showimplicit, 0, 0);
2802 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:2824
static char * deparse_expression_pretty ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit,
int  prettyFlags,
int  startIndent 
)
static

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

2827 {
2829  deparse_context context;
2830 
2831  initStringInfo(&buf);
2832  context.buf = &buf;
2833  context.namespaces = dpcontext;
2834  context.windowClause = NIL;
2835  context.windowTList = NIL;
2836  context.varprefix = forceprefix;
2837  context.prettyFlags = prettyFlags;
2838  context.wrapColumn = WRAP_COLUMN_DEFAULT;
2839  context.indentLevel = startIndent;
2840  context.special_exprkind = EXPR_KIND_NONE;
2841 
2842  get_rule_expr(expr, &context, showimplicit);
2843 
2844  return buf.data;
2845 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:91
static char * buf
Definition: pg_test_fsync.c:65
ParseExprKind special_exprkind
Definition: ruleutils.c:114
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
List * windowTList
Definition: ruleutils.c:109
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
List * windowClause
Definition: ruleutils.c:108
StringInfo buf
Definition: ruleutils.c:106
static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

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

4009 {
4010  if (n > colinfo->num_cols)
4011  {
4012  if (colinfo->colnames == NULL)
4013  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4014  else
4015  {
4016  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4017  n * sizeof(char *));
4018  memset(colinfo->colnames + colinfo->num_cols, 0,
4019  (n - colinfo->num_cols) * sizeof(char *));
4020  }
4021  colinfo->num_cols = n;
4022  }
4023 }
void * palloc0(Size size)
Definition: mcxt.c:920
#define NULL
Definition: c.h:226
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
char ** colnames
Definition: ruleutils.c:223
static Node * find_param_referent ( Param param,
deparse_context context,
deparse_namespace **  dpns_p,
ListCell **  ancestor_cell_p 
)
static

Definition at line 6840 of file ruleutils.c.

References deparse_namespace::ancestors, arg, SubPlan::args, Assert, ExprState::expr, 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, PlanState::subPlan, and SubPlanState::xprstate.

Referenced by get_name_for_var_field(), and get_parameter().

6842 {
6843  /* Initialize output parameters to prevent compiler warnings */
6844  *dpns_p = NULL;
6845  *ancestor_cell_p = NULL;
6846 
6847  /*
6848  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
6849  * SubPlan argument. This will necessarily be in some ancestor of the
6850  * current expression's PlanState.
6851  */
6852  if (param->paramkind == PARAM_EXEC)
6853  {
6854  deparse_namespace *dpns;
6855  PlanState *child_ps;
6856  bool in_same_plan_level;
6857  ListCell *lc;
6858 
6859  dpns = (deparse_namespace *) linitial(context->namespaces);
6860  child_ps = dpns->planstate;
6861  in_same_plan_level = true;
6862 
6863  foreach(lc, dpns->ancestors)
6864  {
6865  PlanState *ps = (PlanState *) lfirst(lc);
6866  ListCell *lc2;
6867 
6868  /*
6869  * NestLoops transmit params to their inner child only; also, once
6870  * we've crawled up out of a subplan, this couldn't possibly be
6871  * the right match.
6872  */
6873  if (IsA(ps, NestLoopState) &&
6874  child_ps == innerPlanState(ps) &&
6875  in_same_plan_level)
6876  {
6877  NestLoop *nl = (NestLoop *) ps->plan;
6878 
6879  foreach(lc2, nl->nestParams)
6880  {
6881  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
6882 
6883  if (nlp->paramno == param->paramid)
6884  {
6885  /* Found a match, so return it */
6886  *dpns_p = dpns;
6887  *ancestor_cell_p = lc;
6888  return (Node *) nlp->paramval;
6889  }
6890  }
6891  }
6892 
6893  /*
6894  * Check to see if we're crawling up from a subplan.
6895  */
6896  foreach(lc2, ps->subPlan)
6897  {
6898  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6899  SubPlan *subplan = (SubPlan *) sstate->xprstate.expr;
6900  ListCell *lc3;
6901  ListCell *lc4;
6902 
6903  if (child_ps != sstate->planstate)
6904  continue;
6905 
6906  /* Matched subplan, so check its arguments */
6907  forboth(lc3, subplan->parParam, lc4, subplan->args)
6908  {
6909  int paramid = lfirst_int(lc3);
6910  Node *arg = (Node *) lfirst(lc4);
6911 
6912  if (paramid == param->paramid)
6913  {
6914  /* Found a match, so return it */
6915  *dpns_p = dpns;
6916  *ancestor_cell_p = lc;
6917  return arg;
6918  }
6919  }
6920 
6921  /* Keep looking, but we are emerging from a subplan. */
6922  in_same_plan_level = false;
6923  break;
6924  }
6925 
6926  /*
6927  * Likewise check to see if we're emerging from an initplan.
6928  * Initplans never have any parParams, so no need to search that
6929  * list, but we need to know if we should reset
6930  * in_same_plan_level.
6931  */
6932  foreach(lc2, ps->initPlan)
6933  {
6934  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6935 
6936  if (child_ps != sstate->planstate)
6937  continue;
6938 
6939  /* No parameters to be had here. */
6940  Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL);
6941 
6942  /* Keep looking, but we are emerging from an initplan. */
6943  in_same_plan_level = false;
6944  break;
6945  }
6946 
6947  /* No luck, crawl up to next ancestor */
6948  child_ps = ps;
6949  }
6950  }
6951 
6952  /* No referent found */
6953  return NULL;
6954 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
List * nestParams
Definition: plannodes.h:637
ExprState xprstate
Definition: execnodes.h:784
List * initPlan
Definition: execnodes.h:1064
List * subPlan
Definition: execnodes.h:1066
ParamKind paramkind
Definition: primnodes.h:222
Definition: nodes.h:508
Var * paramval
Definition: plannodes.h:644
#define linitial(l)
Definition: pg_list.h:110
struct PlanState * planstate
Definition: execnodes.h:785
Expr * expr
Definition: execnodes.h:597
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:1046
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:223
List * parParam
Definition: primnodes.h:685
PlanState * planstate
Definition: ruleutils.c:155
void * arg
#define innerPlanState(node)
Definition: execnodes.h:1088
List * args
Definition: primnodes.h:686
static void flatten_join_using_qual ( Node qual,
List **  leftvars,
List **  rightvars 
)
static

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

4160 {
4161  if (IsA(qual, BoolExpr))
4162  {
4163  /* Handle AND nodes by recursion */
4164  BoolExpr *b = (BoolExpr *) qual;
4165  ListCell *lc;
4166 
4167  Assert(b->boolop == AND_EXPR);
4168  foreach(lc, b->args)
4169  {
4171  leftvars, rightvars);
4172  }
4173  }
4174  else if (IsA(qual, OpExpr))
4175  {
4176  /* Otherwise we should have an equality operator */
4177  OpExpr *op = (OpExpr *) qual;
4178  Var *var;
4179 
4180  if (list_length(op->args) != 2)
4181  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4182  /* Arguments should be Vars with perhaps implicit coercions */
4183  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4184  if (!IsA(var, Var))
4185  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4186  (int) nodeTag(var));
4187  *leftvars = lappend(*leftvars, var);
4188  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4189  if (!IsA(var, Var))
4190  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4191  (int) nodeTag(var));
4192  *rightvars = lappend(*rightvars, var);
4193  }
4194  else
4195  {
4196  /* Perhaps we have an implicit coercion to boolean? */
4197  Node *q = strip_implicit_coercions(qual);
4198 
4199  if (q != qual)
4200  flatten_join_using_qual(q, leftvars, rightvars);
4201  else
4202  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4203  (int) nodeTag(qual));
4204  }
4205 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Definition: nodes.h:508
Definition: primnodes.h:141
#define lsecond(l)
Definition: pg_list.h:114
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:539
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:4159
#define Assert(condition)
Definition: c.h:670
#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:540
#define nodeTag(nodeptr)
Definition: nodes.h:513
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:479
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612
static char * flatten_reloptions ( Oid  relid)
static

Definition at line 10428 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, SearchSysCache1, simple_quote_literal(), SysCacheGetAttr(), TextDatumGetCString, TEXTOID, and value.

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

10429 {
10430  char *result = NULL;
10431  HeapTuple tuple;
10432  Datum reloptions;
10433  bool isnull;
10434 
10435  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10436  if (!HeapTupleIsValid(tuple))
10437  elog(ERROR, "cache lookup failed for relation %u", relid);
10438 
10439  reloptions = SysCacheGetAttr(RELOID, tuple,
10440  Anum_pg_class_reloptions, &isnull);
10441  if (!isnull)
10442  {
10444  Datum *options;
10445  int noptions;
10446  int i;
10447 
10448  initStringInfo(&buf);
10449 
10451  TEXTOID, -1, false, 'i',
10452  &options, NULL, &noptions);
10453 
10454  for (i = 0; i < noptions; i++)
10455  {
10456  char *option = TextDatumGetCString(options[i]);
10457  char *name;
10458  char *separator;
10459  char *value;
10460 
10461  /*
10462  * Each array element should have the form name=value. If the "="
10463  * is missing for some reason, treat it like an empty value.
10464  */
10465  name = option;
10466  separator = strchr(option, '=');
10467  if (separator)
10468  {
10469  *separator = '\0';
10470  value = separator + 1;
10471  }
10472  else
10473  value = "";
10474 
10475  if (i > 0)
10476  appendStringInfoString(&buf, ", ");
10477  appendStringInfo(&buf, "%s=", quote_identifier(name));
10478 
10479  /*
10480  * In general we need to quote the value; but to avoid unnecessary
10481  * clutter, do not quote if it is an identifier that would not
10482  * need quoting. (We could also allow numbers, but that is a bit
10483  * trickier than it looks --- for example, are leading zeroes
10484  * significant? We don't want to assume very much here about what
10485  * custom reloptions might mean.)
10486  */
10487  if (quote_identifier(value) == value)
10488  appendStringInfoString(&buf, value);
10489  else
10490  simple_quote_literal(&buf, value);
10491 
10492  pfree(option);
10493  }
10494 
10495  result = buf.data;
10496  }
10497 
10498  ReleaseSysCache(tuple);
10499 
10500  return result;
10501 }
static struct @76 value
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
#define TEXTOID
Definition: pg_type.h:324
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
void pfree(void *pointer)
Definition: mcxt.c:992
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9140
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1245
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
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 size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:242
char* generate_collation_name ( Oid  collid)

Definition at line 10383 of file ruleutils.c.

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

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

10384 {
10385  HeapTuple tp;
10386  Form_pg_collation colltup;
10387  char *collname;
10388  char *nspname;
10389  char *result;
10390 
10391  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
10392  if (!HeapTupleIsValid(tp))
10393  elog(ERROR, "cache lookup failed for collation %u", collid);
10394  colltup = (Form_pg_collation) GETSTRUCT(tp);
10395  collname = NameStr(colltup->collname);
10396 
10397  if (!CollationIsVisible(collid))
10398  nspname = get_namespace_name(colltup->collnamespace);
10399  else
10400  nspname = NULL;
10401 
10402  result = quote_qualified_identifier(nspname, collname);
10403 
10404  ReleaseSysCache(tp);
10405 
10406  return result;
10407 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
bool CollationIsVisible(Oid collid)
Definition: namespace.c:1965
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10061
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
#define NameStr(name)
Definition: c.h:494
#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 10203 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(), and SearchSysCache1.

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

10206 {
10207  char *result;
10208  HeapTuple proctup;
10209  Form_pg_proc procform;
10210  char *proname;
10211  bool use_variadic;
10212  char *nspname;
10213  FuncDetailCode p_result;
10214  Oid p_funcid;
10215  Oid p_rettype;
10216  bool p_retset;
10217  int p_nvargs;
10218  Oid p_vatype;
10219  Oid *p_true_typeids;
10220  bool force_qualify = false;
10221 
10222  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10223  if (!HeapTupleIsValid(proctup))
10224  elog(ERROR, "cache lookup failed for function %u", funcid);
10225  procform = (Form_pg_proc) GETSTRUCT(proctup);
10226  proname = NameStr(procform->proname);
10227 
10228  /*
10229  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10230  * qualification in some special cases.
10231  */
10232  if (special_exprkind == EXPR_KIND_GROUP_BY)
10233  {
10234  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10235  force_qualify = true;
10236  }
10237 
10238  /*
10239  * Determine whether VARIADIC should be printed. We must do this first
10240  * since it affects the lookup rules in func_get_detail().
10241  *
10242  * Currently, we always print VARIADIC if the function has a merged
10243  * variadic-array argument. Note that this is always the case for
10244  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10245  *
10246  * In principle, if VARIADIC wasn't originally specified and the array
10247  * actual argument is deconstructable, we could print the array elements
10248  * separately and not print VARIADIC, thus more nearly reproducing the
10249  * original input. For the moment that seems like too much complication
10250  * for the benefit, and anyway we do not know whether VARIADIC was
10251  * originally specified if it's a non-ANY type.
10252  */
10253  if (use_variadic_p)
10254  {
10255  /* Parser should not have set funcvariadic unless fn is variadic */
10256  Assert(!has_variadic || OidIsValid(procform->provariadic));
10257  use_variadic = has_variadic;
10258  *use_variadic_p = use_variadic;
10259  }
10260  else
10261  {
10262  Assert(!has_variadic);
10263  use_variadic = false;
10264  }
10265 
10266  /*
10267  * The idea here is to schema-qualify only if the parser would fail to
10268  * resolve the correct function given the unqualified func name with the
10269  * specified argtypes and VARIADIC flag. But if we already decided to
10270  * force qualification, then we can skip the lookup and pretend we didn't
10271  * find it.
10272  */
10273  if (!force_qualify)
10274  p_result = func_get_detail(list_make1(makeString(proname)),
10275  NIL, argnames, nargs, argtypes,
10276  !use_variadic, true,
10277  &p_funcid, &p_rettype,
10278  &p_retset, &p_nvargs, &p_vatype,
10279  &p_true_typeids, NULL);
10280  else
10281  {
10282  p_result = FUNCDETAIL_NOTFOUND;
10283  p_funcid = InvalidOid;
10284  }
10285 
10286  if ((p_result == FUNCDETAIL_NORMAL ||
10287  p_result == FUNCDETAIL_AGGREGATE ||
10288  p_result == FUNCDETAIL_WINDOWFUNC) &&
10289  p_funcid == funcid)
10290  nspname = NULL;
10291  else
10292  nspname = get_namespace_name(procform->pronamespace);
10293 
10294  result = quote_qualified_identifier(nspname, proname);
10295 
10296  ReleaseSysCache(proctup);
10297 
10298  return result;
10299 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define list_make1(x1)
Definition: pg_list.h:133
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10061
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
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:226
#define Assert(condition)
Definition: c.h:670
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:494
#define elog
Definition: elog.h:219
static char * generate_operator_name ( Oid  operid,
Oid  arg1,
Oid  arg2 
)
static

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

10314 {
10316  HeapTuple opertup;
10317  Form_pg_operator operform;
10318  char *oprname;
10319  char *nspname;
10320  Operator p_result;
10321 
10322  initStringInfo(&buf);
10323 
10324  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10325  if (!HeapTupleIsValid(opertup))
10326  elog(ERROR, "cache lookup failed for operator %u", operid);
10327  operform = (Form_pg_operator) GETSTRUCT(opertup);
10328  oprname = NameStr(operform->oprname);
10329 
10330  /*
10331  * The idea here is to schema-qualify only if the parser would fail to
10332  * resolve the correct operator given the unqualified op name with the
10333  * specified argtypes.
10334  */
10335  switch (operform->oprkind)
10336  {
10337  case 'b':
10338  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10339  true, -1);
10340  break;
10341  case 'l':
10342  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10343  true, -1);
10344  break;
10345  case 'r':
10346  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10347  true, -1);
10348  break;
10349  default:
10350  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10351  p_result = NULL; /* keep compiler quiet */
10352  break;
10353  }
10354 
10355  if (p_result != NULL && oprid(p_result) == operid)
10356  nspname = NULL;
10357  else
10358  {
10359  nspname = get_namespace_name(operform->oprnamespace);
10360  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10361  }
10362 
10363  appendStringInfoString(&buf, oprname);
10364 
10365  if (nspname)
10366  appendStringInfoChar(&buf, ')');
10367 
10368  if (p_result != NULL)
10369  ReleaseSysCache(p_result);
10370 
10371  ReleaseSysCache(opertup);
10372 
10373  return buf.data;
10374 }
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:9975
Oid oprid(Operator op)
Definition: parse_oper.c:243
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define list_make1(x1)
Definition: pg_list.h:133
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:602
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:523
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
static char * buf
Definition: pg_test_fsync.c:65
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:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:219
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:375
static char * generate_qualified_relation_name ( Oid  relid)
static

Definition at line 10161 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_serial_sequence().

10162 {
10163  HeapTuple tp;
10164  Form_pg_class reltup;
10165  char *relname;
10166  char *nspname;
10167  char *result;
10168 
10169  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10170  if (!HeapTupleIsValid(tp))
10171  elog(ERROR, "cache lookup failed for relation %u", relid);
10172  reltup = (Form_pg_class) GETSTRUCT(tp);
10173  relname = NameStr(reltup->relname);
10174 
10175  nspname = get_namespace_name(reltup->relnamespace);
10176  if (!nspname)
10177  elog(ERROR, "cache lookup failed for namespace %u",
10178  reltup->relnamespace);
10179 
10180  result = quote_qualified_identifier(nspname, relname);
10181 
10182  ReleaseSysCache(tp);
10183 
10184  return result;
10185 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10061
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:219
static char * generate_relation_name ( Oid  relid,
List namespaces 
)
static

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

10102 {
10103  HeapTuple tp;
10104  Form_pg_class reltup;
10105  bool need_qual;
10106  ListCell *nslist;
10107  char *relname;
10108  char *nspname;
10109  char *result;
10110 
10111  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10112  if (!HeapTupleIsValid(tp))
10113  elog(ERROR, "cache lookup failed for relation %u", relid);
10114  reltup = (Form_pg_class) GETSTRUCT(tp);
10115  relname = NameStr(reltup->relname);
10116 
10117  /* Check for conflicting CTE name */
10118  need_qual = false;
10119  foreach(nslist, namespaces)
10120  {
10121  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10122  ListCell *ctlist;
10123 
10124  foreach(ctlist, dpns->ctes)
10125  {
10126  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10127 
10128  if (strcmp(cte->ctename, relname) == 0)
10129  {
10130  need_qual = true;
10131  break;
10132  }
10133  }
10134  if (need_qual)
10135  break;
10136  }
10137 
10138  /* Otherwise, qualify the name if not visible in search path */
10139  if (!need_qual)
10140  need_qual = !RelationIsVisible(relid);
10141 
10142  if (need_qual)
10143  nspname = get_namespace_name(reltup->relnamespace);
10144  else
10145  nspname = NULL;
10146 
10147  result = quote_qualified_identifier(nspname, relname);
10148 
10149  ReleaseSysCache(tp);
10150 
10151  return result;
10152 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10061
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#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:494
#define elog
Definition: elog.h:219
static void get_agg_combine_expr ( Node node,
deparse_context context,
void *  private 
)
static

Definition at line 8836 of file ruleutils.c.

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

Referenced by get_agg_expr().

8837 {
8838  Aggref *aggref;
8839  Aggref *original_aggref = private;
8840 
8841  if (!IsA(node, Aggref))
8842  elog(ERROR, "combining Aggref does not point to an Aggref");
8843 
8844  aggref = (Aggref *) node;
8845  get_agg_expr(aggref, context, original_aggref);
8846 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:8729
#define elog
Definition: elog.h:219
static void get_agg_expr ( Aggref aggref,
deparse_context context,
Aggref original_aggref 
)
static

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

Referenced by get_agg_combine_expr(), and get_rule_expr().

8731 {
8732  StringInfo buf = context->buf;
8733  Oid argtypes[FUNC_MAX_ARGS];
8734  int nargs;
8735  bool use_variadic;
8736 
8737  /*
8738  * For a combining aggregate, we look up and deparse the corresponding
8739  * partial aggregate instead. This is necessary because our input
8740  * argument list has been replaced; the new argument list always has just
8741  * one element, which will point to a partial Aggref that supplies us with
8742  * transition states to combine.
8743  */
8744  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
8745  {
8746  TargetEntry *tle = linitial(aggref->args);
8747 
8748  Assert(list_length(aggref->args) == 1);
8749  Assert(IsA(tle, TargetEntry));
8750  resolve_special_varno((Node *) tle->expr, context, original_aggref,
8752  return;
8753  }
8754 
8755  /*
8756  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
8757  * to avoid printing this when recursing from the code just above.
8758  */
8759  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
8760  appendStringInfoString(buf, "PARTIAL ");
8761 
8762  /* Extract the argument types as seen by the parser */
8763  nargs = get_aggregate_argtypes(aggref, argtypes);
8764 
8765  /* Print the aggregate name, schema-qualified if needed */
8766  appendStringInfo(buf, "%s(%s",
8767  generate_function_name(aggref->aggfnoid, nargs,
8768  NIL, argtypes,
8769  aggref->aggvariadic,
8770  &use_variadic,
8771  context->special_exprkind),
8772  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
8773 
8774  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
8775  {
8776  /*
8777  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
8778  * worry about inserting VARIADIC. So we can just dump the direct
8779  * args as-is.
8780  */
8781  Assert(!aggref->aggvariadic);
8782  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
8783  Assert(aggref->aggorder != NIL);
8784  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
8785  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8786  }
8787  else
8788  {
8789  /* aggstar can be set only in zero-argument aggregates */
8790  if (aggref->aggstar)
8791  appendStringInfoChar(buf, '*');
8792  else
8793  {
8794  ListCell *l;
8795  int i;
8796 
8797  i = 0;
8798  foreach(l, aggref->args)
8799  {
8800  TargetEntry *tle = (TargetEntry *) lfirst(l);
8801  Node *arg = (Node *) tle->expr;
8802 
8803  Assert(!IsA(arg, NamedArgExpr));
8804  if (tle->resjunk)
8805  continue;
8806  if (i++ > 0)
8807  appendStringInfoString(buf, ", ");
8808  if (use_variadic && i == nargs)
8809  appendStringInfoString(buf, "VARIADIC ");
8810  get_rule_expr(arg, context, true);
8811  }
8812  }
8813 
8814  if (aggref->aggorder != NIL)
8815  {
8816  appendStringInfoString(buf, " ORDER BY ");
8817  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8818  }
8819  }
8820 
8821  if (aggref->aggfilter != NULL)
8822  {
8823  appendStringInfoString(buf, ") FILTER (WHERE ");
8824  get_rule_expr((Node *) aggref->aggfilter, context, false);
8825  }
8826 
8827  appendStringInfoChar(buf, ')');
8828 }
List * aggdistinct
Definition: primnodes.h:281
#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:10203
bool aggvariadic
Definition: primnodes.h:284
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6375
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5506
Definition: nodes.h:508
List * args
Definition: primnodes.h:279
bool aggstar
Definition: primnodes.h:283
unsigned int Oid
Definition: postgres_ext.h:31
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:759
#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:1337
#define linitial(l)
Definition: pg_list.h:110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
List * aggorder
Definition: primnodes.h:280
List * aggdirectargs
Definition: primnodes.h:278
ParseExprKind special_exprkind
Definition: ruleutils.c:114
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
Oid aggfnoid
Definition: primnodes.h:272
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:8836
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
AggSplit aggsplit
Definition: primnodes.h:288
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:760
Expr * aggfilter
Definition: primnodes.h:282
StringInfo buf
Definition: ruleutils.c:106
int i
void * arg
char aggkind
Definition: primnodes.h:286
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 4999 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().

5001 {
5002  StringInfo buf = context->buf;
5003  RangeTblEntry *values_rte;
5004  char *sep;
5005  ListCell *l;
5006 
5007  if (PRETTY_INDENT(context))
5008  {
5009  context->indentLevel += PRETTYINDENT_STD;
5010  appendStringInfoChar(buf, ' ');
5011  }
5012 
5013  /*
5014  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5015  * VALUES part. This reverses what transformValuesClause() did at parse
5016  * time.
5017  */
5018  values_rte = get_simple_values_rte(query);
5019  if (values_rte)
5020  {
5021  get_values_def(values_rte->values_lists, context);
5022  return;
5023  }
5024 
5025  /*
5026  * Build up the query string - first we say SELECT
5027  */
5028  appendStringInfoString(buf, "SELECT");
5029 
5030  /* Add the DISTINCT clause if given */
5031  if (query->distinctClause != NIL)
5032  {
5033  if (query->hasDistinctOn)
5034  {
5035  appendStringInfoString(buf, " DISTINCT ON (");
5036  sep = "";
5037  foreach(l, query->distinctClause)
5038  {
5039  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5040 
5041  appendStringInfoString(buf, sep);
5043  false, context);
5044  sep = ", ";
5045  }
5046  appendStringInfoChar(buf, ')');
5047  }
5048  else
5049  appendStringInfoString(buf, " DISTINCT");
5050  }
5051 
5052  /* Then we tell what to select (the targetlist) */
5053  get_target_list(query->targetList, context, resultDesc);
5054 
5055  /* Add the FROM clause if needed */
5056  get_from_clause(query, " FROM ", context);
5057 
5058  /* Add the WHERE clause if given */
5059  if (query->jointree->quals != NULL)
5060  {
5061  appendContextKeyword(context, " WHERE ",
5063  get_rule_expr(query->jointree->quals, context, false);
5064  }
5065 
5066  /* Add the GROUP BY clause if given */
5067  if (query->groupClause != NULL || query->groupingSets != NULL)
5068  {
5069  ParseExprKind save_exprkind;
5070 
5071  appendContextKeyword(context, " GROUP BY ",
5073 
5074  save_exprkind = context->special_exprkind;
5076 
5077  if (query->groupingSets == NIL)
5078  {
5079  sep = "";
5080  foreach(l, query->groupClause)
5081  {
5082  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5083 
5084  appendStringInfoString(buf, sep);
5086  false, context);
5087  sep = ", ";
5088  }
5089  }
5090  else
5091  {
5092  sep = "";
5093  foreach(l, query->groupingSets)
5094  {
5095  GroupingSet *grp = lfirst(l);
5096 
5097  appendStringInfoString(buf, sep);
5098  get_rule_groupingset(grp, query->targetList, true, context);
5099  sep = ", ";
5100  }
5101  }
5102 
5103  context->special_exprkind = save_exprkind;
5104  }
5105 
5106  /* Add the HAVING clause if given */
5107  if (query->havingQual != NULL)
5108  {
5109  appendContextKeyword(context, " HAVING ",
5111  get_rule_expr(query->havingQual, context, false);
5112  }
5113 
5114  /* Add the WINDOW clause if needed */
5115  if (query->windowClause != NIL)
5116  get_rule_windowclause(query, context);
5117 }
#define NIL
Definition: pg_list.h:69
FromExpr * jointree
Definition: parsenodes.h:129
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5126
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5390
Index tleSortGroupRef
Definition: parsenodes.h:1102
List * groupingSets
Definition: parsenodes.h:139
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9297
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5564
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
ParseExprKind
Definition: parse_node.h:32
List * values_lists
Definition: parsenodes.h:937
Node * quals
Definition: primnodes.h:1434
bool hasDistinctOn
Definition: parsenodes.h:120
List * windowClause
Definition: parsenodes.h:143
List * targetList
Definition: parsenodes.h:131
List * distinctClause
Definition: parsenodes.h:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7265
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5446
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
ParseExprKind special_exprkind
Definition: ruleutils.c:114
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
#define NULL
Definition: c.h:226
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4715
List * groupClause
Definition: parsenodes.h:137
StringInfo buf
Definition: ruleutils.c:106
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:4943
Node * havingQual
Definition: parsenodes.h:141
static void get_coercion_expr ( Node arg,
deparse_context context,
Oid  resulttype,
int32  resulttypmod,
Node parentNode 
)
static

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

8932 {
8933  StringInfo buf = context->buf;
8934 
8935  /*
8936  * Since parse_coerce.c doesn't immediately collapse application of
8937  * length-coercion functions to constants, what we'll typically see in
8938  * such cases is a Const with typmod -1 and a length-coercion function
8939  * right above it. Avoid generating redundant output. However, beware of
8940  * suppressing casts when the user actually wrote something like
8941  * 'foo'::text::char(3).
8942  *
8943  * Note: it might seem that we are missing the possibility of needing to
8944  * print a COLLATE clause for such a Const. However, a Const could only
8945  * have nondefault collation in a post-constant-folding tree, in which the
8946  * length coercion would have been folded too. See also the special
8947  * handling of CollateExpr in coerce_to_target_type(): any collation
8948  * marking will be above the coercion node, not below it.
8949  */
8950  if (arg && IsA(arg, Const) &&
8951  ((Const *) arg)->consttype == resulttype &&
8952  ((Const *) arg)->consttypmod == -1)
8953  {
8954  /* Show the constant without normal ::typename decoration */
8955  get_const_expr((Const *) arg, context, -1);
8956  }
8957  else
8958  {
8959  if (!PRETTY_PAREN(context))
8960  appendStringInfoChar(buf, '(');
8961  get_rule_expr_paren(arg, context, false, parentNode);
8962  if (!PRETTY_PAREN(context))
8963  appendStringInfoChar(buf, ')');
8964  }
8965  appendStringInfo(buf, "::%s",
8966  format_type_with_typemod(resulttype, resulttypmod));
8967 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7338
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:8985
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static char * buf
Definition: pg_test_fsync.c:65
#define PRETTY_PAREN(context)
Definition: ruleutils.c:94
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:106
static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

9711 {
9712  StringInfo buf = context->buf;
9713  int i;
9714  bool first = true;
9715 
9716  /* Don't print aliases if not needed */
9717  if (!colinfo->printaliases)
9718  return;
9719 
9720  for (i = 0; i < colinfo->num_new_cols; i++)
9721  {
9722  char *colname = colinfo->new_colnames[i];
9723 
9724  if (first)
9725  {
9726  appendStringInfoChar(buf, '(');
9727  first = false;
9728  }
9729  else
9730  appendStringInfoString(buf, ", ");
9732  }
9733  if (!first)
9734  appendStringInfoChar(buf, ')');
9735 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
StringInfo buf
Definition: ruleutils.c:106
int i
char ** new_colnames
Definition: ruleutils.c:240
static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9121 {
9122  StringInfo buf = context->buf;
9123 
9124  if (OidIsValid(constval->constcollid))
9125  {
9126  Oid typcollation = get_typcollation(constval->consttype);
9127 
9128  if (constval->constcollid != typcollation)
9129  {
9130  appendStringInfo(buf, " COLLATE %s",
9132  }
9133  }
9134 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10383
Oid consttype
Definition: primnodes.h:170
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
Oid constcollid
Definition: primnodes.h:172
static char * buf
Definition: pg_test_fsync.c:65
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2749
StringInfo buf
Definition: ruleutils.c:106
static void get_const_expr ( Const constval,
deparse_context context,
int  showtype 
)
static

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

8986 {
8987  StringInfo buf = context->buf;
8988  Oid typoutput;
8989  bool typIsVarlena;
8990  char *extval;
8991  bool needlabel = false;
8992 
8993  if (constval->constisnull)
8994  {
8995  /*
8996  * Always label the type of a NULL constant to prevent misdecisions
8997  * about type when reparsing.
8998  */
8999  appendStringInfoString(buf, "NULL");
9000  if (showtype >= 0)
9001  {
9002  appendStringInfo(buf, "::%s",
9004  constval->consttypmod));
9005  get_const_collation(constval, context);
9006  }
9007  return;
9008  }
9009 
9010  getTypeOutputInfo(constval->consttype,
9011  &typoutput, &typIsVarlena);
9012 
9013  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9014 
9015  switch (constval->consttype)
9016  {
9017  case INT4OID:
9018 
9019  /*
9020  * INT4 can be printed without any decoration, unless it is
9021  * negative; in that case print it as '-nnn'::integer to ensure
9022  * that the output will re-parse as a constant, not as a constant
9023  * plus operator. In most cases we could get away with printing
9024  * (-nnn) instead, because of the way that gram.y handles negative
9025  * literals; but that doesn't work for INT_MIN, and it doesn't
9026  * seem that much prettier anyway.
9027  */
9028  if (extval[0] != '-')
9029  appendStringInfoString(buf, extval);
9030  else
9031  {
9032  appendStringInfo(buf, "'%s'", extval);
9033  needlabel = true; /* we must attach a cast */
9034  }
9035  break;
9036 
9037  case NUMERICOID:
9038 
9039  /*
9040  * NUMERIC can be printed without quotes if it looks like a float
9041  * constant (not an integer, and not Infinity or NaN) and doesn't
9042  * have a leading sign (for the same reason as for INT4).
9043  */
9044  if (isdigit((unsigned char) extval[0]) &&
9045  strcspn(extval, "eE.") != strlen(extval))
9046  {
9047  appendStringInfoString(buf, extval);
9048  }
9049  else
9050  {
9051  appendStringInfo(buf, "'%s'", extval);
9052  needlabel = true; /* we must attach a cast */
9053  }
9054  break;
9055 
9056  case BITOID:
9057  case VARBITOID:
9058  appendStringInfo(buf, "B'%s'", extval);
9059  break;
9060 
9061  case BOOLOID:
9062  if (strcmp(extval, "t") == 0)
9063  appendStringInfoString(buf, "true");
9064  else
9065  appendStringInfoString(buf, "false");
9066  break;
9067 
9068  default:
9069  simple_quote_literal(buf, extval);
9070  break;
9071  }
9072 
9073  pfree(extval);
9074 
9075  if (showtype < 0)
9076  return;
9077 
9078  /*
9079  * For showtype == 0, append ::typename unless the constant will be
9080  * implicitly typed as the right type when it is read in.
9081  *
9082  * XXX this code has to be kept in sync with the behavior of the parser,
9083  * especially make_const.
9084  */
9085  switch (constval->consttype)
9086  {
9087  case BOOLOID:
9088  case UNKNOWNOID:
9089  /* These types can be left unlabeled */
9090  needlabel = false;
9091  break;
9092  case INT4OID:
9093  /* We determined above whether a label is needed */
9094  break;
9095  case NUMERICOID:
9096 
9097  /*
9098  * Float-looking constants will be typed as numeric, which we
9099  * checked above; but if there's a nondefault typmod we need to
9100  * show it.
9101  */
9102  needlabel |= (constval->consttypmod >= 0);
9103  break;
9104  default:
9105  needlabel = true;
9106  break;
9107  }
9108  if (needlabel || showtype > 0)
9109  appendStringInfo(buf, "::%s",
9111  constval->consttypmod));
9112 
9113  get_const_collation(constval, context);
9114 }
Datum constvalue
Definition: primnodes.h:174
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2600
#define NUMERICOID
Definition: pg_type.h:542
#define INT4OID
Definition: pg_type.h:316
#define VARBITOID
Definition: pg_type.h:534
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:170
void pfree(void *pointer)
Definition: mcxt.c:992
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9140
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9120
static char * buf
Definition: pg_test_fsync.c:65
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
#define BITOID
Definition: pg_type.h:530
#define BOOLOID
Definition: pg_type.h:288
#define UNKNOWNOID
Definition: pg_type.h:423
int32 consttypmod
Definition: primnodes.h:171
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:2006
StringInfo buf
Definition: ruleutils.c:106
bool constisnull
Definition: primnodes.h:175
static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6097 {
6098  StringInfo buf = context->buf;
6099  RangeTblEntry *rte;
6100 
6101  /* Insert the WITH clause if given */
6102  get_with_clause(query, context);
6103 
6104  /*
6105  * Start the query with DELETE FROM relname
6106  */
6107  rte = rt_fetch(query->resultRelation, query->rtable);
6108  Assert(rte->rtekind == RTE_RELATION);
6109  if (PRETTY_INDENT(context))
6110  {
6111  appendStringInfoChar(buf, ' ');
6112  context->indentLevel += PRETTYINDENT_STD;
6113  }
6114  appendStringInfo(buf, "DELETE FROM %s%s",
6115  only_marker(rte),
6117  if (rte->alias != NULL)
6118  appendStringInfo(buf, " %s",
6120 
6121  /* Add the USING clause if given */
6122  get_from_clause(query, " USING ", context);
6123 
6124  /* Add a WHERE clause if given */
6125  if (query->jointree->quals != NULL)
6126  {
6127  appendContextKeyword(context, " WHERE ",
6129  get_rule_expr(query->jointree->quals, context, false);
6130  }
6131 
6132  /* Add RETURNING if present */
6133  if (query->returningList)
6134  {
6135  appendContextKeyword(context, " RETURNING",
6137  get_target_list(query->returningList, context, NULL);
6138  }
6139 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4758
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
Alias * alias
Definition: parsenodes.h:960
FromExpr * jointree
Definition: parsenodes.h:129
int resultRelation
Definition: parsenodes.h:113
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5126
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9297
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
Node * quals
Definition: primnodes.h:1434
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10101
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
List * rtable
Definition: parsenodes.h:128
static char * buf
Definition: pg_test_fsync.c:65
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7265
List * returningList
Definition: parsenodes.h:135
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
char * aliasname
Definition: primnodes.h:41
#define only_marker(rte)
Definition: ruleutils.c:457
RTEKind rtekind
Definition: parsenodes.h:882
StringInfo buf
Definition: ruleutils.c:106
static void get_from_clause ( Query query,
const char *  prefix,
deparse_context context 
)
static

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

9298 {
9299  StringInfo buf = context->buf;
9300  bool first = true;
9301  ListCell *l;
9302 
9303  /*
9304  * We use the query's jointree as a guide to what to print. However, we
9305  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9306  * only appear at the top level of the jointree, so it's sufficient to
9307  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9308  * for NEW and OLD.
9309  */
9310  foreach(l, query->jointree->fromlist)
9311  {
9312  Node *jtnode = (Node *) lfirst(l);
9313 
9314  if (IsA(jtnode, RangeTblRef))
9315  {
9316  int varno = ((RangeTblRef *) jtnode)->rtindex;
9317  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9318 
9319  if (!rte->inFromCl)
9320  continue;
9321  }
9322 
9323  if (first)
9324  {
9325  appendContextKeyword(context, prefix,
9327  first = false;
9328 
9329  get_from_clause_item(jtnode, query, context);
9330  }
9331  else
9332  {
9333  StringInfoData itembuf;
9334 
9335  appendStringInfoString(buf, ", ");
9336 
9337  /*
9338  * Put the new FROM item's text into itembuf so we can decide
9339  * after we've got it whether or not it needs to go on a new line.
9340  */
9341  initStringInfo(&itembuf);
9342  context->buf = &itembuf;
9343 
9344  get_from_clause_item(jtnode, query, context);
9345 
9346  /* Restore context's output buffer */
9347  context->buf = buf;
9348 
9349  /* Consider line-wrapping if enabled */
9350  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9351  {
9352  /* Does the new item start with a new line? */
9353  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9354  {
9355  /* If so, we shouldn't add anything */
9356  /* instead, remove any trailing spaces currently in buf */
9358  }
9359  else
9360  {
9361  char *trailing_nl;
9362 
9363  /* Locate the start of the current line in the buffer */
9364  trailing_nl = strrchr(buf->data, '\n');
9365  if (trailing_nl == NULL)
9366  trailing_nl = buf->data;
9367  else
9368  trailing_nl++;
9369 
9370  /*
9371  * Add a newline, plus some indentation, if the new item
9372  * would cause an overflow.
9373  */
9374  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9375  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9378  }
9379  }
9380 
9381  /* Add the new item */
9382  appendStringInfoString(buf, itembuf.data);
9383 
9384  /* clean up */
9385  pfree(itembuf.data);
9386  }
9387  }
9388 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
FromExpr * jointree
Definition: parsenodes.h:129
#define PRETTYINDENT_VAR
Definition: ruleutils.c:82
Definition: nodes.h:508
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
List * fromlist
Definition: primnodes.h:1433
void pfree(void *pointer)
Definition: mcxt.c:992
List * rtable
Definition: parsenodes.h:128
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7265
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7319
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:106
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9391
static void get_from_clause_coldeflist ( RangeTblFunction rtfunc,
deparse_columns colinfo,
deparse_context context 
)
static

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

9753 {
9754  StringInfo buf = context->buf;
9755  ListCell *l1;
9756  ListCell *l2;
9757  ListCell *l3;
9758  ListCell *l4;
9759  int i;
9760 
9761  appendStringInfoChar(buf, '(');
9762 
9763  /* there's no forfour(), so must chase one list the hard way */
9764  i = 0;
9765  l4 = list_head(rtfunc->funccolnames);
9766  forthree(l1, rtfunc->funccoltypes,
9767  l2, rtfunc->funccoltypmods,
9768  l3, rtfunc->funccolcollations)
9769  {
9770  Oid atttypid = lfirst_oid(l1);
9771  int32 atttypmod = lfirst_int(l2);
9772  Oid attcollation = lfirst_oid(l3);
9773  char *attname;
9774 
9775  if (colinfo)
9776  attname = colinfo->colnames[i];
9777  else
9778  attname = strVal(lfirst(l4));
9779 
9780  Assert(attname); /* shouldn't be any dropped columns here */
9781 
9782  if (i > 0)
9783  appendStringInfoString(buf, ", ");
9784  appendStringInfo(buf, "%s %s",
9785  quote_identifier(attname),
9786  format_type_with_typemod(atttypid, atttypmod));
9787  if (OidIsValid(attcollation) &&
9788  attcollation != get_typcollation(atttypid))
9789  appendStringInfo(buf, " COLLATE %s",
9790  generate_collation_name(attcollation));
9791 
9792  l4 = lnext(l4);
9793  i++;
9794  }
9795 
9796  appendStringInfoChar(buf, ')');
9797 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
#define strVal(v)
Definition: value.h:54
List * funccolnames
Definition: parsenodes.h:996
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10383
signed int int32
Definition: c.h:253
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:65
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:998
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2749
List * funccolcollations
Definition: parsenodes.h:999
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:106
int i
List * funccoltypes
Definition: parsenodes.h:997
#define lfirst_oid(lc)
Definition: pg_list.h:108
char ** colnames
Definition: ruleutils.c:223
static void get_from_clause_item ( Node jtnode,
Query query,
deparse_context context 
)
static

Definition at line 9391 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_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_VALUES, RangeTblEntry::rtekind, JoinExpr::rtindex, RangeTblEntry::subquery, RangeTblEntry::tablesample, JoinExpr::usingClause, deparse_columns::usingNames, RangeTblEntry::values_lists, and deparse_context::wrapColumn.

Referenced by get_from_clause().

9392 {
9393  StringInfo buf = context->buf;
9395 
9396  if (IsA(jtnode, RangeTblRef))
9397  {
9398  int varno = ((RangeTblRef *) jtnode)->rtindex;
9399  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9400  char *refname = get_rtable_name(varno, context);
9401  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9402  RangeTblFunction *rtfunc1 = NULL;
9403  bool printalias;
9404 
9405  if (rte->lateral)
9406  appendStringInfoString(buf, "LATERAL ");
9407 
9408  /* Print the FROM item proper */
9409  switch (rte->rtekind)
9410  {
9411  case RTE_RELATION:
9412  /* Normal relation RTE */
9413  appendStringInfo(buf, "%s%s",
9414  only_marker(rte),
9416  context->namespaces));
9417  break;
9418  case RTE_SUBQUERY:
9419  /* Subquery RTE */
9420  appendStringInfoChar(buf, '(');
9421  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9422  context->prettyFlags, context->wrapColumn,
9423  context->indentLevel);
9424  appendStringInfoChar(buf, ')');
9425  break;
9426  case RTE_FUNCTION:
9427  /* Function RTE */
9428  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9429 
9430  /*
9431  * Omit ROWS FROM() syntax for just one function, unless it
9432  * has both a coldeflist and WITH ORDINALITY. If it has both,
9433  * we must use ROWS FROM() syntax to avoid ambiguity about
9434  * whether the coldeflist includes the ordinality column.
9435  */
9436  if (list_length(rte->functions) == 1 &&
9437  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9438  {
9439  get_rule_expr(rtfunc1->funcexpr, context, true);
9440  /* we'll print the coldeflist below, if it has one */
9441  }
9442  else
9443  {
9444  bool all_unnest;
9445  ListCell *lc;
9446 
9447  /*
9448  * If all the function calls in the list are to unnest,
9449  * and none need a coldeflist, then collapse the list back
9450  * down to UNNEST(args). (If we had more than one
9451  * built-in unnest function, this would get more
9452  * difficult.)
9453  *
9454  * XXX This is pretty ugly, since it makes not-terribly-
9455  * future-proof assumptions about what the parser would do
9456  * with the output; but the alternative is to emit our
9457  * nonstandard ROWS FROM() notation for what might have
9458  * been a perfectly spec-compliant multi-argument
9459  * UNNEST().
9460  */
9461  all_unnest = true;
9462  foreach(lc, rte->functions)
9463  {
9464  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9465 
9466  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9467  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9468  rtfunc->funccolnames != NIL)
9469  {
9470  all_unnest = false;
9471  break;
9472  }
9473  }
9474 
9475  if (all_unnest)
9476  {
9477  List *allargs = NIL;
9478 
9479  foreach(lc, rte->functions)
9480  {
9481  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9482  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9483 
9484  allargs = list_concat(allargs, list_copy(args));
9485  }
9486 
9487  appendStringInfoString(buf, "UNNEST(");
9488  get_rule_expr((Node *) allargs, context, true);
9489  appendStringInfoChar(buf, ')');
9490  }
9491  else
9492  {
9493  int funcno = 0;
9494 
9495  appendStringInfoString(buf, "ROWS FROM(");
9496  foreach(lc, rte->functions)
9497  {
9498  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9499 
9500  if (funcno > 0)
9501  appendStringInfoString(buf, ", ");
9502  get_rule_expr(rtfunc->funcexpr, context, true);
9503  if (rtfunc->funccolnames != NIL)
9504  {
9505  /* Reconstruct the column definition list */
9506  appendStringInfoString(buf, " AS ");
9508  NULL,
9509  context);
9510  }
9511  funcno++;
9512  }
9513  appendStringInfoChar(buf, ')');
9514  }
9515  /* prevent printing duplicate coldeflist below */
9516  rtfunc1 = NULL;
9517  }
9518  if (rte->funcordinality)
9519  appendStringInfoString(buf, " WITH ORDINALITY");
9520  break;
9521  case RTE_VALUES:
9522  /* Values list RTE */
9523  appendStringInfoChar(buf, '(');
9524  get_values_def(rte->values_lists, context);
9525  appendStringInfoChar(buf, ')');
9526  break;
9527  case RTE_CTE:
9529  break;
9530  default:
9531  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9532  break;
9533  }
9534 
9535  /* Print the relation alias, if needed */
9536  printalias = false;
9537  if (rte->alias != NULL)
9538  {
9539  /* Always print alias if user provided one */
9540  printalias = true;
9541  }
9542  else if (colinfo->printaliases)
9543  {
9544  /* Always print alias if we need to print column aliases */
9545  printalias = true;
9546  }
9547  else if (rte->rtekind == RTE_RELATION)
9548  {
9549  /*
9550  * No need to print alias if it's same as relation name (this
9551  * would normally be the case, but not if set_rtable_names had to
9552  * resolve a conflict).
9553  */
9554  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9555  printalias = true;
9556  }
9557  else if (rte->rtekind == RTE_FUNCTION)
9558  {
9559  /*
9560  * For a function RTE, always print alias. This covers possible
9561  * renaming of the function and/or instability of the
9562  * FigureColname rules for things that aren't simple functions.
9563  * Note we'd need to force it anyway for the columndef list case.
9564  */
9565  printalias = true;
9566  }
9567  else if (rte->rtekind == RTE_VALUES)
9568  {
9569  /* Alias is syntactically required for VALUES */
9570  printalias = true;
9571  }
9572  else if (rte->rtekind == RTE_CTE)
9573  {
9574  /*
9575  * No need to print alias if it's same as CTE name (this would
9576  * normally be the case, but not if set_rtable_names had to
9577  * resolve a conflict).
9578  */
9579  if (strcmp(refname, rte->ctename) != 0)
9580  printalias = true;
9581  }
9582  if (printalias)
9583  appendStringInfo(buf, " %s", quote_identifier(refname));
9584 
9585  /* Print the column definitions or aliases, if needed */
9586  if (rtfunc1 && rtfunc1->funccolnames != NIL)
9587  {
9588  /* Reconstruct the columndef list, which is also the aliases */
9589  get_from_clause_coldeflist(rtfunc1, colinfo, context);
9590  }
9591  else
9592  {
9593  /* Else print column aliases as needed */
9594  get_column_alias_list(colinfo, context);
9595  }
9596 
9597  /* Tablesample clause must go after any alias */
9598  if (rte->rtekind == RTE_RELATION && rte->tablesample)
9599  get_tablesample_def(rte->tablesample, context);
9600  }
9601  else if (IsA(jtnode, JoinExpr))
9602  {
9603  JoinExpr *j = (JoinExpr *) jtnode;
9604  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
9605  bool need_paren_on_right;
9606 
9607  need_paren_on_right = PRETTY_PAREN(context) &&
9608  !IsA(j->rarg, RangeTblRef) &&
9609  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
9610 
9611  if (!PRETTY_PAREN(context) || j->alias != NULL)
9612  appendStringInfoChar(buf, '(');
9613 
9614  get_from_clause_item(j->larg, query, context);
9615 
9616  switch (j->jointype)
9617  {
9618  case JOIN_INNER:
9619  if (j->quals)
9620  appendContextKeyword(context, " JOIN ",
9624  else
9625  appendContextKeyword(context, " CROSS JOIN ",
9629  break;
9630  case JOIN_LEFT:
9631  appendContextKeyword(context, " LEFT JOIN ",
9635  break;
9636  case JOIN_FULL:
9637  appendContextKeyword(context, " FULL JOIN ",
9641  break;
9642  case JOIN_RIGHT:
9643  appendContextKeyword(context, " RIGHT JOIN ",
9647  break;
9648  default:
9649  elog(ERROR, "unrecognized join type: %d",
9650  (int) j->jointype);
9651  }
9652 
9653  if (need_paren_on_right)
9654  appendStringInfoChar(buf, '(');
9655  get_from_clause_item(j->rarg, query, context);
9656  if (need_paren_on_right)
9657  appendStringInfoChar(buf, ')');
9658 
9659  if (j->usingClause)
9660  {
9661  ListCell *lc;
9662  bool first = true;
9663 
9664  appendStringInfoString(buf, " USING (");
9665  /* Use the assigned names, not what's in usingClause */
9666  foreach(lc, colinfo->usingNames)
9667  {
9668  char *colname = (char *) lfirst(lc);
9669 
9670  if (first)
9671  first = false;
9672  else
9673  appendStringInfoString(buf, ", ");
9675  }
9676  appendStringInfoChar(buf, ')');
9677  }
9678  else if (j->quals)
9679  {
9680  appendStringInfoString(buf, " ON ");
9681  if (!PRETTY_PAREN(context))
9682  appendStringInfoChar(buf, '(');
9683  get_rule_expr(j->quals, context, false);
9684  if (!PRETTY_PAREN(context))
9685  appendStringInfoChar(buf, ')');
9686  }
9687 
9688  if (!PRETTY_PAREN(context) || j->alias != NULL)
9689  appendStringInfoChar(buf, ')');
9690 
9691  /* Yes, it's correct to put alias after the right paren ... */
9692  if (j->alias != NULL)
9693  {
9694  appendStringInfo(buf, " %s",
9696  get_column_alias_list(colinfo, context);
9697  }
9698  }
9699  else
9700  elog(ERROR, "unrecognized node type: %d",
9701  (int) nodeTag(jtnode));
9702 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10081
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:81
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
Alias * alias
Definition: parsenodes.h:960
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:508
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * funccolnames
Definition: parsenodes.h:996
bool funcordinality
Definition: parsenodes.h:932
List * values_lists
Definition: parsenodes.h:937
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10101
Node * larg
Definition: primnodes.h:1413
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:9803
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:269
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
#define PRETTY_PAREN(context)
Definition: ruleutils.c:94
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7265
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:273
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
List * usingClause
Definition: primnodes.h:1415
Node * quals
Definition: primnodes.h:1416
Node * rarg
Definition: primnodes.h:1414
Alias * alias
Definition: primnodes.h:1417
#define NULL
Definition: c.h:226
JoinType jointype
Definition: primnodes.h:1411
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:41
List * functions
Definition: parsenodes.h:931
#define only_marker(rte)
Definition: ruleutils.c:457
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:4642
#define nodeTag(nodeptr)
Definition: nodes.h:513
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4715
RTEKind rtekind
Definition: parsenodes.h:882
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9710
char * ctename
Definition: parsenodes.h:942
Query * subquery
Definition: parsenodes.h:900
StringInfo buf
Definition: ruleutils.c:106
#define elog
Definition: elog.h:219
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9750
int rtindex
Definition: primnodes.h:1418
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:895
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4213
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9391
static void get_func_expr ( FuncExpr expr,
deparse_context context,
bool  showimplicit 
)
static

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

8646 {
8647  StringInfo buf = context->buf;
8648  Oid funcoid = expr->funcid;
8649  Oid argtypes[FUNC_MAX_ARGS];
8650  int nargs;
8651  List *argnames;
8652  bool use_variadic;
8653  ListCell *l;
8654 
8655  /*
8656  * If the function call came from an implicit coercion, then just show the
8657  * first argument --- unless caller wants to see implicit coercions.
8658  */
8659  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8660  {
8661  get_rule_expr_paren((Node *) linitial(expr->args), context,
8662  false, (Node *) expr);
8663  return;
8664  }
8665 
8666  /*
8667  * If the function call came from a cast, then show the first argument
8668  * plus an explicit cast operation.
8669  */
8670  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8672  {
8673  Node *arg = linitial(expr->args);
8674  Oid rettype = expr->funcresulttype;
8675  int32 coercedTypmod;
8676 
8677  /* Get the typmod if this is a length-coercion function */
8678  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8679 
8680  get_coercion_expr(arg, context,
8681  rettype, coercedTypmod,
8682  (Node *) expr);
8683 
8684  return;
8685  }
8686 
8687  /*
8688  * Normal function: display as proname(args). First we need to extract
8689  * the argument datatypes.
8690  */
8691  if (list_length(expr->args) > FUNC_MAX_ARGS)
8692  ereport(ERROR,
8693  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8694  errmsg("too many arguments")));
8695  nargs = 0;
8696  argnames = NIL;
8697  foreach(l, expr->args)
8698  {
8699  Node *arg = (Node *) lfirst(l);
8700 
8701  if (IsA(arg, NamedArgExpr))
8702  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8703  argtypes[nargs] = exprType(arg);
8704  nargs++;
8705  }
8706 
8707  appendStringInfo(buf, "%s(",
8708  generate_function_name(funcoid, nargs,
8709  argnames, argtypes,
8710  expr->funcvariadic,
8711  &use_variadic,
8712  context->special_exprkind));
8713  nargs = 0;
8714  foreach(l, expr->args)
8715  {
8716  if (nargs++ > 0)
8717  appendStringInfoString(buf, ", ");
8718  if (use_variadic && lnext(l) == NULL)
8719  appendStringInfoString(buf, "VARIADIC ");
8720  get_rule_expr((Node *) lfirst(l), context, true);
8721  }
8722  appendStringInfoChar(buf, ')');
8723 }
Oid funcresulttype
Definition: primnodes.h:427
#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:10203
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7338
List * args
Definition: primnodes.h:434
Definition: nodes.h:508
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:253
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:431
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define linitial(l)
Definition: pg_list.h:110
Oid funcid
Definition: primnodes.h:426
#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:65
#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:8929
ParseExprKind special_exprkind
Definition: ruleutils.c:114
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:226
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
#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:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:429
static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

5698 {
5699  StringInfo buf = context->buf;
5700  RangeTblEntry *select_rte = NULL;
5701  RangeTblEntry *values_rte = NULL;
5702  RangeTblEntry *rte;
5703  char *sep;
5704  ListCell *l;
5705  List *strippedexprs;
5706 
5707  /* Insert the WITH clause if given */
5708  get_with_clause(query, context);
5709 
5710  /*
5711  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5712  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5713  */
5714  foreach(l, query->rtable)
5715  {
5716  rte = (RangeTblEntry *) lfirst(l);
5717 
5718  if (rte->rtekind == RTE_SUBQUERY)
5719  {
5720  if (select_rte)
5721  elog(ERROR, "too many subquery RTEs in INSERT");
5722  select_rte = rte;
5723  }
5724 
5725  if (rte->rtekind == RTE_VALUES)
5726  {
5727  if (values_rte)
5728  elog(ERROR, "too many values RTEs in INSERT");
5729  values_rte = rte;
5730  }
5731  }
5732  if (select_rte && values_rte)
5733  elog(ERROR, "both subquery and values RTEs in INSERT");
5734 
5735  /*
5736  * Start the query with INSERT INTO relname
5737  */
5738  rte = rt_fetch(query->resultRelation, query->rtable);
5739  Assert(rte->rtekind == RTE_RELATION);
5740 
5741  if (PRETTY_INDENT(context))
5742  {
5743  context->indentLevel += PRETTYINDENT_STD;
5744  appendStringInfoChar(buf, ' ');
5745  }
5746  appendStringInfo(buf, "INSERT INTO %s ",
5748  /* INSERT requires AS keyword for target alias */
5749  if (rte->alias != NULL)
5750  appendStringInfo(buf, "AS %s ",
5752 
5753  /*
5754  * Add the insert-column-names list. Any indirection decoration needed on
5755  * the column names can be inferred from the top targetlist.
5756  */
5757  strippedexprs = NIL;
5758  sep = "";
5759  if (query->targetList)
5760  appendStringInfoChar(buf, '(');
5761  foreach(l, query->targetList)
5762  {
5763  TargetEntry *tle = (TargetEntry *) lfirst(l);
5764 
5765  if (tle->resjunk)
5766  continue; /* ignore junk entries */
5767 
5768  appendStringInfoString(buf, sep);
5769  sep = ", ";
5770 
5771  /*
5772  * Put out name of target column; look in the catalogs, not at
5773  * tle->resname, since resname will fail to track RENAME.
5774  */
5777  tle->resno)));
5778 
5779  /*
5780  * Print any indirection needed (subfields or subscripts), and strip
5781  * off the top-level nodes representing the indirection assignments.
5782  * Add the stripped expressions to strippedexprs. (If it's a
5783  * single-VALUES statement, the stripped expressions are the VALUES to
5784  * print below. Otherwise they're just Vars and not really
5785  * interesting.)
5786  */
5787  strippedexprs = lappend(strippedexprs,
5788  processIndirection((Node *) tle->expr,
5789  context));
5790  }
5791  if (query->targetList)
5792  appendStringInfoString(buf, ") ");
5793 
5794  if (select_rte)
5795  {
5796  /* Add the SELECT */
5797  get_query_def(select_rte->subquery, buf, NIL, NULL,
5798  context->prettyFlags, context->wrapColumn,
5799  context->indentLevel);
5800  }
5801  else if (values_rte)
5802  {
5803  /* Add the multi-VALUES expression lists */
5804  get_values_def(values_rte->values_lists, context);
5805  }
5806  else if (strippedexprs)
5807  {
5808  /* Add the single-VALUES expression list */
5809  appendContextKeyword(context, "VALUES (",
5811  get_rule_expr((Node *) strippedexprs, context, false);
5812  appendStringInfoChar(buf, ')');
5813  }
5814  else
5815  {
5816  /* No expressions, so it must be DEFAULT VALUES */
5817  appendStringInfoString(buf, "DEFAULT VALUES");
5818  }
5819 
5820  /* Add ON CONFLICT if present */
5821  if (query->onConflict)
5822  {
5823  OnConflictExpr *confl = query->onConflict;
5824 
5825  appendStringInfoString(buf, " ON CONFLICT");
5826 
5827  if (confl->arbiterElems)
5828  {
5829  /* Add the single-VALUES expression list */
5830  appendStringInfoChar(buf, '(');
5831  get_rule_expr((Node *) confl->arbiterElems, context, false);
5832  appendStringInfoChar(buf, ')');
5833 
5834  /* Add a WHERE clause (for partial indexes) if given */
5835  if (confl->arbiterWhere != NULL)
5836  {
5837  bool save_varprefix;
5838 
5839  /*
5840  * Force non-prefixing of Vars, since parser assumes that they
5841  * belong to target relation. WHERE clause does not use
5842  * InferenceElem, so this is separately required.
5843  */
5844  save_varprefix = context->varprefix;
5845  context->varprefix = false;
5846 
5847  appendContextKeyword(context, " WHERE ",
5849  get_rule_expr(confl->arbiterWhere, context, false);
5850 
5851  context->varprefix = save_varprefix;
5852  }
5853  }
5854  else if (OidIsValid(confl->constraint))
5855  {
5856  char *constraint = get_constraint_name(confl->constraint);
5857 
5858  if (!constraint)
5859  elog(ERROR, "cache lookup failed for constraint %u",
5860  confl->constraint);
5861  appendStringInfo(buf, " ON CONSTRAINT %s",
5862  quote_identifier(constraint));
5863  }
5864 
5865  if (confl->action == ONCONFLICT_NOTHING)
5866  {
5867  appendStringInfoString(buf, " DO NOTHING");
5868  }
5869  else
5870  {
5871  appendStringInfoString(buf, " DO UPDATE SET ");
5872  /* Deparse targetlist */
5874  context, rte);
5875 
5876  /* Add a WHERE clause if given */
5877  if (confl->onConflictWhere != NULL)
5878  {
5879  appendContextKeyword(context, " WHERE ",
5881  get_rule_expr(confl->onConflictWhere, context, false);
5882  }
5883  }
5884  }
5885 
5886  /* Add RETURNING if present */
5887  if (query->returningList)
5888  {
5889  appendContextKeyword(context, " RETURNING",
5891  get_target_list(query->returningList, context, NULL);
5892  }
5893 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4758
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
Alias * alias
Definition: parsenodes.h:960
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:965
OnConflictExpr * onConflict
Definition: parsenodes.h:133
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:9887
int resultRelation
Definition: parsenodes.h:113
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5126
Definition: nodes.h:508
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:5956
#define OidIsValid(objectId)
Definition: c.h:533
List * values_lists
Definition: parsenodes.h:937
List * targetList
Definition: parsenodes.h:131
List * arbiterElems
Definition: primnodes.h:1452
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10101
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
bool resjunk
Definition: primnodes.h:1337
List * rtable
Definition: parsenodes.h:128
#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:65
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7265
AttrNumber resno
Definition: primnodes.h:1331
List * returningList
Definition: parsenodes.h:135
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:80
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1449
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7370
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:41
Expr * expr
Definition: primnodes.h:1330
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4642
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4715
RTEKind rtekind
Definition: parsenodes.h:882
Node * arbiterWhere
Definition: primnodes.h:1454
Query * subquery
Definition: parsenodes.h:900
StringInfo buf
Definition: ruleutils.c:106
List * onConflictSet
Definition: primnodes.h:1458
#define elog
Definition: elog.h:219
Node * onConflictWhere
Definition: primnodes.h:1459
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 6460 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, rt_fetch, deparse_namespace::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, 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().

6462 {
6463  RangeTblEntry *rte;
6464  AttrNumber attnum;
6465  int netlevelsup;
6466  deparse_namespace *dpns;
6468  Node *expr;
6469 
6470  /*
6471  * If it's a RowExpr that was expanded from a whole-row Var, use the
6472  * column names attached to it.
6473  */
6474  if (IsA(var, RowExpr))
6475  {
6476  RowExpr *r = (RowExpr *) var;
6477 
6478  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6479  return strVal(list_nth(r->colnames, fieldno - 1));
6480  }
6481 
6482  /*
6483  * If it's a Param of type RECORD, try to find what the Param refers to.
6484  */
6485  if (IsA(var, Param))
6486  {
6487  Param *param = (Param *) var;
6488  ListCell *ancestor_cell;
6489 
6490  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6491  if (expr)
6492  {
6493  /* Found a match, so recurse to decipher the field name */
6494  deparse_namespace save_dpns;
6495  const char *result;
6496 
6497  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6498  result = get_name_for_var_field((Var *) expr, fieldno,
6499  0, context);
6500  pop_ancestor_plan(dpns, &save_dpns);
6501  return result;
6502  }
6503  }
6504 
6505  /*
6506  * If it's a Var of type RECORD, we have to find what the Var refers to;
6507  * if not, we can use get_expr_result_type. If that fails, we try
6508  * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
6509  * an acceptable message.
6510  */
6511  if (!IsA(var, Var) ||
6512  var->vartype != RECORDOID)
6513  {
6514  if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6515  tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
6516  exprTypmod((Node *) var));
6517  Assert(tupleDesc);
6518  /* Got the tupdesc, so we can extract the field name */
6519  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6520  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6521  }
6522 
6523  /* Find appropriate nesting depth */
6524  netlevelsup = var->varlevelsup + levelsup;
6525  if (netlevelsup >= list_length(context->namespaces))
6526  elog(ERROR, "bogus varlevelsup: %d offset %d",
6527  var->varlevelsup, levelsup);
6528  dpns = (deparse_namespace *) list_nth(context->namespaces,
6529  netlevelsup);
6530 
6531  /*
6532  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6533  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6534  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6535  */
6536  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6537  {
6538  rte = rt_fetch(var->varno, dpns->rtable);
6539  attnum = var->varattno;
6540  }
6541  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6542  {
6543  TargetEntry *tle;
6544  deparse_namespace save_dpns;
6545  const char *result;
6546 
6547  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6548  if (!tle)
6549  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6550 
6551  Assert(netlevelsup == 0);
6552  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6553 
6554  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6555  levelsup, context);
6556 
6557  pop_child_plan(dpns, &save_dpns);
6558  return result;
6559  }
6560  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6561  {
6562  TargetEntry *tle;
6563  deparse_namespace save_dpns;
6564  const char *result;
6565 
6566  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6567  if (!tle)
6568  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6569 
6570  Assert(netlevelsup == 0);
6571  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6572 
6573  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6574  levelsup, context);
6575 
6576  pop_child_plan(dpns, &save_dpns);
6577  return result;
6578  }
6579  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6580  {
6581  TargetEntry *tle;
6582  const char *result;
6583 
6584  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6585  if (!tle)
6586  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6587 
6588  Assert(netlevelsup == 0);
6589 
6590  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6591  levelsup, context);
6592 
6593  return result;
6594  }
6595  else
6596  {
6597  elog(ERROR, "bogus varno: %d", var->varno);
6598  return NULL; /* keep compiler quiet */
6599  }
6600 
6601  if (attnum == InvalidAttrNumber)
6602  {
6603  /* Var is whole-row reference to RTE, so select the right field */
6604  return get_rte_attribute_name(rte, fieldno);
6605  }
6606 
6607  /*
6608  * This part has essentially the same logic as the parser's
6609  * expandRecordVariable() function, but we are dealing with a different
6610  * representation of the input context, and we only need one field name
6611  * not a TupleDesc. Also, we need special cases for finding subquery and
6612  * CTE subplans when deparsing Plan trees.
6613  */
6614  expr = (Node *) var; /* default if we can't drill down */
6615 
6616  switch (rte->rtekind)
6617  {
6618  case RTE_RELATION:
6619  case RTE_VALUES:
6620 
6621  /*
6622  * This case should not occur: a column of a table or values list
6623  * shouldn't have type RECORD. Fall through and fail (most
6624  * likely) at the bottom.
6625  */
6626  break;
6627  case RTE_SUBQUERY:
6628  /* Subselect-in-FROM: examine sub-select's output expr */
6629  {
6630  if (rte->subquery)
6631  {
6633  attnum);
6634 
6635  if (ste == NULL || ste->resjunk)
6636  elog(ERROR, "subquery %s does not have attribute %d",
6637  rte->eref->aliasname, attnum);
6638  expr = (Node *) ste->expr;
6639  if (IsA(expr, Var))
6640  {
6641  /*
6642  * Recurse into the sub-select to see what its Var
6643  * refers to. We have to build an additional level of
6644  * namespace to keep in step with varlevelsup in the
6645  * subselect.
6646  */
6647  deparse_namespace mydpns;
6648  const char *result;
6649 
6650  set_deparse_for_query(&mydpns, rte->subquery,
6651  context->namespaces);
6652 
6653  context->namespaces = lcons(&mydpns,
6654  context->namespaces);
6655 
6656  result = get_name_for_var_field((Var *) expr, fieldno,
6657  0, context);
6658 
6659  context->namespaces =
6660  list_delete_first(context->namespaces);
6661 
6662  return result;
6663  }
6664  /* else fall through to inspect the expression */
6665  }
6666  else
6667  {
6668  /*
6669  * We're deparsing a Plan tree so we don't have complete
6670  * RTE entries (in particular, rte->subquery is NULL). But
6671  * the only place we'd see a Var directly referencing a
6672  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6673  * look into the child plan's tlist instead.
6674  */
6675  TargetEntry *tle;
6676  deparse_namespace save_dpns;
6677  const char *result;
6678 
6679  if (!dpns->inner_planstate)
6680  elog(ERROR, "failed to find plan for subquery %s",
6681  rte->eref->aliasname);
6682  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6683  if (!tle)
6684  elog(ERROR, "bogus varattno for subquery var: %d",
6685  attnum);
6686  Assert(netlevelsup == 0);
6687  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6688 
6689  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6690  levelsup, context);
6691 
6692  pop_child_plan(dpns, &save_dpns);
6693  return result;
6694  }
6695  }
6696  break;
6697  case RTE_JOIN:
6698  /* Join RTE --- recursively inspect the alias variable */
6699  if (rte->joinaliasvars == NIL)
6700  elog(ERROR, "cannot decompile join alias var in plan tree");
6701  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
6702  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
6703  Assert(expr != NULL);
6704  /* we intentionally don't strip implicit coercions here */
6705  if (IsA(expr, Var))
6706  return get_name_for_var_field((Var *) expr, fieldno,
6707  var->varlevelsup + levelsup,
6708  context);
6709  /* else fall through to inspect the expression */
6710  break;
6711  case RTE_FUNCTION:
6712 
6713  /*
6714  * We couldn't get here unless a function is declared with one of
6715  * its result columns as RECORD, which is not allowed.
6716  */
6717  break;
6718  case RTE_CTE:
6719  /* CTE reference: examine subquery's output expr */
6720  {
6721  CommonTableExpr *cte = NULL;
6722  Index ctelevelsup;
6723  ListCell *lc;
6724 
6725  /*
6726  * Try to find the referenced CTE using the namespace stack.
6727  */
6728  ctelevelsup = rte->ctelevelsup + netlevelsup;
6729  if (ctelevelsup >= list_length(context->namespaces))
6730  lc = NULL;
6731  else
6732  {
6733  deparse_namespace *ctedpns;
6734 
6735  ctedpns = (deparse_namespace *)
6736  list_nth(context->namespaces, ctelevelsup);
6737  foreach(lc, ctedpns->ctes)
6738  {
6739  cte = (CommonTableExpr *) lfirst(lc);
6740  if (strcmp(cte->ctename, rte->ctename) == 0)
6741  break;
6742  }
6743  }
6744  if (lc != NULL)
6745  {
6746  Query *ctequery = (Query *) cte->ctequery;
6748  attnum);
6749 
6750  if (ste == NULL || ste->resjunk)
6751  elog(ERROR, "subquery %s does not have attribute %d",
6752  rte->eref->aliasname, attnum);
6753  expr = (Node *) ste->expr;
6754  if (IsA(expr, Var))
6755  {
6756  /*
6757  * Recurse into the CTE to see what its Var refers to.
6758  * We have to build an additional level of namespace
6759  * to keep in step with varlevelsup in the CTE.
6760  * Furthermore it could be an outer CTE, so we may
6761  * have to delete some levels of namespace.
6762  */
6763  List *save_nslist = context->namespaces;
6764  List *new_nslist;
6765  deparse_namespace mydpns;
6766  const char *result;
6767 
6768  set_deparse_for_query(&mydpns, ctequery,
6769  context->namespaces);
6770 
6771  new_nslist = list_copy_tail(context->namespaces,
6772  ctelevelsup);
6773  context->namespaces = lcons(&mydpns, new_nslist);
6774 
6775  result = get_name_for_var_field((Var *) expr, fieldno,
6776  0, context);
6777 
6778  context->namespaces = save_nslist;
6779 
6780  return result;
6781  }
6782  /* else fall through to inspect the expression */
6783  }
6784  else
6785  {
6786  /*
6787  * We're deparsing a Plan tree so we don't have a CTE
6788  * list. But the only place we'd see a Var directly
6789  * referencing a CTE RTE is in a CteScan plan node, and we
6790  * can look into the subplan's tlist instead.
6791  */
6792  TargetEntry *tle;
6793  deparse_namespace save_dpns;
6794  const char *result;
6795 
6796  if (!dpns->inner_planstate)
6797  elog(ERROR, "failed to find plan for CTE %s",
6798  rte->eref->aliasname);
6799  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6800  if (!tle)
6801  elog(ERROR, "bogus varattno for subquery var: %d",
6802  attnum);
6803  Assert(netlevelsup == 0);
6804  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6805 
6806  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6807  levelsup, context);
6808 
6809  pop_child_plan(dpns, &save_dpns);
6810  return result;
6811  }
6812  }
6813  break;
6814  }
6815 
6816  /*
6817  * We now have an expression we can't expand any more, so see if
6818  * get_expr_result_type() can do anything with it. If not, pass to
6819  * lookup_rowtype_tupdesc() which will probably fail, but will give an
6820  * appropriate error message while failing.
6821  */
6822  if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
6823  tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
6824  exprTypmod(expr));
6825  Assert(tupleDesc);
6826  /* Got the tupdesc, so we can extract the field name */
6827  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6828  return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
6829 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
List * joinaliasvars
Definition: parsenodes.h:921
Index varlevelsup
Definition: primnodes.h:151
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:6840
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:274
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Definition: nodes.h:508
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:146
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4377
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:158
Definition: primnodes.h:141
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:227
List * targetList
Definition: parsenodes.h:131
bool resjunk
Definition: primnodes.h:1337
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:975
Oid vartype
Definition: primnodes.h:148
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:4307
#define RECORDOID
Definition: pg_type.h:668
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:144
List * outer_tlist
Definition: ruleutils.c:159
unsigned int Index
Definition: c.h:361
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6460
#define INNER_VAR
Definition: primnodes.h:131
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:4324
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:41
Expr * expr
Definition: primnodes.h:1330
PlanState * outer_planstate
Definition: ruleutils.c:157
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:943
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3150
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:882
char * ctename
Definition: parsenodes.h:942
Query * subquery
Definition: parsenodes.h:900
List * index_tlist
Definition: ruleutils.c:161
List * inner_tlist
Definition: ruleutils.c:160
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4354
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:494
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:961
#define INDEX_VAR
Definition: primnodes.h:133
Definition: pg_list.h:45
#define GetCTETargetList(cte)
Definition: parsenodes.h:1296
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:132
List * list_delete_first(List *list)
Definition: list.c:666
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1279
static void get_opclass_name ( Oid  opclass,
Oid  actual_datatype,
StringInfo  buf 
)
static

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

9849 {
9850  HeapTuple ht_opc;
9851  Form_pg_opclass opcrec;
9852  char *opcname;
9853  char *nspname;
9854 
9855  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
9856  if (!HeapTupleIsValid(ht_opc))
9857  elog(ERROR, "cache lookup failed for opclass %u", opclass);
9858  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
9859 
9860  if (!OidIsValid(actual_datatype) ||
9861  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
9862  {
9863  /* Okay, we need the opclass name. Do we need to qualify it? */
9864  opcname = NameStr(opcrec->opcname);
9865  if (OpclassIsVisible(opclass))
9866  appendStringInfo(buf, " %s", quote_identifier(opcname));
9867  else
9868  {
9869  nspname = get_namespace_name(opcrec->opcnamespace);
9870  appendStringInfo(buf, " %s.%s",
9871  quote_identifier(nspname),
9872  quote_identifier(opcname));
9873  }
9874  }
9875  ReleaseSysCache(ht_opc);
9876 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1383
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9975
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1792
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:494
#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 8583 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().

8584 {
8585  StringInfo buf = context->buf;
8586  Oid opno = expr->opno;
8587  List *args = expr->args;
8588 
8589  if (!PRETTY_PAREN(context))
8590  appendStringInfoChar(buf, '(');
8591  if (list_length(args) == 2)
8592  {
8593  /* binary operator */
8594  Node *arg1 = (Node *) linitial(args);
8595  Node *arg2 = (Node *) lsecond(args);
8596 
8597  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8598  appendStringInfo(buf, " %s ",
8600  exprType(arg1),
8601  exprType(arg2)));
8602  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8603  }
8604  else
8605  {
8606  /* unary operator --- but which side? */
8607  Node *arg = (Node *) linitial(args);
8608  HeapTuple tp;
8609  Form_pg_operator optup;
8610 
8612  if (!HeapTupleIsValid(tp))
8613  elog(ERROR, "cache lookup failed for operator %u", opno);
8614  optup = (Form_pg_operator) GETSTRUCT(tp);
8615  switch (optup->oprkind)
8616  {
8617  case 'l':
8618  appendStringInfo(buf, "%s ",
8620  InvalidOid,
8621  exprType(arg)));
8622  get_rule_expr_paren(arg, context, true, (Node *) expr);
8623  break;
8624  case 'r':
8625  get_rule_expr_paren(arg, context, true, (Node *) expr);
8626  appendStringInfo(buf, " %s",
8628  exprType(arg),
8629  InvalidOid));
8630  break;
8631  default:
8632  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8633  }
8634  ReleaseSysCache(tp);
8635  }
8636  if (!PRETTY_PAREN(context))
8637  appendStringInfoChar(buf, ')');
8638 }
#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:7338
Definition: nodes.h:508
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10313
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define linitial(l)
Definition: pg_list.h:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:65
#define PRETTY_PAREN(context)
Definition: ruleutils.c:94
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#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:106
void * arg
Oid opno
Definition: primnodes.h:473
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:479
Definition: pg_list.h:45
static void get_parameter ( Param param,
deparse_context context 
)
static

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

6961 {
6962  Node *expr;
6963  deparse_namespace *dpns;
6964  ListCell *ancestor_cell;
6965 
6966  /*
6967  * If it's a PARAM_EXEC parameter, try to locate the expression from which
6968  * the parameter was computed. Note that failing to find a referent isn't
6969  * an error, since the Param might well be a subplan output rather than an
6970  * input.
6971  */
6972  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6973  if (expr)
6974  {
6975  /* Found a match, so print it */
6976  deparse_namespace save_dpns;
6977  bool save_varprefix;
6978  bool need_paren;
6979 
6980  /* Switch attention to the ancestor plan node */
6981  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6982 
6983  /*
6984  * Force prefixing of Vars, since they won't belong to the relation
6985  * being scanned in the original plan node.
6986  */
6987  save_varprefix = context->varprefix;
6988  context->varprefix = true;
6989 
6990  /*
6991  * A Param's expansion is typically a Var, Aggref, or upper-level
6992  * Param, which wouldn't need extra parentheses. Otherwise, insert
6993  * parens to ensure the expression looks atomic.
6994  */
6995  need_paren = !(IsA(expr, Var) ||
6996  IsA(expr, Aggref) ||
6997  IsA(expr, Param));
6998  if (need_paren)
6999  appendStringInfoChar(context->buf, '(');
7000 
7001  get_rule_expr(expr, context, false);
7002 
7003  if (need_paren)
7004  appendStringInfoChar(context->buf, ')');
7005 
7006  context->varprefix = save_varprefix;
7007 
7008  pop_ancestor_plan(dpns, &save_dpns);
7009 
7010  return;
7011  }
7012 
7013  /*
7014  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7015  */
7016  appendStringInfo(context->buf, "$%d", param->paramid);
7017 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:6840
Definition: nodes.h:508
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4377
Definition: primnodes.h:141
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:7370
int paramid
Definition: primnodes.h:223
StringInfo buf
Definition: ruleutils.c:106
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4354
static void get_query_def ( Query query,
StringInfo  buf,
List parentnamespace,
TupleDesc  resultDesc,
int  prettyFlags,
int  wrapColumn,
int  startIndent 
)
static

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

4645 {
4646  deparse_context context;
4647  deparse_namespace dpns;
4648 
4649  /* Guard against excessively long or deeply-nested queries */
4652 
4653  /*
4654  * Before we begin to examine the query, acquire locks on referenced
4655  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4656  * consistent results. Note we assume it's OK to scribble on the passed
4657  * querytree!
4658  *
4659  * We are only deparsing the query (we are not about to execute it), so we
4660  * only need AccessShareLock on the relations it mentions.
4661  */
4662  AcquireRewriteLocks(query, false, false);
4663 
4664  context.buf = buf;
4665  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4666  context.windowClause = NIL;
4667  context.windowTList = NIL;
4668  context.varprefix = (parentnamespace != NIL ||
4669  list_length(query->rtable) != 1);
4670  context.prettyFlags = prettyFlags;
4671  context.wrapColumn = wrapColumn;
4672  context.indentLevel = startIndent;
4673  context.special_exprkind = EXPR_KIND_NONE;
4674 
4675  set_deparse_for_query(&dpns, query, parentnamespace);
4676 
4677  switch (query->commandType)
4678  {
4679  case CMD_SELECT:
4680  get_select_query_def(query, &context, resultDesc);
4681  break;
4682 
4683  case CMD_UPDATE:
4684  get_update_query_def(query, &context);
4685  break;
4686 
4687  case CMD_INSERT:
4688  get_insert_query_def(query, &context);
4689  break;
4690 
4691  case CMD_DELETE:
4692  get_delete_query_def(query, &context);
4693  break;
4694 
4695  case CMD_NOTHING:
4696  appendStringInfoString(buf, "NOTHING");
4697  break;
4698 
4699  case CMD_UTILITY:
4700  get_utility_query_def(query, &context);
4701  break;
4702 
4703  default:
4704  elog(ERROR, "unrecognized query command type: %d",
4705  query->commandType);
4706  break;
4707  }
4708 }
List * namespaces
Definition: ruleutils.c:107
#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:5697
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5901
List * rtable
Definition: parsenodes.h:128
#define ERROR
Definition: elog.h:43
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6147
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4826
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c:65
void check_stack_depth(void)
Definition: postgres.c:3096
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:114
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6096
List * windowTList
Definition: ruleutils.c:109
CmdType commandType
Definition: parsenodes.h:103
List * lcons(void *datum, List *list)
Definition: list.c:259
List * windowClause
Definition: ruleutils.c:108
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:3150
StringInfo buf
Definition: ruleutils.c:106
#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 10081 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().

10082 {
10083  char *relname = get_rel_name(relid);
10084 
10085  if (!relname)
10086  elog(ERROR, "cache lookup failed for relation %u", relid);
10087  return relname;
10088 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
static char * get_rtable_name ( int  rtindex,
deparse_context context 
)
static

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

4214 {
4216 
4217  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4218  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4219 }
List * namespaces
Definition: ruleutils.c:107
List * rtable_names
Definition: ruleutils.c:148
#define linitial(l)
Definition: pg_list.h:110
void * list_nth(const List *list, int n)
Definition: list.c:410
#define Assert(condition)
Definition: c.h:670
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 7370 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_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, linitial, linitial_oid, list_head(), list_length(), PartitionBoundSpec::listdatums, lnext, lookup_rowtype_tupdesc(), PartitionBoundSpec::lowerdatums, lsecond, lthird, 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_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_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().

7372 {
7373  StringInfo buf = context->buf;
7374 
7375  if (node == NULL)
7376  return;
7377 
7378  /* Guard against excessively long or deeply-nested queries */
7381 
7382  /*
7383  * Each level of get_rule_expr must emit an indivisible term
7384  * (parenthesized if necessary) to ensure result is reparsed into the same
7385  * expression tree. The only exception is that when the input is a List,
7386  * we emit the component items comma-separated with no surrounding
7387  * decoration; this is convenient for most callers.
7388  */
7389  switch (nodeTag(node))
7390  {
7391  case T_Var:
7392  (void) get_variable((Var *) node, 0, false, context);
7393  break;
7394 
7395  case T_Const:
7396  get_const_expr((Const *) node, context, 0);
7397  break;
7398 
7399  case T_Param:
7400  get_parameter((Param *) node, context);
7401  break;
7402 
7403  case T_Aggref:
7404  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7405  break;
7406 
7407  case T_GroupingFunc:
7408  {
7409  GroupingFunc *gexpr = (GroupingFunc *) node;
7410 
7411  appendStringInfoString(buf, "GROUPING(");
7412  get_rule_expr((Node *) gexpr->args, context, true);
7413  appendStringInfoChar(buf, ')');
7414  }
7415  break;
7416 
7417  case T_WindowFunc:
7418  get_windowfunc_expr((WindowFunc *) node, context);
7419  break;
7420 
7421  case T_ArrayRef:
7422  {
7423  ArrayRef *aref = (ArrayRef *) node;
7424  bool need_parens;
7425 
7426  /*
7427  * If the argument is a CaseTestExpr, we must be inside a
7428  * FieldStore, ie, we are assigning to an element of an array
7429  * within a composite column. Since we already punted on
7430  * displaying the FieldStore's target information, just punt
7431  * here too, and display only the assignment source
7432  * expression.
7433  */
7434  if (IsA(aref->refexpr, CaseTestExpr))
7435  {
7436  Assert(aref->refassgnexpr);
7437  get_rule_expr((Node *) aref->refassgnexpr,
7438  context, showimplicit);
7439  break;
7440  }
7441 
7442  /*
7443  * Parenthesize the argument unless it's a simple Var or a
7444  * FieldSelect. (In particular, if it's another ArrayRef, we
7445  * *must* parenthesize to avoid confusion.)
7446  */
7447  need_parens = !IsA(aref->refexpr, Var) &&
7448  !IsA(aref->refexpr, FieldSelect);
7449  if (need_parens)
7450  appendStringInfoChar(buf, '(');
7451  get_rule_expr((Node *) aref->refexpr, context, showimplicit);
7452  if (need_parens)
7453  appendStringInfoChar(buf, ')');
7454 
7455  /*
7456  * If there's a refassgnexpr, we want to print the node in the
7457  * format "array[subscripts] := refassgnexpr". This is not
7458  * legal SQL, so decompilation of INSERT or UPDATE statements
7459  * should always use processIndirection as part of the
7460  * statement-level syntax. We should only see this when
7461  * EXPLAIN tries to print the targetlist of a plan resulting
7462  * from such a statement.
7463  */
7464  if (aref->refassgnexpr)
7465  {
7466  Node *refassgnexpr;
7467 
7468  /*
7469  * Use processIndirection to print this node's subscripts
7470  * as well as any additional field selections or
7471  * subscripting in immediate descendants. It returns the
7472  * RHS expr that is actually being "assigned".
7473  */
7474  refassgnexpr = processIndirection(node, context);
7475  appendStringInfoString(buf, " := ");
7476  get_rule_expr(refassgnexpr, context, showimplicit);
7477  }
7478  else
7479  {
7480  /* Just an ordinary array fetch, so print subscripts */
7481  printSubscripts(aref, context);
7482  }
7483  }
7484  break;
7485 
7486  case T_FuncExpr:
7487  get_func_expr((FuncExpr *) node, context, showimplicit);
7488  break;
7489 
7490  case T_NamedArgExpr:
7491  {
7492  NamedArgExpr *na = (NamedArgExpr *) node;
7493 
7494  appendStringInfo(buf, "%s => ", quote_identifier(na->name));
7495  get_rule_expr((Node *) na->arg, context, showimplicit);
7496  }
7497  break;
7498 
7499  case T_OpExpr:
7500  get_oper_expr((OpExpr *) node, context);
7501  break;
7502 
7503  case T_DistinctExpr:
7504  {
7505  DistinctExpr *expr = (DistinctExpr *) node;
7506  List *args = expr->args;
7507  Node *arg1 = (Node *) linitial(args);
7508  Node *arg2 = (Node *) lsecond(args);
7509 
7510  if (!PRETTY_PAREN(context))
7511  appendStringInfoChar(buf, '(');
7512  get_rule_expr_paren(arg1, context, true, node);
7513  appendStringInfoString(buf, " IS DISTINCT FROM ");
7514  get_rule_expr_paren(arg2, context, true, node);
7515  if (!PRETTY_PAREN(context))
7516  appendStringInfoChar(buf, ')');
7517  }
7518  break;
7519 
7520  case T_NullIfExpr:
7521  {
7522  NullIfExpr *nullifexpr = (NullIfExpr *) node;
7523 
7524  appendStringInfoString(buf, "NULLIF(");
7525  get_rule_expr((Node *) nullifexpr->args, context, true);
7526  appendStringInfoChar(buf, ')');
7527  }
7528  break;
7529 
7530  case T_ScalarArrayOpExpr:
7531  {
7532  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
7533  List *args = expr->args;
7534  Node *arg1 = (Node *) linitial(args);
7535  Node *arg2 = (Node *) lsecond(args);
7536 
7537  if (!PRETTY_PAREN(context))
7538  appendStringInfoChar(buf, '(');
7539  get_rule_expr_paren(arg1, context, true, node);
7540  appendStringInfo(buf, " %s %s (",
7542  exprType(arg1),
7544  expr->useOr ? "ANY" : "ALL");
7545  get_rule_expr_paren(arg2, context, true, node);
7546 
7547  /*
7548  * There's inherent ambiguity in "x op ANY/ALL (y)" when y is
7549  * a bare sub-SELECT. Since we're here, the sub-SELECT must
7550  * be meant as a scalar sub-SELECT yielding an array value to
7551  * be used in ScalarArrayOpExpr; but the grammar will
7552  * preferentially interpret such a construct as an ANY/ALL
7553  * SubLink. To prevent misparsing the output that way, insert
7554  * a dummy coercion (which will be stripped by parse analysis,
7555  * so no inefficiency is added in dump and reload). This is
7556  * indeed most likely what the user wrote to get the construct
7557  * accepted in the first place.
7558  */
7559  if (IsA(arg2, SubLink) &&
7560  ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
7561  appendStringInfo(buf, "::%s",
7563  exprTypmod(arg2)));
7564  appendStringInfoChar(buf, ')');
7565  if (!PRETTY_PAREN(context))
7566  appendStringInfoChar(buf, ')');
7567  }
7568  break;
7569 
7570  case T_BoolExpr:
7571  {
7572  BoolExpr *expr = (BoolExpr *) node;
7573  Node *first_arg = linitial(expr->args);
7574  ListCell *arg = lnext(list_head(expr->args));
7575 
7576  switch (expr->boolop)
7577  {
7578  case AND_EXPR:
7579  if (!PRETTY_PAREN(context))
7580  appendStringInfoChar(buf, '(');
7581  get_rule_expr_paren(first_arg, context,
7582  false, node);
7583  while (arg)
7584  {
7585