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

Variables

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

Macro Definition Documentation

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

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

7290 {
7291  StringInfo buf = context->buf;
7292 
7293  if (PRETTY_INDENT(context))
7294  {
7295  int indentAmount;
7296 
7297  context->indentLevel += indentBefore;
7298 
7299  /* remove any trailing spaces currently in the buffer ... */
7301  /* ... then add a newline and some spaces */
7302  appendStringInfoChar(buf, '\n');
7303 
7304  if (context->indentLevel < PRETTYINDENT_LIMIT)
7305  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7306  else
7307  {
7308  /*
7309  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7310  * to conserve horizontal space by reducing the per-level
7311  * indentation. For best results the scale factor here should
7312  * divide all the indent amounts that get added to indentLevel
7313  * (PRETTYINDENT_STD, etc). It's important that the indentation
7314  * not grow unboundedly, else deeply-nested trees use O(N^2)
7315  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7316  */
7317  indentAmount = PRETTYINDENT_LIMIT +
7318  (context->indentLevel - PRETTYINDENT_LIMIT) /
7319  (PRETTYINDENT_STD / 2);
7320  indentAmount %= PRETTYINDENT_LIMIT;
7321  /* scale/wrap logic affects indentLevel, but not indentPlus */
7322  indentAmount += indentPlus;
7323  }
7324  appendStringInfoSpaces(buf, indentAmount);
7325 
7326  appendStringInfoString(buf, str);
7327 
7328  context->indentLevel += indentAfter;
7329  if (context->indentLevel < 0)
7330  context->indentLevel = 0;
7331  }
7332  else
7333  appendStringInfoString(buf, str);
7334 }
#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:7342
#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:800
StringInfo buf
Definition: ruleutils.c:106
static bool colname_is_unique ( char *  colname,
deparse_namespace dpns,
deparse_columns colinfo 
)
static

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

3934 {
3935  int i;
3936  ListCell *lc;
3937 
3938  /* Check against already-assigned column aliases within RTE */
3939  for (i = 0; i < colinfo->num_cols; i++)
3940  {
3941  char *oldname = colinfo->colnames[i];
3942 
3943  if (oldname && strcmp(oldname, colname) == 0)
3944  return false;
3945  }
3946 
3947  /*
3948  * If we're building a new_colnames array, check that too (this will be
3949  * partially but not completely redundant with the previous checks)
3950  */
3951  for (i = 0; i < colinfo->num_new_cols; i++)
3952  {
3953  char *oldname = colinfo->new_colnames[i];
3954 
3955  if (oldname && strcmp(oldname, colname) == 0)
3956  return false;
3957  }
3958 
3959  /* Also check against USING-column names that must be globally unique */
3960  foreach(lc, dpns->using_names)
3961  {
3962  char *oldname = (char *) lfirst(lc);
3963 
3964  if (strcmp(oldname, colname) == 0)
3965  return false;
3966  }
3967 
3968  /* Also check against names already assigned for parent-join USING cols */
3969  foreach(lc, colinfo->parentUsing)
3970  {
3971  char *oldname = (char *) lfirst(lc);
3972 
3973  if (strcmp(oldname, colname) == 0)
3974  return false;
3975  }
3976 
3977  return true;
3978 }
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 1995 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().

1997 {
1998  Datum *keys;
1999  int nKeys;
2000  int j;
2001 
2002  /* Extract data from array of int16 */
2003  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2004  INT2OID, 2, true, 's',
2005  &keys, NULL, &nKeys);
2006 
2007  for (j = 0; j < nKeys; j++)
2008  {
2009  char *colName;
2010 
2011  colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
2012 
2013  if (j == 0)
2015  else
2016  appendStringInfo(buf, ", %s", quote_identifier(colName));
2017  }
2018 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define INT2OID
Definition: pg_type.h:308
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
#define DatumGetInt16(X)
Definition: postgres.h:450
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define DatumGetArrayTypeP(X)
Definition: array.h:242
List* deparse_context_for ( const char *  aliasname,
Oid  relid 
)

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

2876 {
2877  deparse_namespace *dpns;
2878  RangeTblEntry *rte;
2879 
2880  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2881 
2882  /* Build a minimal RTE for the rel */
2883  rte = makeNode(RangeTblEntry);
2884  rte->rtekind = RTE_RELATION;
2885  rte->relid = relid;
2886  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
2887  rte->alias = makeAlias(aliasname, NIL);
2888  rte->eref = rte->alias;
2889  rte->lateral = false;
2890  rte->inh = false;
2891  rte->inFromCl = true;
2892 
2893  /* Build one-element rtable */
2894  dpns->rtable = list_make1(rte);
2895  dpns->ctes = NIL;
2896  set_rtable_names(dpns, NIL, NULL);
2898 
2899  /* Return a one-deep namespace stack */
2900  return list_make1(dpns);
2901 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:999
#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:3019
void * palloc0(Size size)
Definition: mcxt.c:878
#define makeNode(_type_)
Definition: nodes.h:568
#define NULL
Definition: c.h:229
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3232
RTEKind rtekind
Definition: parsenodes.h:916
Alias * eref
Definition: parsenodes.h:1000
#define RELKIND_RELATION
Definition: pg_class.h:160
List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

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

2918 {
2919  deparse_namespace *dpns;
2920 
2921  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2922 
2923  /* Initialize fields that stay the same across the whole plan tree */
2924  dpns->rtable = rtable;
2925  dpns->rtable_names = rtable_names;
2926  dpns->ctes = NIL;
2927 
2928  /*
2929  * Set up column name aliases. We will get rather bogus results for join
2930  * RTEs, but that doesn't matter because plan trees don't contain any join
2931  * alias Vars.
2932  */
2934 
2935  /* Return a one-deep namespace stack */
2936  return list_make1(dpns);
2937 }
#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:878
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3232
char* deparse_expression ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit 
)

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

2818 {
2819  return deparse_expression_pretty(expr, dpcontext, forceprefix,
2820  showimplicit, 0, 0);
2821 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:2843
static char * deparse_expression_pretty ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit,
int  prettyFlags,
int  startIndent 
)
static

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

2846 {
2848  deparse_context context;
2849 
2850  initStringInfo(&buf);
2851  context.buf = &buf;
2852  context.namespaces = dpcontext;
2853  context.windowClause = NIL;
2854  context.windowTList = NIL;
2855  context.varprefix = forceprefix;
2856  context.prettyFlags = prettyFlags;
2857  context.wrapColumn = WRAP_COLUMN_DEFAULT;
2858  context.indentLevel = startIndent;
2859  context.special_exprkind = EXPR_KIND_NONE;
2860 
2861  get_rule_expr(expr, &context, showimplicit);
2862 
2863  return buf.data;
2864 }
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:7393
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 4030 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().

4031 {
4032  if (n > colinfo->num_cols)
4033  {
4034  if (colinfo->colnames == NULL)
4035  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4036  else
4037  {
4038  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4039  n * sizeof(char *));
4040  memset(colinfo->colnames + colinfo->num_cols, 0,
4041  (n - colinfo->num_cols) * sizeof(char *));
4042  }
4043  colinfo->num_cols = n;
4044  }
4045 }
void * palloc0(Size size)
Definition: mcxt.c:878
#define NULL
Definition: c.h:229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
char ** colnames
Definition: ruleutils.c:223
static Node * find_param_referent ( Param param,
deparse_context context,
deparse_namespace **  dpns_p,
ListCell **  ancestor_cell_p 
)
static

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

6865 {
6866  /* Initialize output parameters to prevent compiler warnings */
6867  *dpns_p = NULL;
6868  *ancestor_cell_p = NULL;
6869 
6870  /*
6871  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
6872  * SubPlan argument. This will necessarily be in some ancestor of the
6873  * current expression's PlanState.
6874  */
6875  if (param->paramkind == PARAM_EXEC)
6876  {
6877  deparse_namespace *dpns;
6878  PlanState *child_ps;
6879  bool in_same_plan_level;
6880  ListCell *lc;
6881 
6882  dpns = (deparse_namespace *) linitial(context->namespaces);
6883  child_ps = dpns->planstate;
6884  in_same_plan_level = true;
6885 
6886  foreach(lc, dpns->ancestors)
6887  {
6888  PlanState *ps = (PlanState *) lfirst(lc);
6889  ListCell *lc2;
6890 
6891  /*
6892  * NestLoops transmit params to their inner child only; also, once
6893  * we've crawled up out of a subplan, this couldn't possibly be
6894  * the right match.
6895  */
6896  if (IsA(ps, NestLoopState) &&
6897  child_ps == innerPlanState(ps) &&
6898  in_same_plan_level)
6899  {
6900  NestLoop *nl = (NestLoop *) ps->plan;
6901 
6902  foreach(lc2, nl->nestParams)
6903  {
6904  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
6905 
6906  if (nlp->paramno == param->paramid)
6907  {
6908  /* Found a match, so return it */
6909  *dpns_p = dpns;
6910  *ancestor_cell_p = lc;
6911  return (Node *) nlp->paramval;
6912  }
6913  }
6914  }
6915 
6916  /*
6917  * Check to see if we're crawling up from a subplan.
6918  */
6919  foreach(lc2, ps->subPlan)
6920  {
6921  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6922  SubPlan *subplan = (SubPlan *) sstate->xprstate.expr;
6923  ListCell *lc3;
6924  ListCell *lc4;
6925 
6926  if (child_ps != sstate->planstate)
6927  continue;
6928 
6929  /* Matched subplan, so check its arguments */
6930  forboth(lc3, subplan->parParam, lc4, subplan->args)
6931  {
6932  int paramid = lfirst_int(lc3);
6933  Node *arg = (Node *) lfirst(lc4);
6934 
6935  if (paramid == param->paramid)
6936  {
6937  /* Found a match, so return it */
6938  *dpns_p = dpns;
6939  *ancestor_cell_p = lc;
6940  return arg;
6941  }
6942  }
6943 
6944  /* Keep looking, but we are emerging from a subplan. */
6945  in_same_plan_level = false;
6946  break;
6947  }
6948 
6949  /*
6950  * Likewise check to see if we're emerging from an initplan.
6951  * Initplans never have any parParams, so no need to search that
6952  * list, but we need to know if we should reset
6953  * in_same_plan_level.
6954  */
6955  foreach(lc2, ps->initPlan)
6956  {
6957  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
6958 
6959  if (child_ps != sstate->planstate)
6960  continue;
6961 
6962  /* No parameters to be had here. */
6963  Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL);
6964 
6965  /* Keep looking, but we are emerging from an initplan. */
6966  in_same_plan_level = false;
6967  break;
6968  }
6969 
6970  /* No luck, crawl up to next ancestor */
6971  child_ps = ps;
6972  }
6973  }
6974 
6975  /* No referent found */
6976  return NULL;
6977 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
List * nestParams
Definition: plannodes.h:658
ExprState xprstate
Definition: execnodes.h:787
List * initPlan
Definition: execnodes.h:1067
List * subPlan
Definition: execnodes.h:1069
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:520
Var * paramval
Definition: plannodes.h:665
#define linitial(l)
Definition: pg_list.h:110
struct PlanState * planstate
Definition: execnodes.h:788
Expr * expr
Definition: execnodes.h:600
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:1049
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:245
List * parParam
Definition: primnodes.h:707
PlanState * planstate
Definition: ruleutils.c:155
void * arg
#define innerPlanState(node)
Definition: execnodes.h:1091
List * args
Definition: primnodes.h:708
static void flatten_join_using_qual ( Node qual,
List **  leftvars,
List **  rightvars 
)
static

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

4182 {
4183  if (IsA(qual, BoolExpr))
4184  {
4185  /* Handle AND nodes by recursion */
4186  BoolExpr *b = (BoolExpr *) qual;
4187  ListCell *lc;
4188 
4189  Assert(b->boolop == AND_EXPR);
4190  foreach(lc, b->args)
4191  {
4193  leftvars, rightvars);
4194  }
4195  }
4196  else if (IsA(qual, OpExpr))
4197  {
4198  /* Otherwise we should have an equality operator */
4199  OpExpr *op = (OpExpr *) qual;
4200  Var *var;
4201 
4202  if (list_length(op->args) != 2)
4203  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4204  /* Arguments should be Vars with perhaps implicit coercions */
4205  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4206  if (!IsA(var, Var))
4207  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4208  (int) nodeTag(var));
4209  *leftvars = lappend(*leftvars, var);
4210  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4211  if (!IsA(var, Var))
4212  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4213  (int) nodeTag(var));
4214  *rightvars = lappend(*rightvars, var);
4215  }
4216  else
4217  {
4218  /* Perhaps we have an implicit coercion to boolean? */
4219  Node *q = strip_implicit_coercions(qual);
4220 
4221  if (q != qual)
4222  flatten_join_using_qual(q, leftvars, rightvars);
4223  else
4224  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4225  (int) nodeTag(qual));
4226  }
4227 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
Definition: nodes.h:520
Definition: primnodes.h:163
#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:561
List * lappend(List *list, void *datum)
Definition: list.c:128
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:4181
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * args
Definition: primnodes.h:562
#define nodeTag(nodeptr)
Definition: nodes.h:525
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:609
static char * flatten_reloptions ( Oid  relid)
static

Definition at line 10567 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

10568 {
10569  char *result = NULL;
10570  HeapTuple tuple;
10571  Datum reloptions;
10572  bool isnull;
10573 
10574  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10575  if (!HeapTupleIsValid(tuple))
10576  elog(ERROR, "cache lookup failed for relation %u", relid);
10577 
10578  reloptions = SysCacheGetAttr(RELOID, tuple,
10579  Anum_pg_class_reloptions, &isnull);
10580  if (!isnull)
10581  {
10583  Datum *options;
10584  int noptions;
10585  int i;
10586 
10587  initStringInfo(&buf);
10588 
10590  TEXTOID, -1, false, 'i',
10591  &options, NULL, &noptions);
10592 
10593  for (i = 0; i < noptions; i++)
10594  {
10595  char *option = TextDatumGetCString(options[i]);
10596  char *name;
10597  char *separator;
10598  char *value;
10599 
10600  /*
10601  * Each array element should have the form name=value. If the "="
10602  * is missing for some reason, treat it like an empty value.
10603  */
10604  name = option;
10605  separator = strchr(option, '=');
10606  if (separator)
10607  {
10608  *separator = '\0';
10609  value = separator + 1;
10610  }
10611  else
10612  value = "";
10613 
10614  if (i > 0)
10615  appendStringInfoString(&buf, ", ");
10616  appendStringInfo(&buf, "%s=", quote_identifier(name));
10617 
10618  /*
10619  * In general we need to quote the value; but to avoid unnecessary
10620  * clutter, do not quote if it is an identifier that would not
10621  * need quoting. (We could also allow numbers, but that is a bit
10622  * trickier than it looks --- for example, are leading zeroes
10623  * significant? We don't want to assume very much here about what
10624  * custom reloptions might mean.)
10625  */
10626  if (quote_identifier(value) == value)
10627  appendStringInfoString(&buf, value);
10628  else
10629  simple_quote_literal(&buf, value);
10630 
10631  pfree(option);
10632  }
10633 
10634  result = buf.data;
10635  }
10636 
10637  ReleaseSysCache(tuple);
10638 
10639  return result;
10640 }
static struct @78 value
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
#define TEXTOID
Definition: pg_type.h:324
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
void pfree(void *pointer)
Definition: mcxt.c:950
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9163
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:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1255
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
const char * name
Definition: encode.c:521
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
int i
#define elog
Definition: elog.h:219
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:242
char* generate_collation_name ( Oid  collid)

Definition at line 10522 of file ruleutils.c.

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

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

10523 {
10524  HeapTuple tp;
10525  Form_pg_collation colltup;
10526  char *collname;
10527  char *nspname;
10528  char *result;
10529 
10530  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
10531  if (!HeapTupleIsValid(tp))
10532  elog(ERROR, "cache lookup failed for collation %u", collid);
10533  colltup = (Form_pg_collation) GETSTRUCT(tp);
10534  collname = NameStr(colltup->collname);
10535 
10536  if (!CollationIsVisible(collid))
10537  nspname = get_namespace_name(colltup->collnamespace);
10538  else
10539  nspname = NULL;
10540 
10541  result = quote_qualified_identifier(nspname, collname);
10542 
10543  ReleaseSysCache(tp);
10544 
10545  return result;
10546 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:10200
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static char * generate_function_name ( Oid  funcid,
int  nargs,
List argnames,
Oid argtypes,
bool  has_variadic,
bool use_variadic_p,
ParseExprKind  special_exprkind 
)
static

Definition at line 10342 of file ruleutils.c.

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

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

10345 {
10346  char *result;
10347  HeapTuple proctup;
10348  Form_pg_proc procform;
10349  char *proname;
10350  bool use_variadic;
10351  char *nspname;
10352  FuncDetailCode p_result;
10353  Oid p_funcid;
10354  Oid p_rettype;
10355  bool p_retset;
10356  int p_nvargs;
10357  Oid p_vatype;
10358  Oid *p_true_typeids;
10359  bool force_qualify = false;
10360 
10361  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10362  if (!HeapTupleIsValid(proctup))
10363  elog(ERROR, "cache lookup failed for function %u", funcid);
10364  procform = (Form_pg_proc) GETSTRUCT(proctup);
10365  proname = NameStr(procform->proname);
10366 
10367  /*
10368  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10369  * qualification in some special cases.
10370  */
10371  if (special_exprkind == EXPR_KIND_GROUP_BY)
10372  {
10373  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10374  force_qualify = true;
10375  }
10376 
10377  /*
10378  * Determine whether VARIADIC should be printed. We must do this first
10379  * since it affects the lookup rules in func_get_detail().
10380  *
10381  * Currently, we always print VARIADIC if the function has a merged
10382  * variadic-array argument. Note that this is always the case for
10383  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10384  *
10385  * In principle, if VARIADIC wasn't originally specified and the array
10386  * actual argument is deconstructable, we could print the array elements
10387  * separately and not print VARIADIC, thus more nearly reproducing the
10388  * original input. For the moment that seems like too much complication
10389  * for the benefit, and anyway we do not know whether VARIADIC was
10390  * originally specified if it's a non-ANY type.
10391  */
10392  if (use_variadic_p)
10393  {
10394  /* Parser should not have set funcvariadic unless fn is variadic */
10395  Assert(!has_variadic || OidIsValid(procform->provariadic));
10396  use_variadic = has_variadic;
10397  *use_variadic_p = use_variadic;
10398  }
10399  else
10400  {
10401  Assert(!has_variadic);
10402  use_variadic = false;
10403  }
10404 
10405  /*
10406  * The idea here is to schema-qualify only if the parser would fail to
10407  * resolve the correct function given the unqualified func name with the
10408  * specified argtypes and VARIADIC flag. But if we already decided to
10409  * force qualification, then we can skip the lookup and pretend we didn't
10410  * find it.
10411  */
10412  if (!force_qualify)
10413  p_result = func_get_detail(list_make1(makeString(proname)),
10414  NIL, argnames, nargs, argtypes,
10415  !use_variadic, true,
10416  &p_funcid, &p_rettype,
10417  &p_retset, &p_nvargs, &p_vatype,
10418  &p_true_typeids, NULL);
10419  else
10420  {
10421  p_result = FUNCDETAIL_NOTFOUND;
10422  p_funcid = InvalidOid;
10423  }
10424 
10425  if ((p_result == FUNCDETAIL_NORMAL ||
10426  p_result == FUNCDETAIL_AGGREGATE ||
10427  p_result == FUNCDETAIL_WINDOWFUNC) &&
10428  p_funcid == funcid)
10429  nspname = NULL;
10430  else
10431  nspname = get_namespace_name(procform->pronamespace);
10432 
10433  result = quote_qualified_identifier(nspname, proname);
10434 
10435  ReleaseSysCache(proctup);
10436 
10437  return result;
10438 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
#define list_make1(x1)
Definition: pg_list.h:133
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:10200
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1264
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static char * generate_operator_name ( Oid  operid,
Oid  arg1,
Oid  arg2 
)
static

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

10453 {
10455  HeapTuple opertup;
10456  Form_pg_operator operform;
10457  char *oprname;
10458  char *nspname;
10459  Operator p_result;
10460 
10461  initStringInfo(&buf);
10462 
10463  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10464  if (!HeapTupleIsValid(opertup))
10465  elog(ERROR, "cache lookup failed for operator %u", operid);
10466  operform = (Form_pg_operator) GETSTRUCT(opertup);
10467  oprname = NameStr(operform->oprname);
10468 
10469  /*
10470  * The idea here is to schema-qualify only if the parser would fail to
10471  * resolve the correct operator given the unqualified op name with the
10472  * specified argtypes.
10473  */
10474  switch (operform->oprkind)
10475  {
10476  case 'b':
10477  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10478  true, -1);
10479  break;
10480  case 'l':
10481  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10482  true, -1);
10483  break;
10484  case 'r':
10485  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10486  true, -1);
10487  break;
10488  default:
10489  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10490  p_result = NULL; /* keep compiler quiet */
10491  break;
10492  }
10493 
10494  if (p_result != NULL && oprid(p_result) == operid)
10495  nspname = NULL;
10496  else
10497  {
10498  nspname = get_namespace_name(operform->oprnamespace);
10499  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10500  }
10501 
10502  appendStringInfoString(&buf, oprname);
10503 
10504  if (nspname)
10505  appendStringInfoChar(&buf, ')');
10506 
10507  if (p_result != NULL)
10508  ReleaseSysCache(p_result);
10509 
10510  ReleaseSysCache(opertup);
10511 
10512  return buf.data;
10513 }
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:10114
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
#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:513
#define ERROR
Definition: elog.h:43
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:604
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:525
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c: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:1093
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377
static char * generate_qualified_relation_name ( Oid  relid)
static

Definition at line 10300 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_serial_sequence().

10301 {
10302  HeapTuple tp;
10303  Form_pg_class reltup;
10304  char *relname;
10305  char *nspname;
10306  char *result;
10307 
10308  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10309  if (!HeapTupleIsValid(tp))
10310  elog(ERROR, "cache lookup failed for relation %u", relid);
10311  reltup = (Form_pg_class) GETSTRUCT(tp);
10312  relname = NameStr(reltup->relname);
10313 
10314  nspname = get_namespace_name(reltup->relnamespace);
10315  if (!nspname)
10316  elog(ERROR, "cache lookup failed for namespace %u",
10317  reltup->relnamespace);
10318 
10319  result = quote_qualified_identifier(nspname, relname);
10320 
10321  ReleaseSysCache(tp);
10322 
10323  return result;
10324 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:10200
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static char * generate_relation_name ( Oid  relid,
List namespaces 
)
static

Definition at line 10240 of file ruleutils.c.

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

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

10241 {
10242  HeapTuple tp;
10243  Form_pg_class reltup;
10244  bool need_qual;
10245  ListCell *nslist;
10246  char *relname;
10247  char *nspname;
10248  char *result;
10249 
10250  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10251  if (!HeapTupleIsValid(tp))
10252  elog(ERROR, "cache lookup failed for relation %u", relid);
10253  reltup = (Form_pg_class) GETSTRUCT(tp);
10254  relname = NameStr(reltup->relname);
10255 
10256  /* Check for conflicting CTE name */
10257  need_qual = false;
10258  foreach(nslist, namespaces)
10259  {
10260  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10261  ListCell *ctlist;
10262 
10263  foreach(ctlist, dpns->ctes)
10264  {
10265  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10266 
10267  if (strcmp(cte->ctename, relname) == 0)
10268  {
10269  need_qual = true;
10270  break;
10271  }
10272  }
10273  if (need_qual)
10274  break;
10275  }
10276 
10277  /* Otherwise, qualify the name if not visible in search path */
10278  if (!need_qual)
10279  need_qual = !RelationIsVisible(relid);
10280 
10281  if (need_qual)
10282  nspname = get_namespace_name(reltup->relnamespace);
10283  else
10284  nspname = NULL;
10285 
10286  result = quote_qualified_identifier(nspname, relname);
10287 
10288  ReleaseSysCache(tp);
10289 
10290  return result;
10291 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:10200
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
bool RelationIsVisible(Oid relid)
Definition: namespace.c:681
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
static void get_agg_combine_expr ( Node node,
deparse_context context,
void *  private 
)
static

Definition at line 8859 of file ruleutils.c.

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

Referenced by get_agg_expr().

8860 {
8861  Aggref *aggref;
8862  Aggref *original_aggref = private;
8863 
8864  if (!IsA(node, Aggref))
8865  elog(ERROR, "combining Aggref does not point to an Aggref");
8866 
8867  aggref = (Aggref *) node;
8868  get_agg_expr(aggref, context, original_aggref);
8869 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:8753
#define elog
Definition: elog.h:219
static void get_agg_expr ( Aggref aggref,
deparse_context context,
Aggref original_aggref 
)
static

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

8755 {
8756  StringInfo buf = context->buf;
8757  Oid argtypes[FUNC_MAX_ARGS];
8758  int nargs;
8759  bool use_variadic;
8760 
8761  /*
8762  * For a combining aggregate, we look up and deparse the corresponding
8763  * partial aggregate instead. This is necessary because our input
8764  * argument list has been replaced; the new argument list always has just
8765  * one element, which will point to a partial Aggref that supplies us with
8766  * transition states to combine.
8767  */
8768  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
8769  {
8770  TargetEntry *tle = castNode(TargetEntry, linitial(aggref->args));
8771 
8772  Assert(list_length(aggref->args) == 1);
8773  resolve_special_varno((Node *) tle->expr, context, original_aggref,
8775  return;
8776  }
8777 
8778  /*
8779  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
8780  * to avoid printing this when recursing from the code just above.
8781  */
8782  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
8783  appendStringInfoString(buf, "PARTIAL ");
8784 
8785  /* Extract the argument types as seen by the parser */
8786  nargs = get_aggregate_argtypes(aggref, argtypes);
8787 
8788  /* Print the aggregate name, schema-qualified if needed */
8789  appendStringInfo(buf, "%s(%s",
8790  generate_function_name(aggref->aggfnoid, nargs,
8791  NIL, argtypes,
8792  aggref->aggvariadic,
8793  &use_variadic,
8794  context->special_exprkind),
8795  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
8796 
8797  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
8798  {
8799  /*
8800  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
8801  * worry about inserting VARIADIC. So we can just dump the direct
8802  * args as-is.
8803  */
8804  Assert(!aggref->aggvariadic);
8805  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
8806  Assert(aggref->aggorder != NIL);
8807  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
8808  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8809  }
8810  else
8811  {
8812  /* aggstar can be set only in zero-argument aggregates */
8813  if (aggref->aggstar)
8814  appendStringInfoChar(buf, '*');
8815  else
8816  {
8817  ListCell *l;
8818  int i;
8819 
8820  i = 0;
8821  foreach(l, aggref->args)
8822  {
8823  TargetEntry *tle = (TargetEntry *) lfirst(l);
8824  Node *arg = (Node *) tle->expr;
8825 
8826  Assert(!IsA(arg, NamedArgExpr));
8827  if (tle->resjunk)
8828  continue;
8829  if (i++ > 0)
8830  appendStringInfoString(buf, ", ");
8831  if (use_variadic && i == nargs)
8832  appendStringInfoString(buf, "VARIADIC ");
8833  get_rule_expr(arg, context, true);
8834  }
8835  }
8836 
8837  if (aggref->aggorder != NIL)
8838  {
8839  appendStringInfoString(buf, " ORDER BY ");
8840  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
8841  }
8842  }
8843 
8844  if (aggref->aggfilter != NULL)
8845  {
8846  appendStringInfoString(buf, ") FILTER (WHERE ");
8847  get_rule_expr((Node *) aggref->aggfilter, context, false);
8848  }
8849 
8850  appendStringInfoChar(buf, ')');
8851 }
List * aggdistinct
Definition: primnodes.h:303
#define NIL
Definition: pg_list.h:69
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10342
bool aggvariadic
Definition: primnodes.h:306
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6397
#define castNode(_type_, nodeptr)
Definition: nodes.h:589
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5528
Definition: nodes.h:520
List * args
Definition: primnodes.h:301
bool aggstar
Definition: primnodes.h:305
unsigned int Oid
Definition: postgres_ext.h:31
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:771
#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:1359
#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:302
List * aggdirectargs
Definition: primnodes.h:300
ParseExprKind special_exprkind
Definition: ruleutils.c:114
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
Oid aggfnoid
Definition: primnodes.h:294
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:8859
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
AggSplit aggsplit
Definition: primnodes.h:310
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:772
Expr * aggfilter
Definition: primnodes.h:304
StringInfo buf
Definition: ruleutils.c:106
int i
void * arg
char aggkind
Definition: primnodes.h:308
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1786
static void get_basic_select_query ( Query query,
deparse_context context,
TupleDesc  resultDesc 
)
static

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

5023 {
5024  StringInfo buf = context->buf;
5025  RangeTblEntry *values_rte;
5026  char *sep;
5027  ListCell *l;
5028 
5029  if (PRETTY_INDENT(context))
5030  {
5031  context->indentLevel += PRETTYINDENT_STD;
5032  appendStringInfoChar(buf, ' ');
5033  }
5034 
5035  /*
5036  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5037  * VALUES part. This reverses what transformValuesClause() did at parse
5038  * time.
5039  */
5040  values_rte = get_simple_values_rte(query);
5041  if (values_rte)
5042  {
5043  get_values_def(values_rte->values_lists, context);
5044  return;
5045  }
5046 
5047  /*
5048  * Build up the query string - first we say SELECT
5049  */
5050  appendStringInfoString(buf, "SELECT");
5051 
5052  /* Add the DISTINCT clause if given */
5053  if (query->distinctClause != NIL)
5054  {
5055  if (query->hasDistinctOn)
5056  {
5057  appendStringInfoString(buf, " DISTINCT ON (");
5058  sep = "";
5059  foreach(l, query->distinctClause)
5060  {
5061  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5062 
5063  appendStringInfoString(buf, sep);
5065  false, context);
5066  sep = ", ";
5067  }
5068  appendStringInfoChar(buf, ')');
5069  }
5070  else
5071  appendStringInfoString(buf, " DISTINCT");
5072  }
5073 
5074  /* Then we tell what to select (the targetlist) */
5075  get_target_list(query->targetList, context, resultDesc);
5076 
5077  /* Add the FROM clause if needed */
5078  get_from_clause(query, " FROM ", context);
5079 
5080  /* Add the WHERE clause if given */
5081  if (query->jointree->quals != NULL)
5082  {
5083  appendContextKeyword(context, " WHERE ",
5085  get_rule_expr(query->jointree->quals, context, false);
5086  }
5087 
5088  /* Add the GROUP BY clause if given */
5089  if (query->groupClause != NULL || query->groupingSets != NULL)
5090  {
5091  ParseExprKind save_exprkind;
5092 
5093  appendContextKeyword(context, " GROUP BY ",
5095 
5096  save_exprkind = context->special_exprkind;
5098 
5099  if (query->groupingSets == NIL)
5100  {
5101  sep = "";
5102  foreach(l, query->groupClause)
5103  {
5104  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5105 
5106  appendStringInfoString(buf, sep);
5108  false, context);
5109  sep = ", ";
5110  }
5111  }
5112  else
5113  {
5114  sep = "";
5115  foreach(l, query->groupingSets)
5116  {
5117  GroupingSet *grp = lfirst(l);
5118 
5119  appendStringInfoString(buf, sep);
5120  get_rule_groupingset(grp, query->targetList, true, context);
5121  sep = ", ";
5122  }
5123  }
5124 
5125  context->special_exprkind = save_exprkind;
5126  }
5127 
5128  /* Add the HAVING clause if given */
5129  if (query->havingQual != NULL)
5130  {
5131  appendContextKeyword(context, " HAVING ",
5133  get_rule_expr(query->havingQual, context, false);
5134  }
5135 
5136  /* Add the WINDOW clause if needed */
5137  if (query->windowClause != NIL)
5138  get_rule_windowclause(query, context);
5139 }
#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:5148
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5412
Index tleSortGroupRef
Definition: parsenodes.h:1141
List * groupingSets
Definition: parsenodes.h:139
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9433
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5586
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
ParseExprKind
Definition: parse_node.h:32
List * values_lists
Definition: parsenodes.h:976
Node * quals
Definition: primnodes.h:1456
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:7288
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5468
#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:229
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4737
List * groupClause
Definition: parsenodes.h:137
StringInfo buf
Definition: ruleutils.c:106
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:4965
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 8952 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().

8955 {
8956  StringInfo buf = context->buf;
8957 
8958  /*
8959  * Since parse_coerce.c doesn't immediately collapse application of
8960  * length-coercion functions to constants, what we'll typically see in
8961  * such cases is a Const with typmod -1 and a length-coercion function
8962  * right above it. Avoid generating redundant output. However, beware of
8963  * suppressing casts when the user actually wrote something like
8964  * 'foo'::text::char(3).
8965  *
8966  * Note: it might seem that we are missing the possibility of needing to
8967  * print a COLLATE clause for such a Const. However, a Const could only
8968  * have nondefault collation in a post-constant-folding tree, in which the
8969  * length coercion would have been folded too. See also the special
8970  * handling of CollateExpr in coerce_to_target_type(): any collation
8971  * marking will be above the coercion node, not below it.
8972  */
8973  if (arg && IsA(arg, Const) &&
8974  ((Const *) arg)->consttype == resulttype &&
8975  ((Const *) arg)->consttypmod == -1)
8976  {
8977  /* Show the constant without normal ::typename decoration */
8978  get_const_expr((Const *) arg, context, -1);
8979  }
8980  else
8981  {
8982  if (!PRETTY_PAREN(context))
8983  appendStringInfoChar(buf, '(');
8984  get_rule_expr_paren(arg, context, false, parentNode);
8985  if (!PRETTY_PAREN(context))
8986  appendStringInfoChar(buf, ')');
8987  }
8988  appendStringInfo(buf, "::%s",
8989  format_type_with_typemod(resulttype, resulttypmod));
8990 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7361
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9008
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 9849 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().

9850 {
9851  StringInfo buf = context->buf;
9852  int i;
9853  bool first = true;
9854 
9855  /* Don't print aliases if not needed */
9856  if (!colinfo->printaliases)
9857  return;
9858 
9859  for (i = 0; i < colinfo->num_new_cols; i++)
9860  {
9861  char *colname = colinfo->new_colnames[i];
9862 
9863  if (first)
9864  {
9865  appendStringInfoChar(buf, '(');
9866  first = false;
9867  }
9868  else
9869  appendStringInfoString(buf, ", ");
9871  }
9872  if (!first)
9873  appendStringInfoChar(buf, ')');
9874 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
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 9143 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().

9144 {
9145  StringInfo buf = context->buf;
9146 
9147  if (OidIsValid(constval->constcollid))
9148  {
9149  Oid typcollation = get_typcollation(constval->consttype);
9150 
9151  if (constval->constcollid != typcollation)
9152  {
9153  appendStringInfo(buf, " COLLATE %s",
9155  }
9156  }
9157 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10522
Oid consttype
Definition: primnodes.h:192
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
Oid constcollid
Definition: primnodes.h:194
static char * buf
Definition: pg_test_fsync.c: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 9008 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().

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

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

6119 {
6120  StringInfo buf = context->buf;
6121  RangeTblEntry *rte;
6122 
6123  /* Insert the WITH clause if given */
6124  get_with_clause(query, context);
6125 
6126  /*
6127  * Start the query with DELETE FROM relname
6128  */
6129  rte = rt_fetch(query->resultRelation, query->rtable);
6130  Assert(rte->rtekind == RTE_RELATION);
6131  if (PRETTY_INDENT(context))
6132  {
6133  appendStringInfoChar(buf, ' ');
6134  context->indentLevel += PRETTYINDENT_STD;
6135  }
6136  appendStringInfo(buf, "DELETE FROM %s%s",
6137  only_marker(rte),
6139  if (rte->alias != NULL)
6140  appendStringInfo(buf, " %s",
6142 
6143  /* Add the USING clause if given */
6144  get_from_clause(query, " USING ", context);
6145 
6146  /* Add a WHERE clause if given */
6147  if (query->jointree->quals != NULL)
6148  {
6149  appendContextKeyword(context, " WHERE ",
6151  get_rule_expr(query->jointree->quals, context, false);
6152  }
6153 
6154  /* Add RETURNING if present */
6155  if (query->returningList)
6156  {
6157  appendContextKeyword(context, " RETURNING",
6159  get_target_list(query->returningList, context, NULL);
6160  }
6161 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4780
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
Alias * alias
Definition: parsenodes.h:999
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:5148
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9433
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
Node * quals
Definition: primnodes.h:1456
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10240
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:7288
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:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:460
RTEKind rtekind
Definition: parsenodes.h:916
StringInfo buf
Definition: ruleutils.c:106
static void get_from_clause ( Query query,
const char *  prefix,
deparse_context context 
)
static

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

9434 {
9435  StringInfo buf = context->buf;
9436  bool first = true;
9437  ListCell *l;
9438 
9439  /*
9440  * We use the query's jointree as a guide to what to print. However, we
9441  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9442  * only appear at the top level of the jointree, so it's sufficient to
9443  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9444  * for NEW and OLD.
9445  */
9446  foreach(l, query->jointree->fromlist)
9447  {
9448  Node *jtnode = (Node *) lfirst(l);
9449 
9450  if (IsA(jtnode, RangeTblRef))
9451  {
9452  int varno = ((RangeTblRef *) jtnode)->rtindex;
9453  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9454 
9455  if (!rte->inFromCl)
9456  continue;
9457  }
9458 
9459  if (first)
9460  {
9461  appendContextKeyword(context, prefix,
9463  first = false;
9464 
9465  get_from_clause_item(jtnode, query, context);
9466  }
9467  else
9468  {
9469  StringInfoData itembuf;
9470 
9471  appendStringInfoString(buf, ", ");
9472 
9473  /*
9474  * Put the new FROM item's text into itembuf so we can decide
9475  * after we've got it whether or not it needs to go on a new line.
9476  */
9477  initStringInfo(&itembuf);
9478  context->buf = &itembuf;
9479 
9480  get_from_clause_item(jtnode, query, context);
9481 
9482  /* Restore context's output buffer */
9483  context->buf = buf;
9484 
9485  /* Consider line-wrapping if enabled */
9486  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9487  {
9488  /* Does the new item start with a new line? */
9489  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9490  {
9491  /* If so, we shouldn't add anything */
9492  /* instead, remove any trailing spaces currently in buf */
9494  }
9495  else
9496  {
9497  char *trailing_nl;
9498 
9499  /* Locate the start of the current line in the buffer */
9500  trailing_nl = strrchr(buf->data, '\n');
9501  if (trailing_nl == NULL)
9502  trailing_nl = buf->data;
9503  else
9504  trailing_nl++;
9505 
9506  /*
9507  * Add a newline, plus some indentation, if the new item
9508  * would cause an overflow.
9509  */
9510  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9511  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9514  }
9515  }
9516 
9517  /* Add the new item */
9518  appendStringInfoString(buf, itembuf.data);
9519 
9520  /* clean up */
9521  pfree(itembuf.data);
9522  }
9523  }
9524 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
FromExpr * jointree
Definition: parsenodes.h:129
#define PRETTYINDENT_VAR
Definition: ruleutils.c:82
Definition: nodes.h:520
#define PRETTY_INDENT(context)
Definition: ruleutils.c:95
List * fromlist
Definition: primnodes.h:1455
void pfree(void *pointer)
Definition: mcxt.c:950
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:7288
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7342
#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:229
#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:9527
static void get_from_clause_coldeflist ( RangeTblFunction rtfunc,
deparse_columns colinfo,
deparse_context context 
)
static

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

9892 {
9893  StringInfo buf = context->buf;
9894  ListCell *l1;
9895  ListCell *l2;
9896  ListCell *l3;
9897  ListCell *l4;
9898  int i;
9899 
9900  appendStringInfoChar(buf, '(');
9901 
9902  /* there's no forfour(), so must chase one list the hard way */
9903  i = 0;
9904  l4 = list_head(rtfunc->funccolnames);
9905  forthree(l1, rtfunc->funccoltypes,
9906  l2, rtfunc->funccoltypmods,
9907  l3, rtfunc->funccolcollations)
9908  {
9909  Oid atttypid = lfirst_oid(l1);
9910  int32 atttypmod = lfirst_int(l2);
9911  Oid attcollation = lfirst_oid(l3);
9912  char *attname;
9913 
9914  if (colinfo)
9915  attname = colinfo->colnames[i];
9916  else
9917  attname = strVal(lfirst(l4));
9918 
9919  Assert(attname); /* shouldn't be any dropped columns here */
9920 
9921  if (i > 0)
9922  appendStringInfoString(buf, ", ");
9923  appendStringInfo(buf, "%s %s",
9924  quote_identifier(attname),
9925  format_type_with_typemod(atttypid, atttypmod));
9926  if (OidIsValid(attcollation) &&
9927  attcollation != get_typcollation(atttypid))
9928  appendStringInfo(buf, " COLLATE %s",
9929  generate_collation_name(attcollation));
9930 
9931  l4 = lnext(l4);
9932  i++;
9933  }
9934 
9935  appendStringInfoChar(buf, ')');
9936 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10522
signed int int32
Definition: c.h:256
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define lfirst_int(lc)
Definition: pg_list.h:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c: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:1037
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2749
List * funccolcollations
Definition: parsenodes.h:1038
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:106
int i
#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 9527 of file ruleutils.c.

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

Referenced by get_from_clause().

9528 {
9529  StringInfo buf = context->buf;
9531 
9532  if (IsA(jtnode, RangeTblRef))
9533  {
9534  int varno = ((RangeTblRef *) jtnode)->rtindex;
9535  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9536  char *refname = get_rtable_name(varno, context);
9537  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9538  RangeTblFunction *rtfunc1 = NULL;
9539  bool printalias;
9540 
9541  if (rte->lateral)
9542  appendStringInfoString(buf, "LATERAL ");
9543 
9544  /* Print the FROM item proper */
9545  switch (rte->rtekind)
9546  {
9547  case RTE_RELATION:
9548  /* Normal relation RTE */
9549  appendStringInfo(buf, "%s%s",
9550  only_marker(rte),
9552  context->namespaces));
9553  break;
9554  case RTE_SUBQUERY:
9555  /* Subquery RTE */
9556  appendStringInfoChar(buf, '(');
9557  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9558  context->prettyFlags, context->wrapColumn,
9559  context->indentLevel);
9560  appendStringInfoChar(buf, ')');
9561  break;
9562  case RTE_FUNCTION:
9563  /* Function RTE */
9564  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9565 
9566  /*
9567  * Omit ROWS FROM() syntax for just one function, unless it
9568  * has both a coldeflist and WITH ORDINALITY. If it has both,
9569  * we must use ROWS FROM() syntax to avoid ambiguity about
9570  * whether the coldeflist includes the ordinality column.
9571  */
9572  if (list_length(rte->functions) == 1 &&
9573  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9574  {
9575  get_rule_expr(rtfunc1->funcexpr, context, true);
9576  /* we'll print the coldeflist below, if it has one */
9577  }
9578  else
9579  {
9580  bool all_unnest;
9581  ListCell *lc;
9582 
9583  /*
9584  * If all the function calls in the list are to unnest,
9585  * and none need a coldeflist, then collapse the list back
9586  * down to UNNEST(args). (If we had more than one
9587  * built-in unnest function, this would get more
9588  * difficult.)
9589  *
9590  * XXX This is pretty ugly, since it makes not-terribly-
9591  * future-proof assumptions about what the parser would do
9592  * with the output; but the alternative is to emit our
9593  * nonstandard ROWS FROM() notation for what might have
9594  * been a perfectly spec-compliant multi-argument
9595  * UNNEST().
9596  */
9597  all_unnest = true;
9598  foreach(lc, rte->functions)
9599  {
9600  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9601 
9602  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9603  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9604  rtfunc->funccolnames != NIL)
9605  {
9606  all_unnest = false;
9607  break;
9608  }
9609  }
9610 
9611  if (all_unnest)
9612  {
9613  List *allargs = NIL;
9614 
9615  foreach(lc, rte->functions)
9616  {
9617  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9618  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9619 
9620  allargs = list_concat(allargs, list_copy(args));
9621  }
9622 
9623  appendStringInfoString(buf, "UNNEST(");
9624  get_rule_expr((Node *) allargs, context, true);
9625  appendStringInfoChar(buf, ')');
9626  }
9627  else
9628  {
9629  int funcno = 0;
9630 
9631  appendStringInfoString(buf, "ROWS FROM(");
9632  foreach(lc, rte->functions)
9633  {
9634  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9635 
9636  if (funcno > 0)
9637  appendStringInfoString(buf, ", ");
9638  get_rule_expr(rtfunc->funcexpr, context, true);
9639  if (rtfunc->funccolnames != NIL)
9640  {
9641  /* Reconstruct the column definition list */
9642  appendStringInfoString(buf, " AS ");
9644  NULL,
9645  context);
9646  }
9647  funcno++;
9648  }
9649  appendStringInfoChar(buf, ')');
9650  }
9651  /* prevent printing duplicate coldeflist below */
9652  rtfunc1 = NULL;
9653  }
9654  if (rte->funcordinality)
9655  appendStringInfoString(buf, " WITH ORDINALITY");
9656  break;
9657  case RTE_TABLEFUNC:
9658  get_tablefunc(rte->tablefunc, context, true);
9659  break;
9660  case RTE_VALUES:
9661  /* Values list RTE */
9662  appendStringInfoChar(buf, '(');
9663  get_values_def(rte->values_lists, context);
9664  appendStringInfoChar(buf, ')');
9665  break;
9666  case RTE_CTE:
9668  break;
9669  default:
9670  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9671  break;
9672  }
9673 
9674  /* Print the relation alias, if needed */
9675  printalias = false;
9676  if (rte->alias != NULL)
9677  {
9678  /* Always print alias if user provided one */
9679  printalias = true;
9680  }
9681  else if (colinfo->printaliases)
9682  {
9683  /* Always print alias if we need to print column aliases */
9684  printalias = true;
9685  }
9686  else if (rte->rtekind == RTE_RELATION)
9687  {
9688  /*
9689  * No need to print alias if it's same as relation name (this
9690  * would normally be the case, but not if set_rtable_names had to
9691  * resolve a conflict).
9692  */
9693  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9694  printalias = true;
9695  }
9696  else if (rte->rtekind == RTE_FUNCTION)
9697  {
9698  /*
9699  * For a function RTE, always print alias. This covers possible
9700  * renaming of the function and/or instability of the
9701  * FigureColname rules for things that aren't simple functions.
9702  * Note we'd need to force it anyway for the columndef list case.
9703  */
9704  printalias = true;
9705  }
9706  else if (rte->rtekind == RTE_VALUES)
9707  {
9708  /* Alias is syntactically required for VALUES */
9709  printalias = true;
9710  }
9711  else if (rte->rtekind == RTE_CTE)
9712  {
9713  /*
9714  * No need to print alias if it's same as CTE name (this would
9715  * normally be the case, but not if set_rtable_names had to
9716  * resolve a conflict).
9717  */
9718  if (strcmp(refname, rte->ctename) != 0)
9719  printalias = true;
9720  }
9721  if (printalias)
9722  appendStringInfo(buf, " %s", quote_identifier(refname));
9723 
9724  /* Print the column definitions or aliases, if needed */
9725  if (rtfunc1 && rtfunc1->funccolnames != NIL)
9726  {
9727  /* Reconstruct the columndef list, which is also the aliases */
9728  get_from_clause_coldeflist(rtfunc1, colinfo, context);
9729  }
9730  else
9731  {
9732  /* Else print column aliases as needed */
9733  get_column_alias_list(colinfo, context);
9734  }
9735 
9736  /* Tablesample clause must go after any alias */
9737  if (rte->rtekind == RTE_RELATION && rte->tablesample)
9738  get_tablesample_def(rte->tablesample, context);
9739  }
9740  else if (IsA(jtnode, JoinExpr))
9741  {
9742  JoinExpr *j = (JoinExpr *) jtnode;
9743  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
9744  bool need_paren_on_right;
9745 
9746  need_paren_on_right = PRETTY_PAREN(context) &&
9747  !IsA(j->rarg, RangeTblRef) &&
9748  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
9749 
9750  if (!PRETTY_PAREN(context) || j->alias != NULL)
9751  appendStringInfoChar(buf, '(');
9752 
9753  get_from_clause_item(j->larg, query, context);
9754 
9755  switch (j->jointype)
9756  {
9757  case JOIN_INNER:
9758  if (j->quals)
9759  appendContextKeyword(context, " JOIN ",
9763  else
9764  appendContextKeyword(context, " CROSS JOIN ",
9768  break;
9769  case JOIN_LEFT:
9770  appendContextKeyword(context, " LEFT JOIN ",
9774  break;
9775  case JOIN_FULL:
9776  appendContextKeyword(context, " FULL JOIN ",
9780  break;
9781  case JOIN_RIGHT:
9782  appendContextKeyword(context, " RIGHT JOIN ",
9786  break;
9787  default:
9788  elog(ERROR, "unrecognized join type: %d",
9789  (int) j->jointype);
9790  }
9791 
9792  if (need_paren_on_right)
9793  appendStringInfoChar(buf, '(');
9794  get_from_clause_item(j->rarg, query, context);
9795  if (need_paren_on_right)
9796  appendStringInfoChar(buf, ')');
9797 
9798  if (j->usingClause)
9799  {
9800  ListCell *lc;
9801  bool first = true;
9802 
9803  appendStringInfoString(buf, " USING (");
9804  /* Use the assigned names, not what's in usingClause */
9805  foreach(lc, colinfo->usingNames)
9806  {
9807  char *colname = (char *) lfirst(lc);
9808 
9809  if (first)
9810  first = false;
9811  else
9812  appendStringInfoString(buf, ", ");
9814  }
9815  appendStringInfoChar(buf, ')');
9816  }
9817  else if (j->quals)
9818  {
9819  appendStringInfoString(buf, " ON ");
9820  if (!PRETTY_PAREN(context))
9821  appendStringInfoChar(buf, '(');
9822  get_rule_expr(j->quals, context, false);
9823  if (!PRETTY_PAREN(context))
9824  appendStringInfoChar(buf, ')');
9825  }
9826 
9827  if (!PRETTY_PAREN(context) || j->alias != NULL)
9828  appendStringInfoChar(buf, ')');
9829 
9830  /* Yes, it's correct to put alias after the right paren ... */
9831  if (j->alias != NULL)
9832  {
9833  appendStringInfo(buf, " %s",
9835  get_column_alias_list(colinfo, context);
9836  }
9837  }
9838  else
9839  elog(ERROR, "unrecognized node type: %d",
9840  (int) nodeTag(jtnode));
9841 }
List * namespaces
Definition: ruleutils.c:107
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10220
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:81
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
Alias * alias
Definition: parsenodes.h:999
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:520
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool funcordinality
Definition: parsenodes.h:966
List * values_lists
Definition: parsenodes.h:976
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10240
Node * larg
Definition: primnodes.h:1435
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:9942
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
TableFunc * tablefunc
Definition: parsenodes.h:971
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:7288
#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:1437
Node * quals
Definition: primnodes.h:1438
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9315
Node * rarg
Definition: primnodes.h:1436
Alias * alias
Definition: primnodes.h:1439
#define NULL
Definition: c.h:229
JoinType jointype
Definition: primnodes.h:1433
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:965
#define only_marker(rte)
Definition: ruleutils.c:460
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:4664
#define nodeTag(nodeptr)
Definition: nodes.h:525
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4737
RTEKind rtekind
Definition: parsenodes.h:916
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:9849
char * ctename
Definition: parsenodes.h:981
Query * subquery
Definition: parsenodes.h:934
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:9889
int rtindex
Definition: primnodes.h:1440
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:929
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4235
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9527
static void get_func_expr ( FuncExpr expr,
deparse_context context,
bool  showimplicit 
)
static

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

8670 {
8671  StringInfo buf = context->buf;
8672  Oid funcoid = expr->funcid;
8673  Oid argtypes[FUNC_MAX_ARGS];
8674  int nargs;
8675  List *argnames;
8676  bool use_variadic;
8677  ListCell *l;
8678 
8679  /*
8680  * If the function call came from an implicit coercion, then just show the
8681  * first argument --- unless caller wants to see implicit coercions.
8682  */
8683  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8684  {
8685  get_rule_expr_paren((Node *) linitial(expr->args), context,
8686  false, (Node *) expr);
8687  return;
8688  }
8689 
8690  /*
8691  * If the function call came from a cast, then show the first argument
8692  * plus an explicit cast operation.
8693  */
8694  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8696  {
8697  Node *arg = linitial(expr->args);
8698  Oid rettype = expr->funcresulttype;
8699  int32 coercedTypmod;
8700 
8701  /* Get the typmod if this is a length-coercion function */
8702  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8703 
8704  get_coercion_expr(arg, context,
8705  rettype, coercedTypmod,
8706  (Node *) expr);
8707 
8708  return;
8709  }
8710 
8711  /*
8712  * Normal function: display as proname(args). First we need to extract
8713  * the argument datatypes.
8714  */
8715  if (list_length(expr->args) > FUNC_MAX_ARGS)
8716  ereport(ERROR,
8717  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
8718  errmsg("too many arguments")));
8719  nargs = 0;
8720  argnames = NIL;
8721  foreach(l, expr->args)
8722  {
8723  Node *arg = (Node *) lfirst(l);
8724 
8725  if (IsA(arg, NamedArgExpr))
8726  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
8727  argtypes[nargs] = exprType(arg);
8728  nargs++;
8729  }
8730 
8731  appendStringInfo(buf, "%s(",
8732  generate_function_name(funcoid, nargs,
8733  argnames, argtypes,
8734  expr->funcvariadic,
8735  &use_variadic,
8736  context->special_exprkind));
8737  nargs = 0;
8738  foreach(l, expr->args)
8739  {
8740  if (nargs++ > 0)
8741  appendStringInfoString(buf, ", ");
8742  if (use_variadic && lnext(l) == NULL)
8743  appendStringInfoString(buf, "VARIADIC ");
8744  get_rule_expr((Node *) lfirst(l), context, true);
8745  }
8746  appendStringInfoChar(buf, ')');
8747 }
Oid funcresulttype
Definition: primnodes.h:449
#define NIL
Definition: pg_list.h:69
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10342
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7361
List * args
Definition: primnodes.h:456
Definition: nodes.h:520
int errcode(int sqlerrcode)
Definition: elog.c:575
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:510
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:453
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define linitial(l)
Definition: pg_list.h:110
Oid funcid
Definition: primnodes.h:448
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
static char * buf
Definition: pg_test_fsync.c: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:8952
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:229
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
#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:451
static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

5720 {
5721  StringInfo buf = context->buf;
5722  RangeTblEntry *select_rte = NULL;
5723  RangeTblEntry *values_rte = NULL;
5724  RangeTblEntry *rte;
5725  char *sep;
5726  ListCell *l;
5727  List *strippedexprs;
5728 
5729  /* Insert the WITH clause if given */
5730  get_with_clause(query, context);
5731 
5732  /*
5733  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5734  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5735  */
5736  foreach(l, query->rtable)
5737  {
5738  rte = (RangeTblEntry *) lfirst(l);
5739 
5740  if (rte->rtekind == RTE_SUBQUERY)
5741  {
5742  if (select_rte)
5743  elog(ERROR, "too many subquery RTEs in INSERT");
5744  select_rte = rte;
5745  }
5746 
5747  if (rte->rtekind == RTE_VALUES)
5748  {
5749  if (values_rte)
5750  elog(ERROR, "too many values RTEs in INSERT");
5751  values_rte = rte;
5752  }
5753  }
5754  if (select_rte && values_rte)
5755  elog(ERROR, "both subquery and values RTEs in INSERT");
5756 
5757  /*
5758  * Start the query with INSERT INTO relname
5759  */
5760  rte = rt_fetch(query->resultRelation, query->rtable);
5761  Assert(rte->rtekind == RTE_RELATION);
5762 
5763  if (PRETTY_INDENT(context))
5764  {
5765  context->indentLevel += PRETTYINDENT_STD;
5766  appendStringInfoChar(buf, ' ');
5767  }
5768  appendStringInfo(buf, "INSERT INTO %s ",
5770  /* INSERT requires AS keyword for target alias */
5771  if (rte->alias != NULL)
5772  appendStringInfo(buf, "AS %s ",
5774 
5775  /*
5776  * Add the insert-column-names list. Any indirection decoration needed on
5777  * the column names can be inferred from the top targetlist.
5778  */
5779  strippedexprs = NIL;
5780  sep = "";
5781  if (query->targetList)
5782  appendStringInfoChar(buf, '(');
5783  foreach(l, query->targetList)
5784  {
5785  TargetEntry *tle = (TargetEntry *) lfirst(l);
5786 
5787  if (tle->resjunk)
5788  continue; /* ignore junk entries */
5789 
5790  appendStringInfoString(buf, sep);
5791  sep = ", ";
5792 
5793  /*
5794  * Put out name of target column; look in the catalogs, not at
5795  * tle->resname, since resname will fail to track RENAME.
5796  */
5799  tle->resno)));
5800 
5801  /*
5802  * Print any indirection needed (subfields or subscripts), and strip
5803  * off the top-level nodes representing the indirection assignments.
5804  * Add the stripped expressions to strippedexprs. (If it's a
5805  * single-VALUES statement, the stripped expressions are the VALUES to
5806  * print below. Otherwise they're just Vars and not really
5807  * interesting.)
5808  */
5809  strippedexprs = lappend(strippedexprs,
5810  processIndirection((Node *) tle->expr,
5811  context));
5812  }
5813  if (query->targetList)
5814  appendStringInfoString(buf, ") ");
5815 
5816  if (select_rte)
5817  {
5818  /* Add the SELECT */
5819  get_query_def(select_rte->subquery, buf, NIL, NULL,
5820  context->prettyFlags, context->wrapColumn,
5821  context->indentLevel);
5822  }
5823  else if (values_rte)
5824  {
5825  /* Add the multi-VALUES expression lists */
5826  get_values_def(values_rte->values_lists, context);
5827  }
5828  else if (strippedexprs)
5829  {
5830  /* Add the single-VALUES expression list */
5831  appendContextKeyword(context, "VALUES (",
5833  get_rule_expr((Node *) strippedexprs, context, false);
5834  appendStringInfoChar(buf, ')');
5835  }
5836  else
5837  {
5838  /* No expressions, so it must be DEFAULT VALUES */
5839  appendStringInfoString(buf, "DEFAULT VALUES");
5840  }
5841 
5842  /* Add ON CONFLICT if present */
5843  if (query->onConflict)
5844  {
5845  OnConflictExpr *confl = query->onConflict;
5846 
5847  appendStringInfoString(buf, " ON CONFLICT");
5848 
5849  if (confl->arbiterElems)
5850  {
5851  /* Add the single-VALUES expression list */
5852  appendStringInfoChar(buf, '(');
5853  get_rule_expr((Node *) confl->arbiterElems, context, false);
5854  appendStringInfoChar(buf, ')');
5855 
5856  /* Add a WHERE clause (for partial indexes) if given */
5857  if (confl->arbiterWhere != NULL)
5858  {
5859  bool save_varprefix;
5860 
5861  /*
5862  * Force non-prefixing of Vars, since parser assumes that they
5863  * belong to target relation. WHERE clause does not use
5864  * InferenceElem, so this is separately required.
5865  */
5866  save_varprefix = context->varprefix;
5867  context->varprefix = false;
5868 
5869  appendContextKeyword(context, " WHERE ",
5871  get_rule_expr(confl->arbiterWhere, context, false);
5872 
5873  context->varprefix = save_varprefix;
5874  }
5875  }
5876  else if (OidIsValid(confl->constraint))
5877  {
5878  char *constraint = get_constraint_name(confl->constraint);
5879 
5880  if (!constraint)
5881  elog(ERROR, "cache lookup failed for constraint %u",
5882  confl->constraint);
5883  appendStringInfo(buf, " ON CONSTRAINT %s",
5884  quote_identifier(constraint));
5885  }
5886 
5887  if (confl->action == ONCONFLICT_NOTHING)
5888  {
5889  appendStringInfoString(buf, " DO NOTHING");
5890  }
5891  else
5892  {
5893  appendStringInfoString(buf, " DO UPDATE SET ");
5894  /* Deparse targetlist */
5896  context, rte);
5897 
5898  /* Add a WHERE clause if given */
5899  if (confl->onConflictWhere != NULL)
5900  {
5901  appendContextKeyword(context, " WHERE ",
5903  get_rule_expr(confl->onConflictWhere, context, false);
5904  }
5905  }
5906  }
5907 
5908  /* Add RETURNING if present */
5909  if (query->returningList)
5910  {
5911  appendContextKeyword(context, " RETURNING",
5913  get_target_list(query->returningList, context, NULL);
5914  }
5915 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:4780
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
Alias * alias
Definition: parsenodes.h:999
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:10026
int resultRelation
Definition: parsenodes.h:113
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5148
Definition: nodes.h:520
#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:5978
#define OidIsValid(objectId)
Definition: c.h:538
List * values_lists
Definition: parsenodes.h:976
List * targetList
Definition: parsenodes.h:131
List * arbiterElems
Definition: primnodes.h:1474
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10240
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
bool resjunk
Definition: primnodes.h:1359
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:7288
AttrNumber resno
Definition: primnodes.h:1353
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:1471
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:229
#define Assert(condition)
Definition: c.h:675
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1352
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4664
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4737
RTEKind rtekind
Definition: parsenodes.h:916
Node * arbiterWhere
Definition: primnodes.h:1476
Query * subquery
Definition: parsenodes.h:934
StringInfo buf
Definition: ruleutils.c:106
List * onConflictSet
Definition: primnodes.h:1480
#define elog
Definition: elog.h:219
Node * onConflictWhere
Definition: primnodes.h:1481
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 6482 of file ruleutils.c.

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

Referenced by get_rule_expr().

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

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

9988 {
9989  HeapTuple ht_opc;
9990  Form_pg_opclass opcrec;
9991  char *opcname;
9992  char *nspname;
9993 
9994  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
9995  if (!HeapTupleIsValid(ht_opc))
9996  elog(ERROR, "cache lookup failed for opclass %u", opclass);
9997  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
9998 
9999  if (!OidIsValid(actual_datatype) ||
10000  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10001  {
10002  /* Okay, we need the opclass name. Do we need to qualify it? */
10003  opcname = NameStr(opcrec->opcname);
10004  if (OpclassIsVisible(opclass))
10005  appendStringInfo(buf, " %s", quote_identifier(opcname));
10006  else
10007  {
10008  nspname = get_namespace_name(opcrec->opcnamespace);
10009  appendStringInfo(buf, " %s.%s",
10010  quote_identifier(nspname),
10011  quote_identifier(opcname));
10012  }
10013  }
10014  ReleaseSysCache(ht_opc);
10015 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1378
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10114
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1093
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1792
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
static void get_oper_expr ( OpExpr expr,
deparse_context context 
)
static

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

8608 {
8609  StringInfo buf = context->buf;
8610  Oid opno = expr->opno;
8611  List *args = expr->args;
8612 
8613  if (!PRETTY_PAREN(context))
8614  appendStringInfoChar(buf, '(');
8615  if (list_length(args) == 2)
8616  {
8617  /* binary operator */
8618  Node *arg1 = (Node *) linitial(args);
8619  Node *arg2 = (Node *) lsecond(args);
8620 
8621  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8622  appendStringInfo(buf, " %s ",
8624  exprType(arg1),
8625  exprType(arg2)));
8626  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8627  }
8628  else
8629  {
8630  /* unary operator --- but which side? */
8631  Node *arg = (Node *) linitial(args);
8632  HeapTuple tp;
8633  Form_pg_operator optup;
8634 
8636  if (!HeapTupleIsValid(tp))
8637  elog(ERROR, "cache lookup failed for operator %u", opno);
8638  optup = (Form_pg_operator) GETSTRUCT(tp);
8639  switch (optup->oprkind)
8640  {
8641  case 'l':
8642  appendStringInfo(buf, "%s ",
8644  InvalidOid,
8645  exprType(arg)));
8646  get_rule_expr_paren(arg, context, true, (Node *) expr);
8647  break;
8648  case 'r':
8649  get_rule_expr_paren(arg, context, true, (Node *) expr);
8650  appendStringInfo(buf, " %s",
8652  exprType(arg),
8653  InvalidOid));
8654  break;
8655  default:
8656  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8657  }
8658  ReleaseSysCache(tp);
8659  }
8660  if (!PRETTY_PAREN(context))
8661  appendStringInfoChar(buf, ')');
8662 }
#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:7361
Definition: nodes.h:520
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:150
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10452
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:513
#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:1093
#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:495
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:501
Definition: pg_list.h:45
static void get_parameter ( Param param,
deparse_context context 
)
static

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

6984 {
6985  Node *expr;
6986  deparse_namespace *dpns;
6987  ListCell *ancestor_cell;
6988 
6989  /*
6990  * If it's a PARAM_EXEC parameter, try to locate the expression from which
6991  * the parameter was computed. Note that failing to find a referent isn't
6992  * an error, since the Param might well be a subplan output rather than an
6993  * input.
6994  */
6995  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6996  if (expr)
6997  {
6998  /* Found a match, so print it */
6999  deparse_namespace save_dpns;
7000  bool save_varprefix;
7001  bool need_paren;
7002 
7003  /* Switch attention to the ancestor plan node */
7004  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7005 
7006  /*
7007  * Force prefixing of Vars, since they won't belong to the relation
7008  * being scanned in the original plan node.
7009  */
7010  save_varprefix = context->varprefix;
7011  context->varprefix = true;
7012 
7013  /*
7014  * A Param's expansion is typically a Var, Aggref, or upper-level
7015  * Param, which wouldn't need extra parentheses. Otherwise, insert
7016  * parens to ensure the expression looks atomic.
7017  */
7018  need_paren = !(IsA(expr, Var) ||
7019  IsA(expr, Aggref) ||
7020  IsA(expr, Param));
7021  if (need_paren)
7022  appendStringInfoChar(context->buf, '(');
7023 
7024  get_rule_expr(expr, context, false);
7025 
7026  if (need_paren)
7027  appendStringInfoChar(context->buf, ')');
7028 
7029  context->varprefix = save_varprefix;
7030 
7031  pop_ancestor_plan(dpns, &save_dpns);
7032 
7033  return;
7034  }
7035 
7036  /*
7037  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7038  */
7039  appendStringInfo(context->buf, "$%d", param->paramid);
7040 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:6863
Definition: nodes.h:520
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4399
Definition: primnodes.h:163
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:201
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7393
int paramid
Definition: primnodes.h:245
StringInfo buf
Definition: ruleutils.c:106
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4376
static void get_query_def ( Query query,
StringInfo  buf,
List parentnamespace,
TupleDesc  resultDesc,
int  prettyFlags,
int  wrapColumn,
int  startIndent 
)
static

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

4667 {
4668  deparse_context context;
4669  deparse_namespace dpns;
4670 
4671  /* Guard against excessively long or deeply-nested queries */
4674 
4675  /*
4676  * Before we begin to examine the query, acquire locks on referenced
4677  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4678  * consistent results. Note we assume it's OK to scribble on the passed
4679  * querytree!
4680  *
4681  * We are only deparsing the query (we are not about to execute it), so we
4682  * only need AccessShareLock on the relations it mentions.
4683  */
4684  AcquireRewriteLocks(query, false, false);
4685 
4686  context.buf = buf;
4687  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4688  context.windowClause = NIL;
4689  context.windowTList = NIL;
4690  context.varprefix = (parentnamespace != NIL ||
4691  list_length(query->rtable) != 1);
4692  context.prettyFlags = prettyFlags;
4693  context.wrapColumn = wrapColumn;
4694  context.indentLevel = startIndent;
4695  context.special_exprkind = EXPR_KIND_NONE;
4696 
4697  set_deparse_for_query(&dpns, query, parentnamespace);
4698 
4699  switch (query->commandType)
4700  {
4701  case CMD_SELECT:
4702  get_select_query_def(query, &context, resultDesc);
4703  break;
4704 
4705  case CMD_UPDATE:
4706  get_update_query_def(query, &context);
4707  break;
4708 
4709  case CMD_INSERT:
4710  get_insert_query_def(query, &context);
4711  break;
4712 
4713  case CMD_DELETE:
4714  get_delete_query_def(query, &context);
4715  break;
4716 
4717  case CMD_NOTHING:
4718  appendStringInfoString(buf, "NOTHING");
4719  break;
4720 
4721  case CMD_UTILITY:
4722  get_utility_query_def(query, &context);
4723  break;
4724 
4725  default:
4726  elog(ERROR, "unrecognized query command type: %d",
4727  query->commandType);
4728  break;
4729  }
4730 }
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:5719
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5923
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:6169
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:4848
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:3098
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:6118
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:3169
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 10220 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().

10221 {
10222  char *relname = get_rel_name(relid);
10223 
10224  if (!relname)
10225  elog(ERROR, "cache lookup failed for relation %u", relid);
10226  return relname;
10227 }
#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 4235 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().

4236 {
4238 
4239  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4240  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4241 }
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:675
static int list_length(const List *l)
Definition: pg_list.h:89
static void get_rule_expr ( Node node,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 7393 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, castNode, CHECK_FOR_INTERRUPTS, check_stack_depth(), COERCE_EXPLICIT_CALL, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, CoerceViaIO::coerceformat, ArrayCoerceExpr::coerceformat, CoerceToDomain::coercionformat, CollateExpr::collOid, Const::constisnull, Const::constvalue, convert(), ConvertRowtypeExpr::convertformat, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, DatumGetBool, DatumGetInt32, CaseExpr::defresult, ArrayExpr::elements, elog, ERROR, CaseWhen::expr, InferenceElem::expr, EXPR_SUBLINK, exprType(), exprTypmod(), FieldSelect::fieldnum, forboth, format_type_with_typemod(), generate_collation_name(), generate_operator_name(), get_agg_expr(), get_base_element_type(), get_coercion_expr(), get_const_expr(), get_func_expr(), get_name_for_var_field(), get_opclass_input_type(), get_opclass_name(), get_oper_expr(), get_parameter(), get_rule_expr_paren(), get_rule_expr_toplevel(), get_sublink_expr(), get_tablefunc(), get_variable(), get_windowfunc_expr(), i, InferenceElem::infercollid, InferenceElem::inferopclass, PartitionRangeDatum::infinite, IS_DOCUMENT, IS_FALSE, IS_GREATEST, IS_LEAST, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IS_XMLCONCAT, IS_XMLELEMENT, IS_XMLFOREST, IS_XMLPARSE, IS_XMLPI, IS_XMLROOT, IS_XMLSERIALIZE, IsA, RowCompareExpr::largs, lfirst, 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_TableFunc, T_Var, T_WindowFunc, T_XmlExpr, XmlExpr::type, type_is_rowtype(), SQLValueFunction::typmod, XmlExpr::typmod, PartitionBoundSpec::upperdatums, SubPlan::useHashTable, ScalarArrayOpExpr::useOr, val, PartitionRangeDatum::value, deparse_context::varprefix, XML_STANDALONE_NO, XML_STANDALONE_NO_VALUE, XML_STANDALONE_YES, XmlExpr::xmloption, and XMLOPTION_DOCUMENT.

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

7395 {
7396  StringInfo buf = context->buf;
7397 
7398  if (node == NULL)
7399  return;
7400 
7401  /* Guard against excessively long or deeply-nested queries */
7404 
7405  /*
7406  * Each level of get_rule_expr must emit an indivisible term
7407  * (parenthesized if necessary) to ensure result is reparsed into the same
7408  * expression tree. The only exception is that when the input is a List,
7409  * we emit the component items comma-separated with no surrounding
7410  * decoration; this is convenient for most callers.
7411  */
7412  switch (nodeTag(node))
7413  {
7414  case T_Var:
7415  (void) get_variable((Var *) node, 0, false, context);
7416  break;
7417 
7418  case T_Const:
7419  get_const_expr((Const *) node, context, 0);
7420  break;
7421 
7422  case T_Param:
7423  get_parameter((Param *) node, context);
7424  break;
7425 
7426  case T_Aggref:
7427  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7428  break;
7429 
7430  case T_GroupingFunc:
7431  {
7432  GroupingFunc *gexpr = (GroupingFunc *) node;
7433 
7434  appendStringInfoString(buf, "GROUPING(");
7435  get_rule_expr((Node *) gexpr->args, context, true);
7436  appendStringInfoChar(buf, ')');
7437  }
7438  break;
7439 
7440  case T_WindowFunc:
7441  get_windowfunc_expr((WindowFunc *) node, context);
7442  break;
7443 
7444  case T_ArrayRef:
7445  {
7446  ArrayRef *aref = (ArrayRef *) node;
7447  bool need_parens;
7448 
7449  /*
7450  * If the argument is a CaseTestExpr, we must be inside a
7451  * FieldStore, ie, we are assigning to an element of an array
7452  * within a composite column. Since we already punted on
7453  * displaying the FieldStore's target information, just punt
7454  * here too, and display only the assignment source
7455  * expression.
7456  */
7457  if (IsA(aref->refexpr, CaseTestExpr))
7458  {
7459  Assert(aref->refassgnexpr);
7460  get_rule_expr((Node *) aref->refassgnexpr,
7461  context, showimplicit);
7462  break;
7463  }
7464 
7465  /*
7466  * Parenthesize the argument unless it's a simple Var or a
7467  * FieldSelect. (In particular, if it's another ArrayRef, we
7468  * *must* parenthesize to avoid confusion.)
7469  */
7470  need_parens = !IsA(aref->refexpr, Var) &&
7471  !IsA(aref->refexpr, FieldSelect);
7472  if (need_parens)
7473  appendStringInfoChar(buf, '(');
7474  get_rule_expr((Node *) aref->refexpr, context, showimplicit);
7475  if (need_parens)
7476  appendStringInfoChar(buf, ')');
7477 
7478  /*
7479  * If there's a refassgnexpr, we want to print the node in the
7480  * format "array[subscripts] := refassgnexpr". This is not
7481  * legal SQL, so decompilation of INSERT or UPDATE statements
7482  * should always use processIndirection as part of the
7483  * statement-level syntax. We should only see this when
7484  * EXPLAIN tries to print the targetlist of a plan resulting
7485  * from such a statement.
7486  */
7487  if (aref->refassgnexpr)
7488  {
7489  Node *refassgnexpr;
7490 
7491  /*
7492  * Use processIndirection to print this node's subscripts
7493  * as well as any additional field selections or
7494  * subscripting in immediate descendants. It returns the
7495  * RHS expr that is actually being "assigned".
7496  */
7497  refassgnexpr = processIndirection(node, context);
7498  appendStringInfoString(buf, " := ");
7499  get_rule_expr(refassgnexpr, context, showimplicit);
7500  }
7501  else
7502  {
7503  /* Just an ordinary array fetch, so print subscripts */
7504  printSubscripts(aref, context);
7505  }
7506  }
7507  break;
7508 
7509  case T_FuncExpr:
7510  get_func_expr((FuncExpr *) node, context, showimplicit);
7511  break;
7512 
7513  case T_NamedArgExpr:
7514  {
7515  NamedArgExpr *na = (NamedArgExpr *) node;
7516 
7517  appendStringInfo(buf, "%s => ", quote_identifier(na->name));
7518  get_rule_expr((Node *) na->arg, context, showimplicit);
7519  }
7520  break;
7521 
7522  case T_OpExpr:
7523  get_oper_expr((OpExpr *) node, context);
7524  break;
7525 
7526  case T_DistinctExpr:
7527  {
7528  DistinctExpr *expr = (DistinctExpr *) node;
7529  List *args = expr->args;
7530  Node *arg1 = (Node *) linitial(args);
7531  Node *arg2 = (Node *) lsecond(args);
7532 
7533  if (!PRETTY_PAREN(context))
7534  appendStringInfoChar(buf, '(');
7535  get_rule_expr_paren(arg1, context, true, node);
7536  appendStringInfoString(buf, " IS DISTINCT FROM ");
7537  get_rule_expr_paren(arg2, context, true, node);
7538  if (!PRETTY_PAREN(context))
7539  appendStringInfoChar(buf, ')');
7540  }
7541  break;
7542 
7543  case T_NullIfExpr:
7544  {
7545  NullIfExpr *nullifexpr = (NullIfExpr *) node;
7546 
7547  appendStringInfoString(buf, "NULLIF(");
7548  get_rule_expr((Node *) nullifexpr->args, context, true);
7549  appendStringInfoChar(buf, ')');
7550  }
7551  break;
7552 
7553  case T_ScalarArrayOpExpr:
7554  {
7555  ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
7556  List *args = expr->args;
7557  Node *arg1 = (Node *) linitial(args);
7558  Node *arg2 = (Node *) lsecond(args);
7559 
7560  if (!PRETTY_PAREN(context))
7561  appendStringInfoChar(buf, '(');
7562  get_rule_expr_paren(arg1, context, true, node);
7563  appendStringInfo(buf, " %s %s (",