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

Go to the source code of this file.

Data Structures

struct  deparse_context
 
struct  deparse_namespace
 
struct  deparse_columns
 
struct  NameHashEntry
 

Macros

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

Functions

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

Variables

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

Macro Definition Documentation

◆ deparse_columns_fetch

#define deparse_columns_fetch (   rangetable_index,
  dpns 
)    ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1))

◆ only_marker

#define only_marker (   rte)    ((rte)->inh ? "" : "ONLY ")

Definition at line 467 of file ruleutils.c.

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

◆ PRETTY_INDENT

◆ PRETTY_PAREN

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

◆ PRETTYFLAG_INDENT

◆ PRETTYFLAG_PAREN

◆ PRETTYINDENT_JOIN

#define PRETTYINDENT_JOIN   4

Definition at line 83 of file ruleutils.c.

Referenced by get_from_clause_item().

◆ PRETTYINDENT_LIMIT

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 86 of file ruleutils.c.

Referenced by appendContextKeyword().

◆ PRETTYINDENT_STD

◆ PRETTYINDENT_VAR

#define PRETTYINDENT_VAR   4

Definition at line 84 of file ruleutils.c.

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

◆ WRAP_COLUMN_DEFAULT

Function Documentation

◆ appendContextKeyword()

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

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

7533 {
7534  StringInfo buf = context->buf;
7535 
7536  if (PRETTY_INDENT(context))
7537  {
7538  int indentAmount;
7539 
7540  context->indentLevel += indentBefore;
7541 
7542  /* remove any trailing spaces currently in the buffer ... */
7544  /* ... then add a newline and some spaces */
7545  appendStringInfoChar(buf, '\n');
7546 
7547  if (context->indentLevel < PRETTYINDENT_LIMIT)
7548  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7549  else
7550  {
7551  /*
7552  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7553  * to conserve horizontal space by reducing the per-level
7554  * indentation. For best results the scale factor here should
7555  * divide all the indent amounts that get added to indentLevel
7556  * (PRETTYINDENT_STD, etc). It's important that the indentation
7557  * not grow unboundedly, else deeply-nested trees use O(N^2)
7558  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7559  */
7560  indentAmount = PRETTYINDENT_LIMIT +
7561  (context->indentLevel - PRETTYINDENT_LIMIT) /
7562  (PRETTYINDENT_STD / 2);
7563  indentAmount %= PRETTYINDENT_LIMIT;
7564  /* scale/wrap logic affects indentLevel, but not indentPlus */
7565  indentAmount += indentPlus;
7566  }
7567  appendStringInfoSpaces(buf, indentAmount);
7568 
7570 
7571  context->indentLevel += indentAfter;
7572  if (context->indentLevel < 0)
7573  context->indentLevel = 0;
7574  }
7575  else
7577 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7585
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:187
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:86
#define Max(x, y)
Definition: c.h:840
StringInfo buf
Definition: ruleutils.c:108

◆ colname_is_unique()

static bool colname_is_unique ( const char *  colname,
deparse_namespace dpns,
deparse_columns colinfo 
)
static

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

4141 {
4142  int i;
4143  ListCell *lc;
4144 
4145  /* Check against already-assigned column aliases within RTE */
4146  for (i = 0; i < colinfo->num_cols; i++)
4147  {
4148  char *oldname = colinfo->colnames[i];
4149 
4150  if (oldname && strcmp(oldname, colname) == 0)
4151  return false;
4152  }
4153 
4154  /*
4155  * If we're building a new_colnames array, check that too (this will be
4156  * partially but not completely redundant with the previous checks)
4157  */
4158  for (i = 0; i < colinfo->num_new_cols; i++)
4159  {
4160  char *oldname = colinfo->new_colnames[i];
4161 
4162  if (oldname && strcmp(oldname, colname) == 0)
4163  return false;
4164  }
4165 
4166  /* Also check against USING-column names that must be globally unique */
4167  foreach(lc, dpns->using_names)
4168  {
4169  char *oldname = (char *) lfirst(lc);
4170 
4171  if (strcmp(oldname, colname) == 0)
4172  return false;
4173  }
4174 
4175  /* Also check against names already assigned for parent-join USING cols */
4176  foreach(lc, colinfo->parentUsing)
4177  {
4178  char *oldname = (char *) lfirst(lc);
4179 
4180  if (strcmp(oldname, colname) == 0)
4181  return false;
4182  }
4183 
4184  return true;
4185 }
List * using_names
Definition: ruleutils.c:155
#define lfirst(lc)
Definition: pg_list.h:106
int i
List * parentUsing
Definition: ruleutils.c:249
char ** new_colnames
Definition: ruleutils.c:242
char ** colnames
Definition: ruleutils.c:225

◆ decompile_column_index_array()

static void decompile_column_index_array ( Datum  column_index_array,
Oid  relId,
StringInfo  buf 
)
static

Definition at line 2183 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2185 {
2186  Datum *keys;
2187  int nKeys;
2188  int j;
2189 
2190  /* Extract data from array of int16 */
2191  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2192  INT2OID, 2, true, 's',
2193  &keys, NULL, &nKeys);
2194 
2195  for (j = 0; j < nKeys; j++)
2196  {
2197  char *colName;
2198 
2199  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2200 
2201  if (j == 0)
2203  else
2204  appendStringInfo(buf, ", %s", quote_identifier(colName));
2205  }
2206 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define INT2OID
Definition: pg_type.h:308
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define DatumGetInt16(X)
Definition: postgres.h:427
uintptr_t Datum
Definition: postgres.h:365
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ deparse_context_for()

List* deparse_context_for ( const char *  aliasname,
Oid  relid 
)

Definition at line 3080 of file ruleutils.c.

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

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

3081 {
3082  deparse_namespace *dpns;
3083  RangeTblEntry *rte;
3084 
3085  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3086 
3087  /* Build a minimal RTE for the rel */
3088  rte = makeNode(RangeTblEntry);
3089  rte->rtekind = RTE_RELATION;
3090  rte->relid = relid;
3091  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3092  rte->alias = makeAlias(aliasname, NIL);
3093  rte->eref = rte->alias;
3094  rte->lateral = false;
3095  rte->inh = false;
3096  rte->inFromCl = true;
3097 
3098  /* Build one-element rtable */
3099  dpns->rtable = list_make1(rte);
3100  dpns->ctes = NIL;
3101  set_rtable_names(dpns, NIL, NULL);
3103 
3104  /* Return a one-deep namespace stack */
3105  return list_make1(dpns);
3106 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:1062
#define list_make1(x1)
Definition: pg_list.h:139
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:386
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3224
void * palloc0(Size size)
Definition: mcxt.c:864
#define makeNode(_type_)
Definition: nodes.h:561
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3437
RTEKind rtekind
Definition: parsenodes.h:959
Alias * eref
Definition: parsenodes.h:1063
#define RELKIND_RELATION
Definition: pg_class.h:160

◆ deparse_context_for_plan_rtable()

List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

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

3123 {
3124  deparse_namespace *dpns;
3125 
3126  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3127 
3128  /* Initialize fields that stay the same across the whole plan tree */
3129  dpns->rtable = rtable;
3130  dpns->rtable_names = rtable_names;
3131  dpns->ctes = NIL;
3132 
3133  /*
3134  * Set up column name aliases. We will get rather bogus results for join
3135  * RTEs, but that doesn't matter because plan trees don't contain any join
3136  * alias Vars.
3137  */
3139 
3140  /* Return a one-deep namespace stack */
3141  return list_make1(dpns);
3142 }
#define NIL
Definition: pg_list.h:69
List * rtable_names
Definition: ruleutils.c:150
#define list_make1(x1)
Definition: pg_list.h:139
void * palloc0(Size size)
Definition: mcxt.c:864
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3437

◆ deparse_expression()

char* deparse_expression ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit 
)

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

3023 {
3024  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3025  showimplicit, 0, 0);
3026 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3048

◆ deparse_expression_pretty()

static char * deparse_expression_pretty ( Node expr,
List dpcontext,
bool  forceprefix,
bool  showimplicit,
int  prettyFlags,
int  startIndent 
)
static

Definition at line 3048 of file ruleutils.c.

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

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

3051 {
3053  deparse_context context;
3054 
3055  initStringInfo(&buf);
3056  context.buf = &buf;
3057  context.namespaces = dpcontext;
3058  context.windowClause = NIL;
3059  context.windowTList = NIL;
3060  context.varprefix = forceprefix;
3061  context.prettyFlags = prettyFlags;
3062  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3063  context.indentLevel = startIndent;
3064  context.special_exprkind = EXPR_KIND_NONE;
3065 
3066  get_rule_expr(expr, &context, showimplicit);
3067 
3068  return buf.data;
3069 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:93
static char * buf
Definition: pg_test_fsync.c:67
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
List * windowTList
Definition: ruleutils.c:111
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
List * windowClause
Definition: ruleutils.c:110
StringInfo buf
Definition: ruleutils.c:108

◆ expand_colnames_array_to()

static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

Definition at line 4237 of file ruleutils.c.

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

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

4238 {
4239  if (n > colinfo->num_cols)
4240  {
4241  if (colinfo->colnames == NULL)
4242  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4243  else
4244  {
4245  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4246  n * sizeof(char *));
4247  memset(colinfo->colnames + colinfo->num_cols, 0,
4248  (n - colinfo->num_cols) * sizeof(char *));
4249  }
4250  colinfo->num_cols = n;
4251  }
4252 }
void * palloc0(Size size)
Definition: mcxt.c:864
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949
char ** colnames
Definition: ruleutils.c:225

◆ find_param_referent()

static Node * find_param_referent ( Param param,
deparse_context context,
deparse_namespace **  dpns_p,
ListCell **  ancestor_cell_p 
)
static

Definition at line 7105 of file ruleutils.c.

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

Referenced by get_name_for_var_field(), and get_parameter().

7107 {
7108  /* Initialize output parameters to prevent compiler warnings */
7109  *dpns_p = NULL;
7110  *ancestor_cell_p = NULL;
7111 
7112  /*
7113  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7114  * SubPlan argument. This will necessarily be in some ancestor of the
7115  * current expression's PlanState.
7116  */
7117  if (param->paramkind == PARAM_EXEC)
7118  {
7119  deparse_namespace *dpns;
7120  PlanState *child_ps;
7121  bool in_same_plan_level;
7122  ListCell *lc;
7123 
7124  dpns = (deparse_namespace *) linitial(context->namespaces);
7125  child_ps = dpns->planstate;
7126  in_same_plan_level = true;
7127 
7128  foreach(lc, dpns->ancestors)
7129  {
7130  PlanState *ps = (PlanState *) lfirst(lc);
7131  ListCell *lc2;
7132 
7133  /*
7134  * NestLoops transmit params to their inner child only; also, once
7135  * we've crawled up out of a subplan, this couldn't possibly be
7136  * the right match.
7137  */
7138  if (IsA(ps, NestLoopState) &&
7139  child_ps == innerPlanState(ps) &&
7140  in_same_plan_level)
7141  {
7142  NestLoop *nl = (NestLoop *) ps->plan;
7143 
7144  foreach(lc2, nl->nestParams)
7145  {
7146  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7147 
7148  if (nlp->paramno == param->paramid)
7149  {
7150  /* Found a match, so return it */
7151  *dpns_p = dpns;
7152  *ancestor_cell_p = lc;
7153  return (Node *) nlp->paramval;
7154  }
7155  }
7156  }
7157 
7158  /*
7159  * Check to see if we're crawling up from a subplan.
7160  */
7161  foreach(lc2, ps->subPlan)
7162  {
7163  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7164  SubPlan *subplan = sstate->subplan;
7165  ListCell *lc3;
7166  ListCell *lc4;
7167 
7168  if (child_ps != sstate->planstate)
7169  continue;
7170 
7171  /* Matched subplan, so check its arguments */
7172  forboth(lc3, subplan->parParam, lc4, subplan->args)
7173  {
7174  int paramid = lfirst_int(lc3);
7175  Node *arg = (Node *) lfirst(lc4);
7176 
7177  if (paramid == param->paramid)
7178  {
7179  /* Found a match, so return it */
7180  *dpns_p = dpns;
7181  *ancestor_cell_p = lc;
7182  return arg;
7183  }
7184  }
7185 
7186  /* Keep looking, but we are emerging from a subplan. */
7187  in_same_plan_level = false;
7188  break;
7189  }
7190 
7191  /*
7192  * Likewise check to see if we're emerging from an initplan.
7193  * Initplans never have any parParams, so no need to search that
7194  * list, but we need to know if we should reset
7195  * in_same_plan_level.
7196  */
7197  foreach(lc2, ps->initPlan)
7198  {
7199  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7200 
7201  if (child_ps != sstate->planstate)
7202  continue;
7203 
7204  /* No parameters to be had here. */
7205  Assert(sstate->subplan->parParam == NIL);
7206 
7207  /* Keep looking, but we are emerging from an initplan. */
7208  in_same_plan_level = false;
7209  break;
7210  }
7211 
7212  /* No luck, crawl up to next ancestor */
7213  child_ps = ps;
7214  }
7215  }
7216 
7217  /* No referent found */
7218  return NULL;
7219 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
List * nestParams
Definition: plannodes.h:688
List * initPlan
Definition: execnodes.h:889
List * subPlan
Definition: execnodes.h:891
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:513
Var * paramval
Definition: plannodes.h:695
#define linitial(l)
Definition: pg_list.h:111
struct PlanState * planstate
Definition: execnodes.h:778
SubPlan * subplan
Definition: execnodes.h:777
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:868
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:245
List * parParam
Definition: primnodes.h:709
PlanState * planstate
Definition: ruleutils.c:157
void * arg
#define innerPlanState(node)
Definition: execnodes.h:913
List * args
Definition: primnodes.h:710

◆ flatten_join_using_qual()

static void flatten_join_using_qual ( Node qual,
List **  leftvars,
List **  rightvars 
)
static

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

4389 {
4390  if (IsA(qual, BoolExpr))
4391  {
4392  /* Handle AND nodes by recursion */
4393  BoolExpr *b = (BoolExpr *) qual;
4394  ListCell *lc;
4395 
4396  Assert(b->boolop == AND_EXPR);
4397  foreach(lc, b->args)
4398  {
4400  leftvars, rightvars);
4401  }
4402  }
4403  else if (IsA(qual, OpExpr))
4404  {
4405  /* Otherwise we should have an equality operator */
4406  OpExpr *op = (OpExpr *) qual;
4407  Var *var;
4408 
4409  if (list_length(op->args) != 2)
4410  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4411  /* Arguments should be Vars with perhaps implicit coercions */
4412  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4413  if (!IsA(var, Var))
4414  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4415  (int) nodeTag(var));
4416  *leftvars = lappend(*leftvars, var);
4417  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4418  if (!IsA(var, Var))
4419  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4420  (int) nodeTag(var));
4421  *rightvars = lappend(*rightvars, var);
4422  }
4423  else
4424  {
4425  /* Perhaps we have an implicit coercion to boolean? */
4426  Node *q = strip_implicit_coercions(qual);
4427 
4428  if (q != qual)
4429  flatten_join_using_qual(q, leftvars, rightvars);
4430  else
4431  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4432  (int) nodeTag(qual));
4433  }
4434 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
Definition: nodes.h:513
Definition: primnodes.h:163
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:562
List * lappend(List *list, void *datum)
Definition: list.c:128
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:4388
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * args
Definition: primnodes.h:563
#define nodeTag(nodeptr)
Definition: nodes.h:518
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

Definition at line 10924 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

10925 {
10926  char *result = NULL;
10927  HeapTuple tuple;
10928  Datum reloptions;
10929  bool isnull;
10930 
10931  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10932  if (!HeapTupleIsValid(tuple))
10933  elog(ERROR, "cache lookup failed for relation %u", relid);
10934 
10935  reloptions = SysCacheGetAttr(RELOID, tuple,
10936  Anum_pg_class_reloptions, &isnull);
10937  if (!isnull)
10938  {
10940  Datum *options;
10941  int noptions;
10942  int i;
10943 
10944  initStringInfo(&buf);
10945 
10947  TEXTOID, -1, false, 'i',
10948  &options, NULL, &noptions);
10949 
10950  for (i = 0; i < noptions; i++)
10951  {
10952  char *option = TextDatumGetCString(options[i]);
10953  char *name;
10954  char *separator;
10955  char *value;
10956 
10957  /*
10958  * Each array element should have the form name=value. If the "="
10959  * is missing for some reason, treat it like an empty value.
10960  */
10961  name = option;
10962  separator = strchr(option, '=');
10963  if (separator)
10964  {
10965  *separator = '\0';
10966  value = separator + 1;
10967  }
10968  else
10969  value = "";
10970 
10971  if (i > 0)
10972  appendStringInfoString(&buf, ", ");
10973  appendStringInfo(&buf, "%s=", quote_identifier(name));
10974 
10975  /*
10976  * In general we need to quote the value; but to avoid unnecessary
10977  * clutter, do not quote if it is an identifier that would not
10978  * need quoting. (We could also allow numbers, but that is a bit
10979  * trickier than it looks --- for example, are leading zeroes
10980  * significant? We don't want to assume very much here about what
10981  * custom reloptions might mean.)
10982  */
10983  if (quote_identifier(value) == value)
10984  appendStringInfoString(&buf, value);
10985  else
10986  simple_quote_literal(&buf, value);
10987 
10988  pfree(option);
10989  }
10990 
10991  result = buf.data;
10992  }
10993 
10994  ReleaseSysCache(tuple);
10995 
10996  return result;
10997 }
static struct @130 value
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
#define TEXTOID
Definition: pg_type.h:324
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
void pfree(void *pointer)
Definition: mcxt.c:936
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9457
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
const char * name
Definition: encode.c:521
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
int i
#define elog
Definition: elog.h:219
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

Definition at line 10879 of file ruleutils.c.

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

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

10880 {
10881  HeapTuple tp;
10882  Form_pg_collation colltup;
10883  char *collname;
10884  char *nspname;
10885  char *result;
10886 
10887  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
10888  if (!HeapTupleIsValid(tp))
10889  elog(ERROR, "cache lookup failed for collation %u", collid);
10890  colltup = (Form_pg_collation) GETSTRUCT(tp);
10891  collname = NameStr(colltup->collname);
10892 
10893  if (!CollationIsVisible(collid))
10894  nspname = get_namespace_name(colltup->collnamespace);
10895  else
10896  nspname = NULL;
10897 
10898  result = quote_qualified_identifier(nspname, collname);
10899 
10900  ReleaseSysCache(tp);
10901 
10902  return result;
10903 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2008
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10521
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:52
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219

◆ generate_function_name()

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

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

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

10666 {
10667  char *result;
10668  HeapTuple proctup;
10669  Form_pg_proc procform;
10670  char *proname;
10671  bool use_variadic;
10672  char *nspname;
10673  FuncDetailCode p_result;
10674  Oid p_funcid;
10675  Oid p_rettype;
10676  bool p_retset;
10677  int p_nvargs;
10678  Oid p_vatype;
10679  Oid *p_true_typeids;
10680  bool force_qualify = false;
10681 
10682  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10683  if (!HeapTupleIsValid(proctup))
10684  elog(ERROR, "cache lookup failed for function %u", funcid);
10685  procform = (Form_pg_proc) GETSTRUCT(proctup);
10686  proname = NameStr(procform->proname);
10687 
10688  /*
10689  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10690  * qualification in some special cases.
10691  */
10692  if (special_exprkind == EXPR_KIND_GROUP_BY)
10693  {
10694  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10695  force_qualify = true;
10696  }
10697 
10698  /*
10699  * Determine whether VARIADIC should be printed. We must do this first
10700  * since it affects the lookup rules in func_get_detail().
10701  *
10702  * Currently, we always print VARIADIC if the function has a merged
10703  * variadic-array argument. Note that this is always the case for
10704  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10705  *
10706  * In principle, if VARIADIC wasn't originally specified and the array
10707  * actual argument is deconstructable, we could print the array elements
10708  * separately and not print VARIADIC, thus more nearly reproducing the
10709  * original input. For the moment that seems like too much complication
10710  * for the benefit, and anyway we do not know whether VARIADIC was
10711  * originally specified if it's a non-ANY type.
10712  */
10713  if (use_variadic_p)
10714  {
10715  /* Parser should not have set funcvariadic unless fn is variadic */
10716  Assert(!has_variadic || OidIsValid(procform->provariadic));
10717  use_variadic = has_variadic;
10718  *use_variadic_p = use_variadic;
10719  }
10720  else
10721  {
10722  Assert(!has_variadic);
10723  use_variadic = false;
10724  }
10725 
10726  /*
10727  * The idea here is to schema-qualify only if the parser would fail to
10728  * resolve the correct function given the unqualified func name with the
10729  * specified argtypes and VARIADIC flag. But if we already decided to
10730  * force qualification, then we can skip the lookup and pretend we didn't
10731  * find it.
10732  */
10733  if (!force_qualify)
10734  p_result = func_get_detail(list_make1(makeString(proname)),
10735  NIL, argnames, nargs, argtypes,
10736  !use_variadic, true,
10737  &p_funcid, &p_rettype,
10738  &p_retset, &p_nvargs, &p_vatype,
10739  &p_true_typeids, NULL);
10740  else
10741  {
10742  p_result = FUNCDETAIL_NOTFOUND;
10743  p_funcid = InvalidOid;
10744  }
10745 
10746  if ((p_result == FUNCDETAIL_NORMAL ||
10747  p_result == FUNCDETAIL_AGGREGATE ||
10748  p_result == FUNCDETAIL_WINDOWFUNC) &&
10749  p_funcid == funcid)
10750  nspname = NULL;
10751  else
10752  nspname = get_namespace_name(procform->pronamespace);
10753 
10754  result = quote_qualified_identifier(nspname, proname);
10755 
10756  ReleaseSysCache(proctup);
10757 
10758  return result;
10759 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define list_make1(x1)
Definition: pg_list.h:139
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10521
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
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:1312
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219

◆ generate_operator_name()

static char * generate_operator_name ( Oid  operid,
Oid  arg1,
Oid  arg2 
)
static

Definition at line 10773 of file ruleutils.c.

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

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

10774 {
10776  HeapTuple opertup;
10777  Form_pg_operator operform;
10778  char *oprname;
10779  char *nspname;
10780  Operator p_result;
10781 
10782  initStringInfo(&buf);
10783 
10784  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10785  if (!HeapTupleIsValid(opertup))
10786  elog(ERROR, "cache lookup failed for operator %u", operid);
10787  operform = (Form_pg_operator) GETSTRUCT(opertup);
10788  oprname = NameStr(operform->oprname);
10789 
10790  /*
10791  * The idea here is to schema-qualify only if the parser would fail to
10792  * resolve the correct operator given the unqualified op name with the
10793  * specified argtypes.
10794  */
10795  switch (operform->oprkind)
10796  {
10797  case 'b':
10798  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10799  true, -1);
10800  break;
10801  case 'l':
10802  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10803  true, -1);
10804  break;
10805  case 'r':
10806  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10807  true, -1);
10808  break;
10809  default:
10810  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10811  p_result = NULL; /* keep compiler quiet */
10812  break;
10813  }
10814 
10815  if (p_result != NULL && oprid(p_result) == operid)
10816  nspname = NULL;
10817  else
10818  {
10819  nspname = get_namespace_name(operform->oprnamespace);
10820  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10821  }
10822 
10823  appendStringInfoString(&buf, oprname);
10824 
10825  if (nspname)
10826  appendStringInfoChar(&buf, ')');
10827 
10828  if (p_result != NULL)
10829  ReleaseSysCache(p_result);
10830 
10831  ReleaseSysCache(opertup);
10832 
10833  return buf.data;
10834 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define list_make1(x1)
Definition: pg_list.h:139
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:604
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:525
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:57
#define NameStr(name)
Definition: c.h:565
#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

◆ generate_qualified_relation_name()

static char * generate_qualified_relation_name ( Oid  relid)
static

Definition at line 10621 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker(), and pg_get_serial_sequence().

10622 {
10623  HeapTuple tp;
10624  Form_pg_class reltup;
10625  char *relname;
10626  char *nspname;
10627  char *result;
10628 
10629  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10630  if (!HeapTupleIsValid(tp))
10631  elog(ERROR, "cache lookup failed for relation %u", relid);
10632  reltup = (Form_pg_class) GETSTRUCT(tp);
10633  relname = NameStr(reltup->relname);
10634 
10635  nspname = get_namespace_name(reltup->relnamespace);
10636  if (!nspname)
10637  elog(ERROR, "cache lookup failed for namespace %u",
10638  reltup->relnamespace);
10639 
10640  result = quote_qualified_identifier(nspname, relname);
10641 
10642  ReleaseSysCache(tp);
10643 
10644  return result;
10645 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10521
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

Definition at line 10846 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

10847 {
10848  HeapTuple tp;
10849  Form_pg_type typtup;
10850  char *typname;
10851  char *nspname;
10852  char *result;
10853 
10855  if (!HeapTupleIsValid(tp))
10856  elog(ERROR, "cache lookup failed for type %u", typid);
10857  typtup = (Form_pg_type) GETSTRUCT(tp);
10858  typname = NameStr(typtup->typname);
10859 
10860  nspname = get_namespace_name(typtup->typnamespace);
10861  if (!nspname)
10862  elog(ERROR, "cache lookup failed for namespace %u",
10863  typtup->typnamespace);
10864 
10865  result = quote_qualified_identifier(nspname, typname);
10866 
10867  ReleaseSysCache(tp);
10868 
10869  return result;
10870 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10521
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219

◆ generate_relation_name()

static char * generate_relation_name ( Oid  relid,
List namespaces 
)
static

Definition at line 10561 of file ruleutils.c.

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

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

10562 {
10563  HeapTuple tp;
10564  Form_pg_class reltup;
10565  bool need_qual;
10566  ListCell *nslist;
10567  char *relname;
10568  char *nspname;
10569  char *result;
10570 
10571  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10572  if (!HeapTupleIsValid(tp))
10573  elog(ERROR, "cache lookup failed for relation %u", relid);
10574  reltup = (Form_pg_class) GETSTRUCT(tp);
10575  relname = NameStr(reltup->relname);
10576 
10577  /* Check for conflicting CTE name */
10578  need_qual = false;
10579  foreach(nslist, namespaces)
10580  {
10581  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10582  ListCell *ctlist;
10583 
10584  foreach(ctlist, dpns->ctes)
10585  {
10586  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10587 
10588  if (strcmp(cte->ctename, relname) == 0)
10589  {
10590  need_qual = true;
10591  break;
10592  }
10593  }
10594  if (need_qual)
10595  break;
10596  }
10597 
10598  /* Otherwise, qualify the name if not visible in search path */
10599  if (!need_qual)
10600  need_qual = !RelationIsVisible(relid);
10601 
10602  if (need_qual)
10603  nspname = get_namespace_name(reltup->relnamespace);
10604  else
10605  nspname = NULL;
10606 
10607  result = quote_qualified_identifier(nspname, relname);
10608 
10609  ReleaseSysCache(tp);
10610 
10611  return result;
10612 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10521
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
bool RelationIsVisible(Oid relid)
Definition: namespace.c:682
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219

◆ get_agg_combine_expr()

static void get_agg_combine_expr ( Node node,
deparse_context context,
void *  private 
)
static

Definition at line 9153 of file ruleutils.c.

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

Referenced by get_agg_expr().

9154 {
9155  Aggref *aggref;
9156  Aggref *original_aggref = private;
9157 
9158  if (!IsA(node, Aggref))
9159  elog(ERROR, "combining Aggref does not point to an Aggref");
9160 
9161  aggref = (Aggref *) node;
9162  get_agg_expr(aggref, context, original_aggref);
9163 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9047
#define elog
Definition: elog.h:219

◆ get_agg_expr()

static void get_agg_expr ( Aggref aggref,
deparse_context context,
Aggref original_aggref 
)
static

Definition at line 9047 of file ruleutils.c.

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

Referenced by get_agg_combine_expr(), and get_rule_expr().

9049 {
9050  StringInfo buf = context->buf;
9051  Oid argtypes[FUNC_MAX_ARGS];
9052  int nargs;
9053  bool use_variadic;
9054 
9055  /*
9056  * For a combining aggregate, we look up and deparse the corresponding
9057  * partial aggregate instead. This is necessary because our input
9058  * argument list has been replaced; the new argument list always has just
9059  * one element, which will point to a partial Aggref that supplies us with
9060  * transition states to combine.
9061  */
9062  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9063  {
9064  TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
9065 
9066  Assert(list_length(aggref->args) == 1);
9067  resolve_special_varno((Node *) tle->expr, context, original_aggref,
9069  return;
9070  }
9071 
9072  /*
9073  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9074  * to avoid printing this when recursing from the code just above.
9075  */
9076  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9077  appendStringInfoString(buf, "PARTIAL ");
9078 
9079  /* Extract the argument types as seen by the parser */
9080  nargs = get_aggregate_argtypes(aggref, argtypes);
9081 
9082  /* Print the aggregate name, schema-qualified if needed */
9083  appendStringInfo(buf, "%s(%s",
9084  generate_function_name(aggref->aggfnoid, nargs,
9085  NIL, argtypes,
9086  aggref->aggvariadic,
9087  &use_variadic,
9088  context->special_exprkind),
9089  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9090 
9091  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9092  {
9093  /*
9094  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9095  * worry about inserting VARIADIC. So we can just dump the direct
9096  * args as-is.
9097  */
9098  Assert(!aggref->aggvariadic);
9099  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9100  Assert(aggref->aggorder != NIL);
9101  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9102  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9103  }
9104  else
9105  {
9106  /* aggstar can be set only in zero-argument aggregates */
9107  if (aggref->aggstar)
9108  appendStringInfoChar(buf, '*');
9109  else
9110  {
9111  ListCell *l;
9112  int i;
9113 
9114  i = 0;
9115  foreach(l, aggref->args)
9116  {
9117  TargetEntry *tle = (TargetEntry *) lfirst(l);
9118  Node *arg = (Node *) tle->expr;
9119 
9120  Assert(!IsA(arg, NamedArgExpr));
9121  if (tle->resjunk)
9122  continue;
9123  if (i++ > 0)
9124  appendStringInfoString(buf, ", ");
9125  if (use_variadic && i == nargs)
9126  appendStringInfoString(buf, "VARIADIC ");
9127  get_rule_expr(arg, context, true);
9128  }
9129  }
9130 
9131  if (aggref->aggorder != NIL)
9132  {
9133  appendStringInfoString(buf, " ORDER BY ");
9134  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9135  }
9136  }
9137 
9138  if (aggref->aggfilter != NULL)
9139  {
9140  appendStringInfoString(buf, ") FILTER (WHERE ");
9141  get_rule_expr((Node *) aggref->aggfilter, context, false);
9142  }
9143 
9144  appendStringInfoChar(buf, ')');
9145 }
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:10663
bool aggvariadic
Definition: primnodes.h:306
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6648
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5750
Definition: nodes.h:513
List * args
Definition: primnodes.h:301
bool aggstar
Definition: primnodes.h:305
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:114
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:772
#define FUNC_MAX_ARGS
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:133
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1382
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * aggorder
Definition: primnodes.h:302
List * aggdirectargs
Definition: primnodes.h:300
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
Oid aggfnoid
Definition: primnodes.h:294
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:9153
#define Assert(condition)
Definition: c.h:688
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
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:773
Expr * aggfilter
Definition: primnodes.h:304
StringInfo buf
Definition: ruleutils.c:108
int i
void * arg
char aggkind
Definition: primnodes.h:308
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1820

◆ get_basic_select_query()

static void get_basic_select_query ( Query query,
deparse_context context,
TupleDesc  resultDesc 
)
static

Definition at line 5243 of file ruleutils.c.

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

Referenced by get_select_query_def().

5245 {
5246  StringInfo buf = context->buf;
5247  RangeTblEntry *values_rte;
5248  char *sep;
5249  ListCell *l;
5250 
5251  if (PRETTY_INDENT(context))
5252  {
5253  context->indentLevel += PRETTYINDENT_STD;
5254  appendStringInfoChar(buf, ' ');
5255  }
5256 
5257  /*
5258  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5259  * VALUES part. This reverses what transformValuesClause() did at parse
5260  * time.
5261  */
5262  values_rte = get_simple_values_rte(query);
5263  if (values_rte)
5264  {
5265  get_values_def(values_rte->values_lists, context);
5266  return;
5267  }
5268 
5269  /*
5270  * Build up the query string - first we say SELECT
5271  */
5272  appendStringInfoString(buf, "SELECT");
5273 
5274  /* Add the DISTINCT clause if given */
5275  if (query->distinctClause != NIL)
5276  {
5277  if (query->hasDistinctOn)
5278  {
5279  appendStringInfoString(buf, " DISTINCT ON (");
5280  sep = "";
5281  foreach(l, query->distinctClause)
5282  {
5283  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5284 
5285  appendStringInfoString(buf, sep);
5287  false, context);
5288  sep = ", ";
5289  }
5290  appendStringInfoChar(buf, ')');
5291  }
5292  else
5293  appendStringInfoString(buf, " DISTINCT");
5294  }
5295 
5296  /* Then we tell what to select (the targetlist) */
5297  get_target_list(query->targetList, context, resultDesc);
5298 
5299  /* Add the FROM clause if needed */
5300  get_from_clause(query, " FROM ", context);
5301 
5302  /* Add the WHERE clause if given */
5303  if (query->jointree->quals != NULL)
5304  {
5305  appendContextKeyword(context, " WHERE ",
5307  get_rule_expr(query->jointree->quals, context, false);
5308  }
5309 
5310  /* Add the GROUP BY clause if given */
5311  if (query->groupClause != NULL || query->groupingSets != NULL)
5312  {
5313  ParseExprKind save_exprkind;
5314 
5315  appendContextKeyword(context, " GROUP BY ",
5317 
5318  save_exprkind = context->special_exprkind;
5320 
5321  if (query->groupingSets == NIL)
5322  {
5323  sep = "";
5324  foreach(l, query->groupClause)
5325  {
5326  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5327 
5328  appendStringInfoString(buf, sep);
5330  false, context);
5331  sep = ", ";
5332  }
5333  }
5334  else
5335  {
5336  sep = "";
5337  foreach(l, query->groupingSets)
5338  {
5339  GroupingSet *grp = lfirst(l);
5340 
5341  appendStringInfoString(buf, sep);
5342  get_rule_groupingset(grp, query->targetList, true, context);
5343  sep = ", ";
5344  }
5345  }
5346 
5347  context->special_exprkind = save_exprkind;
5348  }
5349 
5350  /* Add the HAVING clause if given */
5351  if (query->havingQual != NULL)
5352  {
5353  appendContextKeyword(context, " HAVING ",
5355  get_rule_expr(query->havingQual, context, false);
5356  }
5357 
5358  /* Add the WINDOW clause if needed */
5359  if (query->windowClause != NIL)
5360  get_rule_windowclause(query, context);
5361 }
#define NIL
Definition: pg_list.h:69
FromExpr * jointree
Definition: parsenodes.h:136
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5370
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5634
Index tleSortGroupRef
Definition: parsenodes.h:1204
List * groupingSets
Definition: parsenodes.h:148
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9727
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5808
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:1024
Node * quals
Definition: primnodes.h:1479
bool hasDistinctOn
Definition: parsenodes.h:127
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
List * distinctClause
Definition: parsenodes.h:154
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7531
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5690
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
ParseExprKind special_exprkind
Definition: ruleutils.c:116
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4959
List * groupClause
Definition: parsenodes.h:146
StringInfo buf
Definition: ruleutils.c:108
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:5187
Node * havingQual
Definition: parsenodes.h:150

◆ get_coercion_expr()

static void get_coercion_expr ( Node arg,
deparse_context context,
Oid  resulttype,
int32  resulttypmod,
Node parentNode 
)
static

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

9249 {
9250  StringInfo buf = context->buf;
9251 
9252  /*
9253  * Since parse_coerce.c doesn't immediately collapse application of
9254  * length-coercion functions to constants, what we'll typically see in
9255  * such cases is a Const with typmod -1 and a length-coercion function
9256  * right above it. Avoid generating redundant output. However, beware of
9257  * suppressing casts when the user actually wrote something like
9258  * 'foo'::text::char(3).
9259  *
9260  * Note: it might seem that we are missing the possibility of needing to
9261  * print a COLLATE clause for such a Const. However, a Const could only
9262  * have nondefault collation in a post-constant-folding tree, in which the
9263  * length coercion would have been folded too. See also the special
9264  * handling of CollateExpr in coerce_to_target_type(): any collation
9265  * marking will be above the coercion node, not below it.
9266  */
9267  if (arg && IsA(arg, Const) &&
9268  ((Const *) arg)->consttype == resulttype &&
9269  ((Const *) arg)->consttypmod == -1)
9270  {
9271  /* Show the constant without normal ::typename decoration */
9272  get_const_expr((Const *) arg, context, -1);
9273  }
9274  else
9275  {
9276  if (!PRETTY_PAREN(context))
9277  appendStringInfoChar(buf, '(');
9278  get_rule_expr_paren(arg, context, false, parentNode);
9279  if (!PRETTY_PAREN(context))
9280  appendStringInfoChar(buf, ')');
9281  }
9282  appendStringInfo(buf, "::%s",
9283  format_type_with_typemod(resulttype, resulttypmod));
9284 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7604
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9302
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:339
StringInfo buf
Definition: ruleutils.c:108

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

10149 {
10150  StringInfo buf = context->buf;
10151  int i;
10152  bool first = true;
10153 
10154  /* Don't print aliases if not needed */
10155  if (!colinfo->printaliases)
10156  return;
10157 
10158  for (i = 0; i < colinfo->num_new_cols; i++)
10159  {
10160  char *colname = colinfo->new_colnames[i];
10161 
10162  if (first)
10163  {
10164  appendStringInfoChar(buf, '(');
10165  first = false;
10166  }
10167  else
10168  appendStringInfoString(buf, ", ");
10170  }
10171  if (!first)
10172  appendStringInfoChar(buf, ')');
10173 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: ruleutils.c:108
int i
char ** new_colnames
Definition: ruleutils.c:242

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9438 {
9439  StringInfo buf = context->buf;
9440 
9441  if (OidIsValid(constval->constcollid))
9442  {
9443  Oid typcollation = get_typcollation(constval->consttype);
9444 
9445  if (constval->constcollid != typcollation)
9446  {
9447  appendStringInfo(buf, " COLLATE %s",
9449  }
9450  }
9451 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10879
Oid consttype
Definition: primnodes.h:192
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
Oid constcollid
Definition: primnodes.h:194
static char * buf
Definition: pg_test_fsync.c:67
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2799
StringInfo buf
Definition: ruleutils.c:108

◆ get_const_expr()

static void get_const_expr ( Const constval,
deparse_context context,
int  showtype 
)
static

Definition at line 9302 of file ruleutils.c.

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

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

9303 {
9304  StringInfo buf = context->buf;
9305  Oid typoutput;
9306  bool typIsVarlena;
9307  char *extval;
9308  bool needlabel = false;
9309 
9310  if (constval->constisnull)
9311  {
9312  /*
9313  * Always label the type of a NULL constant to prevent misdecisions
9314  * about type when reparsing.
9315  */
9316  appendStringInfoString(buf, "NULL");
9317  if (showtype >= 0)
9318  {
9319  appendStringInfo(buf, "::%s",
9321  constval->consttypmod));
9322  get_const_collation(constval, context);
9323  }
9324  return;
9325  }
9326 
9327  getTypeOutputInfo(constval->consttype,
9328  &typoutput, &typIsVarlena);
9329 
9330  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9331 
9332  switch (constval->consttype)
9333  {
9334  case INT4OID:
9335 
9336  /*
9337  * INT4 can be printed without any decoration, unless it is
9338  * negative; in that case print it as '-nnn'::integer to ensure
9339  * that the output will re-parse as a constant, not as a constant
9340  * plus operator. In most cases we could get away with printing
9341  * (-nnn) instead, because of the way that gram.y handles negative
9342  * literals; but that doesn't work for INT_MIN, and it doesn't
9343  * seem that much prettier anyway.
9344  */
9345  if (extval[0] != '-')
9346  appendStringInfoString(buf, extval);
9347  else
9348  {
9349  appendStringInfo(buf, "'%s'", extval);
9350  needlabel = true; /* we must attach a cast */
9351  }
9352  break;
9353 
9354  case NUMERICOID:
9355 
9356  /*
9357  * NUMERIC can be printed without quotes if it looks like a float
9358  * constant (not an integer, and not Infinity or NaN) and doesn't
9359  * have a leading sign (for the same reason as for INT4).
9360  */
9361  if (isdigit((unsigned char) extval[0]) &&
9362  strcspn(extval, "eE.") != strlen(extval))
9363  {
9364  appendStringInfoString(buf, extval);
9365  }
9366  else
9367  {
9368  appendStringInfo(buf, "'%s'", extval);
9369  needlabel = true; /* we must attach a cast */
9370  }
9371  break;
9372 
9373  case BITOID:
9374  case VARBITOID:
9375  appendStringInfo(buf, "B'%s'", extval);
9376  break;
9377 
9378  case BOOLOID:
9379  if (strcmp(extval, "t") == 0)
9380  appendStringInfoString(buf, "true");
9381  else
9382  appendStringInfoString(buf, "false");
9383  break;
9384 
9385  default:
9386  simple_quote_literal(buf, extval);
9387  break;
9388  }
9389 
9390  pfree(extval);
9391 
9392  if (showtype < 0)
9393  return;
9394 
9395  /*
9396  * For showtype == 0, append ::typename unless the constant will be
9397  * implicitly typed as the right type when it is read in.
9398  *
9399  * XXX this code has to be kept in sync with the behavior of the parser,
9400  * especially make_const.
9401  */
9402  switch (constval->consttype)
9403  {
9404  case BOOLOID:
9405  case UNKNOWNOID:
9406  /* These types can be left unlabeled */
9407  needlabel = false;
9408  break;
9409  case INT4OID:
9410  /* We determined above whether a label is needed */
9411  break;
9412  case NUMERICOID:
9413 
9414  /*
9415  * Float-looking constants will be typed as numeric, which we
9416  * checked above; but if there's a nondefault typmod we need to
9417  * show it.
9418  */
9419  needlabel |= (constval->consttypmod >= 0);
9420  break;
9421  default:
9422  needlabel = true;
9423  break;
9424  }
9425  if (needlabel || showtype > 0)
9426  appendStringInfo(buf, "::%s",
9428  constval->consttypmod));
9429 
9430  get_const_collation(constval, context);
9431 }
Datum constvalue
Definition: primnodes.h:196
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
#define NUMERICOID
Definition: pg_type.h:554
#define INT4OID
Definition: pg_type.h:316
#define VARBITOID
Definition: pg_type.h:546
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:192
void pfree(void *pointer)
Definition: mcxt.c:936
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9457
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9437
static char * buf
Definition: pg_test_fsync.c:67
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:339
#define BITOID
Definition: pg_type.h:542
#define BOOLOID
Definition: pg_type.h:288
#define UNKNOWNOID
Definition: pg_type.h:431
int32 consttypmod
Definition: primnodes.h:193
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
StringInfo buf
Definition: ruleutils.c:108
bool constisnull
Definition: primnodes.h:197

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

Definition at line 6369 of file ruleutils.c.

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

Referenced by get_query_def().

6370 {
6371  StringInfo buf = context->buf;
6372  RangeTblEntry *rte;
6373 
6374  /* Insert the WITH clause if given */
6375  get_with_clause(query, context);
6376 
6377  /*
6378  * Start the query with DELETE FROM relname
6379  */
6380  rte = rt_fetch(query->resultRelation, query->rtable);
6381  Assert(rte->rtekind == RTE_RELATION);
6382  if (PRETTY_INDENT(context))
6383  {
6384  appendStringInfoChar(buf, ' ');
6385  context->indentLevel += PRETTYINDENT_STD;
6386  }
6387  appendStringInfo(buf, "DELETE FROM %s%s",
6388  only_marker(rte),
6390  if (rte->alias != NULL)
6391  appendStringInfo(buf, " %s",
6393 
6394  /* Add the USING clause if given */
6395  get_from_clause(query, " USING ", context);
6396 
6397  /* Add a WHERE clause if given */
6398  if (query->jointree->quals != NULL)
6399  {
6400  appendContextKeyword(context, " WHERE ",
6402  get_rule_expr(query->jointree->quals, context, false);
6403  }
6404 
6405  /* Add RETURNING if present */
6406  if (query->returningList)
6407  {
6408  appendContextKeyword(context, " RETURNING",
6410  get_target_list(query->returningList, context, NULL);
6411  }
6412 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5002
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
Alias * alias
Definition: parsenodes.h:1062
FromExpr * jointree
Definition: parsenodes.h:136
int resultRelation
Definition: parsenodes.h:120
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5370
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9727
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
Node * quals
Definition: primnodes.h:1479
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10561
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
List * rtable
Definition: parsenodes.h:135
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7531
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define Assert(condition)
Definition: c.h:688
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:467
RTEKind rtekind
Definition: parsenodes.h:959
StringInfo buf
Definition: ruleutils.c:108

◆ get_from_clause()

static void get_from_clause ( Query query,
const char *  prefix,
deparse_context context 
)
static

Definition at line 9727 of file ruleutils.c.

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

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

9728 {
9729  StringInfo buf = context->buf;
9730  bool first = true;
9731  ListCell *l;
9732 
9733  /*
9734  * We use the query's jointree as a guide to what to print. However, we
9735  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9736  * only appear at the top level of the jointree, so it's sufficient to
9737  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9738  * for NEW and OLD.
9739  */
9740  foreach(l, query->jointree->fromlist)
9741  {
9742  Node *jtnode = (Node *) lfirst(l);
9743 
9744  if (IsA(jtnode, RangeTblRef))
9745  {
9746  int varno = ((RangeTblRef *) jtnode)->rtindex;
9747  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9748 
9749  if (!rte->inFromCl)
9750  continue;
9751  }
9752 
9753  if (first)
9754  {
9755  appendContextKeyword(context, prefix,
9757  first = false;
9758 
9759  get_from_clause_item(jtnode, query, context);
9760  }
9761  else
9762  {
9763  StringInfoData itembuf;
9764 
9765  appendStringInfoString(buf, ", ");
9766 
9767  /*
9768  * Put the new FROM item's text into itembuf so we can decide
9769  * after we've got it whether or not it needs to go on a new line.
9770  */
9771  initStringInfo(&itembuf);
9772  context->buf = &itembuf;
9773 
9774  get_from_clause_item(jtnode, query, context);
9775 
9776  /* Restore context's output buffer */
9777  context->buf = buf;
9778 
9779  /* Consider line-wrapping if enabled */
9780  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9781  {
9782  /* Does the new item start with a new line? */
9783  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9784  {
9785  /* If so, we shouldn't add anything */
9786  /* instead, remove any trailing spaces currently in buf */
9788  }
9789  else
9790  {
9791  char *trailing_nl;
9792 
9793  /* Locate the start of the current line in the buffer */
9794  trailing_nl = strrchr(buf->data, '\n');
9795  if (trailing_nl == NULL)
9796  trailing_nl = buf->data;
9797  else
9798  trailing_nl++;
9799 
9800  /*
9801  * Add a newline, plus some indentation, if the new item
9802  * would cause an overflow.
9803  */
9804  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9805  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9808  }
9809  }
9810 
9811  /* Add the new item */
9812  appendStringInfoString(buf, itembuf.data);
9813 
9814  /* clean up */
9815  pfree(itembuf.data);
9816  }
9817  }
9818 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
FromExpr * jointree
Definition: parsenodes.h:136
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
Definition: nodes.h:513
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
List * fromlist
Definition: primnodes.h:1478
void pfree(void *pointer)
Definition: mcxt.c:936
List * rtable
Definition: parsenodes.h:135
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7531
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7585
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9821

◆ get_from_clause_coldeflist()

static void get_from_clause_coldeflist ( RangeTblFunction rtfunc,
deparse_columns colinfo,
deparse_context context 
)
static

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

10191 {
10192  StringInfo buf = context->buf;
10193  ListCell *l1;
10194  ListCell *l2;
10195  ListCell *l3;
10196  ListCell *l4;
10197  int i;
10198 
10199  appendStringInfoChar(buf, '(');
10200 
10201  /* there's no forfour(), so must chase one list the hard way */
10202  i = 0;
10203  l4 = list_head(rtfunc->funccolnames);
10204  forthree(l1, rtfunc->funccoltypes,
10205  l2, rtfunc->funccoltypmods,
10206  l3, rtfunc->funccolcollations)
10207  {
10208  Oid atttypid = lfirst_oid(l1);
10209  int32 atttypmod = lfirst_int(l2);
10210  Oid attcollation = lfirst_oid(l3);
10211  char *attname;
10212 
10213  if (colinfo)
10214  attname = colinfo->colnames[i];
10215  else
10216  attname = strVal(lfirst(l4));
10217 
10218  Assert(attname); /* shouldn't be any dropped columns here */
10219 
10220  if (i > 0)
10221  appendStringInfoString(buf, ", ");
10222  appendStringInfo(buf, "%s %s",
10223  quote_identifier(attname),
10224  format_type_with_typemod(atttypid, atttypmod));
10225  if (OidIsValid(attcollation) &&
10226  attcollation != get_typcollation(atttypid))
10227  appendStringInfo(buf, " COLLATE %s",
10228  generate_collation_name(attcollation));
10229 
10230  l4 = lnext(l4);
10231  i++;
10232  }
10233 
10234  appendStringInfoChar(buf, ')');
10235 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:203
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:10879
signed int int32
Definition: c.h:302
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:339
List * funccoltypmods
Definition: parsenodes.h:1100
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2799
List * funccolcollations
Definition: parsenodes.h:1101
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
int i
#define lfirst_oid(lc)
Definition: pg_list.h:108
char ** colnames
Definition: ruleutils.c:225

◆ get_from_clause_item()

static void get_from_clause_item ( Node jtnode,
Query query,
deparse_context context 
)
static

Definition at line 9821 of file ruleutils.c.

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

Referenced by get_from_clause().

9822 {
9823  StringInfo buf = context->buf;
9825 
9826  if (IsA(jtnode, RangeTblRef))
9827  {
9828  int varno = ((RangeTblRef *) jtnode)->rtindex;
9829  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9830  char *refname = get_rtable_name(varno, context);
9831  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9832  RangeTblFunction *rtfunc1 = NULL;
9833  bool printalias;
9834 
9835  if (rte->lateral)
9836  appendStringInfoString(buf, "LATERAL ");
9837 
9838  /* Print the FROM item proper */
9839  switch (rte->rtekind)
9840  {
9841  case RTE_RELATION:
9842  /* Normal relation RTE */
9843  appendStringInfo(buf, "%s%s",
9844  only_marker(rte),
9846  context->namespaces));
9847  break;
9848  case RTE_SUBQUERY:
9849  /* Subquery RTE */
9850  appendStringInfoChar(buf, '(');
9851  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9852  context->prettyFlags, context->wrapColumn,
9853  context->indentLevel);
9854  appendStringInfoChar(buf, ')');
9855  break;
9856  case RTE_FUNCTION:
9857  /* Function RTE */
9858  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9859 
9860  /*
9861  * Omit ROWS FROM() syntax for just one function, unless it
9862  * has both a coldeflist and WITH ORDINALITY. If it has both,
9863  * we must use ROWS FROM() syntax to avoid ambiguity about
9864  * whether the coldeflist includes the ordinality column.
9865  */
9866  if (list_length(rte->functions) == 1 &&
9867  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9868  {
9869  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
9870  /* we'll print the coldeflist below, if it has one */
9871  }
9872  else
9873  {
9874  bool all_unnest;
9875  ListCell *lc;
9876 
9877  /*
9878  * If all the function calls in the list are to unnest,
9879  * and none need a coldeflist, then collapse the list back
9880  * down to UNNEST(args). (If we had more than one
9881  * built-in unnest function, this would get more
9882  * difficult.)
9883  *
9884  * XXX This is pretty ugly, since it makes not-terribly-
9885  * future-proof assumptions about what the parser would do
9886  * with the output; but the alternative is to emit our
9887  * nonstandard ROWS FROM() notation for what might have
9888  * been a perfectly spec-compliant multi-argument
9889  * UNNEST().
9890  */
9891  all_unnest = true;
9892  foreach(lc, rte->functions)
9893  {
9894  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9895 
9896  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9897  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9898  rtfunc->funccolnames != NIL)
9899  {
9900  all_unnest = false;
9901  break;
9902  }
9903  }
9904 
9905  if (all_unnest)
9906  {
9907  List *allargs = NIL;
9908 
9909  foreach(lc, rte->functions)
9910  {
9911  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9912  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9913 
9914  allargs = list_concat(allargs, list_copy(args));
9915  }
9916 
9917  appendStringInfoString(buf, "UNNEST(");
9918  get_rule_expr((Node *) allargs, context, true);
9919  appendStringInfoChar(buf, ')');
9920  }
9921  else
9922  {
9923  int funcno = 0;
9924 
9925  appendStringInfoString(buf, "ROWS FROM(");
9926  foreach(lc, rte->functions)
9927  {
9928  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9929 
9930  if (funcno > 0)
9931  appendStringInfoString(buf, ", ");
9932  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
9933  if (rtfunc->funccolnames != NIL)
9934  {
9935  /* Reconstruct the column definition list */
9936  appendStringInfoString(buf, " AS ");
9938  NULL,
9939  context);
9940  }
9941  funcno++;
9942  }
9943  appendStringInfoChar(buf, ')');
9944  }
9945  /* prevent printing duplicate coldeflist below */
9946  rtfunc1 = NULL;
9947  }
9948  if (rte->funcordinality)
9949  appendStringInfoString(buf, " WITH ORDINALITY");
9950  break;
9951  case RTE_TABLEFUNC:
9952  get_tablefunc(rte->tablefunc, context, true);
9953  break;
9954  case RTE_VALUES:
9955  /* Values list RTE */
9956  appendStringInfoChar(buf, '(');
9957  get_values_def(rte->values_lists, context);
9958  appendStringInfoChar(buf, ')');
9959  break;
9960  case RTE_CTE:
9962  break;
9963  default:
9964  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
9965  break;
9966  }
9967 
9968  /* Print the relation alias, if needed */
9969  printalias = false;
9970  if (rte->alias != NULL)
9971  {
9972  /* Always print alias if user provided one */
9973  printalias = true;
9974  }
9975  else if (colinfo->printaliases)
9976  {
9977  /* Always print alias if we need to print column aliases */
9978  printalias = true;
9979  }
9980  else if (rte->rtekind == RTE_RELATION)
9981  {
9982  /*
9983  * No need to print alias if it's same as relation name (this
9984  * would normally be the case, but not if set_rtable_names had to
9985  * resolve a conflict).
9986  */
9987  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
9988  printalias = true;
9989  }
9990  else if (rte->rtekind == RTE_FUNCTION)
9991  {
9992  /*
9993  * For a function RTE, always print alias. This covers possible
9994  * renaming of the function and/or instability of the
9995  * FigureColname rules for things that aren't simple functions.
9996  * Note we'd need to force it anyway for the columndef list case.
9997  */
9998  printalias = true;
9999  }
10000  else if (rte->rtekind == RTE_VALUES)
10001  {
10002  /* Alias is syntactically required for VALUES */
10003  printalias = true;
10004  }
10005  else if (rte->rtekind == RTE_CTE)
10006  {
10007  /*
10008  * No need to print alias if it's same as CTE name (this would
10009  * normally be the case, but not if set_rtable_names had to
10010  * resolve a conflict).
10011  */
10012  if (strcmp(refname, rte->ctename) != 0)
10013  printalias = true;
10014  }
10015  if (printalias)
10016  appendStringInfo(buf, " %s", quote_identifier(refname));
10017 
10018  /* Print the column definitions or aliases, if needed */
10019  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10020  {
10021  /* Reconstruct the columndef list, which is also the aliases */
10022  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10023  }
10024  else
10025  {
10026  /* Else print column aliases as needed */
10027  get_column_alias_list(colinfo, context);
10028  }
10029 
10030  /* Tablesample clause must go after any alias */
10031  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10032  get_tablesample_def(rte->tablesample, context);
10033  }
10034  else if (IsA(jtnode, JoinExpr))
10035  {
10036  JoinExpr *j = (JoinExpr *) jtnode;
10037  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10038  bool need_paren_on_right;
10039 
10040  need_paren_on_right = PRETTY_PAREN(context) &&
10041  !IsA(j->rarg, RangeTblRef) &&
10042  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
10043 
10044  if (!PRETTY_PAREN(context) || j->alias != NULL)
10045  appendStringInfoChar(buf, '(');
10046 
10047  get_from_clause_item(j->larg, query, context);
10048 
10049  switch (j->jointype)
10050  {
10051  case JOIN_INNER:
10052  if (j->quals)
10053  appendContextKeyword(context, " JOIN ",
10057  else
10058  appendContextKeyword(context, " CROSS JOIN ",
10062  break;
10063  case JOIN_LEFT:
10064  appendContextKeyword(context, " LEFT JOIN ",
10068  break;
10069  case JOIN_FULL:
10070  appendContextKeyword(context, " FULL JOIN ",
10074  break;
10075  case JOIN_RIGHT:
10076  appendContextKeyword(context, " RIGHT JOIN ",
10080  break;
10081  default:
10082  elog(ERROR, "unrecognized join type: %d",
10083  (int) j->jointype);
10084  }
10085 
10086  if (need_paren_on_right)
10087  appendStringInfoChar(buf, '(');
10088  get_from_clause_item(j->rarg, query, context);
10089  if (need_paren_on_right)
10090  appendStringInfoChar(buf, ')');
10091 
10092  if (j->usingClause)
10093  {
10094  ListCell *lc;
10095  bool first = true;
10096 
10097  appendStringInfoString(buf, " USING (");
10098  /* Use the assigned names, not what's in usingClause */
10099  foreach(lc, colinfo->usingNames)
10100  {
10101  char *colname = (char *) lfirst(lc);
10102 
10103  if (first)
10104  first = false;
10105  else
10106  appendStringInfoString(buf, ", ");
10108  }
10109  appendStringInfoChar(buf, ')');
10110  }
10111  else if (j->quals)
10112  {
10113  appendStringInfoString(buf, " ON ");
10114  if (!PRETTY_PAREN(context))
10115  appendStringInfoChar(buf, '(');
10116  get_rule_expr(j->quals, context, false);
10117  if (!PRETTY_PAREN(context))
10118  appendStringInfoChar(buf, ')');
10119  }
10120  else if (j->jointype != JOIN_INNER)
10121  {
10122  /* If we didn't say CROSS JOIN above, we must provide an ON */
10123  appendStringInfoString(buf, " ON TRUE");
10124  }
10125 
10126  if (!PRETTY_PAREN(context) || j->alias != NULL)
10127  appendStringInfoChar(buf, ')');
10128 
10129  /* Yes, it's correct to put alias after the right paren ... */
10130  if (j->alias != NULL)
10131  {
10132  appendStringInfo(buf, " %s",
10134  get_column_alias_list(colinfo, context);
10135  }
10136  }
10137  else
10138  elog(ERROR, "unrecognized node type: %d",
10139  (int) nodeTag(jtnode));
10140 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10541
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
Alias * alias
Definition: parsenodes.h:1062
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:513
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool funcordinality
Definition: parsenodes.h:1014
List * values_lists
Definition: parsenodes.h:1024
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10561
Node * larg
Definition: primnodes.h:1458
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10241
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:271
TableFunc * tablefunc
Definition: parsenodes.h:1019
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7531
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:275
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
List * usingClause
Definition: primnodes.h:1460
Node * quals
Definition: primnodes.h:1461
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9609
Node * rarg
Definition: primnodes.h:1459
Alias * alias
Definition: primnodes.h:1462
JoinType jointype
Definition: primnodes.h:1456
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:1013
#define only_marker(rte)
Definition: ruleutils.c:467
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:4886
#define nodeTag(nodeptr)
Definition: nodes.h:518
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4959
RTEKind rtekind
Definition: parsenodes.h:959
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10148
char * ctename
Definition: parsenodes.h:1029
Query * subquery
Definition: parsenodes.h:982
StringInfo buf
Definition: ruleutils.c:108
#define elog
Definition: elog.h:219
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10188
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8851
int rtindex
Definition: primnodes.h:1463
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:977
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4442
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9821

◆ get_func_expr()

static void get_func_expr ( FuncExpr expr,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 8962 of file ruleutils.c.

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

Referenced by get_rule_expr().

8964 {
8965  StringInfo buf = context->buf;
8966  Oid funcoid = expr->funcid;
8967  Oid argtypes[FUNC_MAX_ARGS];
8968  int nargs;
8969  List *argnames;
8970  bool use_variadic;
8971  ListCell *l;
8972 
8973  /*
8974  * If the function call came from an implicit coercion, then just show the
8975  * first argument --- unless caller wants to see implicit coercions.
8976  */
8977  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
8978  {
8979  get_rule_expr_paren((Node *) linitial(expr->args), context,
8980  false, (Node *) expr);
8981  return;
8982  }
8983 
8984  /*
8985  * If the function call came from a cast, then show the first argument
8986  * plus an explicit cast operation.
8987  */
8988  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
8990  {
8991  Node *arg = linitial(expr->args);
8992  Oid rettype = expr->funcresulttype;
8993  int32 coercedTypmod;
8994 
8995  /* Get the typmod if this is a length-coercion function */
8996  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
8997 
8998  get_coercion_expr(arg, context,
8999  rettype, coercedTypmod,
9000  (Node *) expr);
9001 
9002  return;
9003  }
9004 
9005  /*
9006  * Normal function: display as proname(args). First we need to extract
9007  * the argument datatypes.
9008  */
9009  if (list_length(expr->args) > FUNC_MAX_ARGS)
9010  ereport(ERROR,
9011  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9012  errmsg("too many arguments")));
9013  nargs = 0;
9014  argnames = NIL;
9015  foreach(l, expr->args)
9016  {
9017  Node *arg = (Node *) lfirst(l);
9018 
9019  if (IsA(arg, NamedArgExpr))
9020  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9021  argtypes[nargs] = exprType(arg);
9022  nargs++;
9023  }
9024 
9025  appendStringInfo(buf, "%s(",
9026  generate_function_name(funcoid, nargs,
9027  argnames, argtypes,
9028  expr->funcvariadic,
9029  &use_variadic,
9030  context->special_exprkind));
9031  nargs = 0;
9032  foreach(l, expr->args)
9033  {
9034  if (nargs++ > 0)
9035  appendStringInfoString(buf, ", ");
9036  if (use_variadic && lnext(l) == NULL)
9037  appendStringInfoString(buf, "VARIADIC ");
9038  get_rule_expr((Node *) lfirst(l), context, true);
9039  }
9040  appendStringInfoChar(buf, ')');
9041 }
Oid funcresulttype
Definition: primnodes.h:450
#define NIL
Definition: pg_list.h:69
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10663
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7604
List * args
Definition: primnodes.h:457
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:513
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:302
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:454
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:449
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:9246
ParseExprKind special_exprkind
Definition: ruleutils.c:116
List * lappend(List *list, void *datum)
Definition: list.c:128
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
StringInfo buf
Definition: ruleutils.c:108
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:452

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

Definition at line 5949 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_attname(), get_constraint_name(), get_query_def(), get_rule_expr(), get_target_list(), get_update_query_targetlist_def(), get_values_def(), get_with_clause(), deparse_context::indentLevel, lappend(), lfirst, NIL, OidIsValid, Query::onConflict, ONCONFLICT_NOTHING, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, Query::override, OVERRIDING_SYSTEM_VALUE, OVERRIDING_USER_VALUE, PRETTY_INDENT, deparse_context::prettyFlags, PRETTYINDENT_STD, processIndirection(), quote_identifier(), RangeTblEntry::relid, TargetEntry::resjunk, TargetEntry::resno, Query::resultRelation, Query::returningList, rt_fetch, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::subquery, Query::targetList, RangeTblEntry::values_lists, deparse_context::varprefix, and deparse_context::wrapColumn.

Referenced by get_query_def().

5950 {
5951  StringInfo buf = context->buf;
5952  RangeTblEntry *select_rte = NULL;
5953  RangeTblEntry *values_rte = NULL;
5954  RangeTblEntry *rte;
5955  char *sep;
5956  ListCell *l;
5957  List *strippedexprs;
5958 
5959  /* Insert the WITH clause if given */
5960  get_with_clause(query, context);
5961 
5962  /*
5963  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
5964  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
5965  */
5966  foreach(l, query->rtable)
5967  {
5968  rte = (RangeTblEntry *) lfirst(l);
5969 
5970  if (rte->rtekind == RTE_SUBQUERY)
5971  {
5972  if (select_rte)
5973  elog(ERROR, "too many subquery RTEs in INSERT");
5974  select_rte = rte;
5975  }
5976 
5977  if (rte->rtekind == RTE_VALUES)
5978  {
5979  if (values_rte)
5980  elog(ERROR, "too many values RTEs in INSERT");
5981  values_rte = rte;
5982  }
5983  }
5984  if (select_rte && values_rte)
5985  elog(ERROR, "both subquery and values RTEs in INSERT");
5986 
5987  /*
5988  * Start the query with INSERT INTO relname
5989  */
5990  rte = rt_fetch(query->resultRelation, query->rtable);
5991  Assert(rte->rtekind == RTE_RELATION);
5992 
5993  if (PRETTY_INDENT(context))
5994  {
5995  context->indentLevel += PRETTYINDENT_STD;
5996  appendStringInfoChar(buf, ' ');
5997  }
5998  appendStringInfo(buf, "INSERT INTO %s ",
6000  /* INSERT requires AS keyword for target alias */
6001  if (rte->alias != NULL)
6002  appendStringInfo(buf, "AS %s ",
6004 
6005  /*
6006  * Add the insert-column-names list. Any indirection decoration needed on
6007  * the column names can be inferred from the top targetlist.
6008  */
6009  strippedexprs = NIL;
6010  sep = "";
6011  if (query->targetList)
6012  appendStringInfoChar(buf, '(');
6013  foreach(l, query->targetList)
6014  {
6015  TargetEntry *tle = (TargetEntry *) lfirst(l);
6016 
6017  if (tle->resjunk)
6018  continue; /* ignore junk entries */
6019 
6020  appendStringInfoString(buf, sep);
6021  sep = ", ";
6022 
6023  /*
6024  * Put out name of target column; look in the catalogs, not at
6025  * tle->resname, since resname will fail to track RENAME.
6026  */
6029  tle->resno,
6030  false)));
6031 
6032  /*
6033  * Print any indirection needed (subfields or subscripts), and strip
6034  * off the top-level nodes representing the indirection assignments.
6035  * Add the stripped expressions to strippedexprs. (If it's a
6036  * single-VALUES statement, the stripped expressions are the VALUES to
6037  * print below. Otherwise they're just Vars and not really
6038  * interesting.)
6039  */
6040  strippedexprs = lappend(strippedexprs,
6041  processIndirection((Node *) tle->expr,
6042  context));
6043  }
6044  if (query->targetList)
6045  appendStringInfoString(buf, ") ");
6046 
6047  if (query->override)
6048  {
6049  if (query->override == OVERRIDING_SYSTEM_VALUE)
6050  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6051  else if (query->override == OVERRIDING_USER_VALUE)
6052  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6053  }
6054 
6055  if (select_rte)
6056  {
6057  /* Add the SELECT */
6058  get_query_def(select_rte->subquery, buf, NIL, NULL,
6059  context->prettyFlags, context->wrapColumn,
6060  context->indentLevel);
6061  }
6062  else if (values_rte)
6063  {
6064  /* Add the multi-VALUES expression lists */
6065  get_values_def(values_rte->values_lists, context);
6066  }
6067  else if (strippedexprs)
6068  {
6069  /* Add the single-VALUES expression list */
6070  appendContextKeyword(context, "VALUES (",
6072  get_rule_expr((Node *) strippedexprs, context, false);
6073  appendStringInfoChar(buf, ')');
6074  }
6075  else
6076  {
6077  /* No expressions, so it must be DEFAULT VALUES */
6078  appendStringInfoString(buf, "DEFAULT VALUES");
6079  }
6080 
6081  /* Add ON CONFLICT if present */
6082  if (query->onConflict)
6083  {
6084  OnConflictExpr *confl = query->onConflict;
6085 
6086  appendStringInfoString(buf, " ON CONFLICT");
6087 
6088  if (confl->arbiterElems)
6089  {
6090  /* Add the single-VALUES expression list */
6091  appendStringInfoChar(buf, '(');
6092  get_rule_expr((Node *) confl->arbiterElems, context, false);
6093  appendStringInfoChar(buf, ')');
6094 
6095  /* Add a WHERE clause (for partial indexes) if given */
6096  if (confl->arbiterWhere != NULL)
6097  {
6098  bool save_varprefix;
6099 
6100  /*
6101  * Force non-prefixing of Vars, since parser assumes that they
6102  * belong to target relation. WHERE clause does not use
6103  * InferenceElem, so this is separately required.
6104  */
6105  save_varprefix = context->varprefix;
6106  context->varprefix = false;
6107 
6108  appendContextKeyword(context, " WHERE ",
6110  get_rule_expr(confl->arbiterWhere, context, false);
6111 
6112  context->varprefix = save_varprefix;
6113  }
6114  }
6115  else if (OidIsValid(confl->constraint))
6116  {
6117  char *constraint = get_constraint_name(confl->constraint);
6118 
6119  if (!constraint)
6120  elog(ERROR, "cache lookup failed for constraint %u",
6121  confl->constraint);
6122  appendStringInfo(buf, " ON CONSTRAINT %s",
6123  quote_identifier(constraint));
6124  }
6125 
6126  if (confl->action == ONCONFLICT_NOTHING)
6127  {
6128  appendStringInfoString(buf, " DO NOTHING");
6129  }
6130  else
6131  {
6132  appendStringInfoString(buf, " DO UPDATE SET ");
6133  /* Deparse targetlist */
6135  context, rte);
6136 
6137  /* Add a WHERE clause if given */
6138  if (confl->onConflictWhere != NULL)
6139  {
6140  appendContextKeyword(context, " WHERE ",
6142  get_rule_expr(confl->onConflictWhere, context, false);
6143  }
6144  }
6145  }
6146 
6147  /* Add RETURNING if present */
6148  if (query->returningList)
6149  {
6150  appendContextKeyword(context, " RETURNING",
6152  get_target_list(query->returningList, context, NULL);
6153  }
6154 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5002
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
Alias * alias
Definition: parsenodes.h:1062
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:982
OnConflictExpr * onConflict
Definition: parsenodes.h:142
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10328
int resultRelation
Definition: parsenodes.h:120
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5370
Definition: nodes.h:513
#define PRETTY_INDENT(context)
Definition: ruleutils.c:97
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6217
#define OidIsValid(objectId)
Definition: c.h:594
List * values_lists
Definition: parsenodes.h:1024
List * targetList
Definition: parsenodes.h:138
List * arbiterElems
Definition: primnodes.h:1497
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10561
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1382
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7531
AttrNumber resno
Definition: primnodes.h:1376
List * returningList
Definition: parsenodes.h:144
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1494
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
OverridingKind override
Definition: parsenodes.h:140
#define Assert(condition)
Definition: c.h:688
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1375
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4886
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:4959
RTEKind rtekind
Definition: parsenodes.h:959
Node * arbiterWhere
Definition: primnodes.h:1499
Query * subquery
Definition: parsenodes.h:982
StringInfo buf
Definition: ruleutils.c:108
List * onConflictSet
Definition: primnodes.h:1503
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define elog
Definition: elog.h:219
Node * onConflictWhere
Definition: primnodes.h:1504
Definition: pg_list.h:45

◆ get_name_for_var_field()

static const char* get_name_for_var_field ( Var var,
int  fieldno,
int  levelsup,
deparse_context context 
)
static

Definition at line 6733 of file ruleutils.c.

References Alias::aliasname, Assert, RowExpr::colnames, RangeTblEntry::ctelevelsup, RangeTblEntry::ctename, CommonTableExpr::ctename, CommonTableExpr::ctequery, deparse_namespace::ctes, elog, RangeTblEntry::eref, ERROR, TargetEntry::expr, find_param_referent(), get_expr_result_tupdesc(), 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(), deparse_context::namespaces, NameStr, NIL, deparse_namespace::outer_planstate, deparse_namespace::outer_tlist, OUTER_VAR, pop_ancestor_plan(), pop_child_plan(), push_ancestor_plan(), push_child_plan(), RECORDOID, TargetEntry::resjunk, rt_fetch, deparse_namespace::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, set_deparse_for_query(), strVal, RangeTblEntry::subquery, Query::targetList, TupleDescAttr, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

Referenced by get_rule_expr().

6735 {
6736  RangeTblEntry *rte;
6737  AttrNumber attnum;
6738  int netlevelsup;
6739  deparse_namespace *dpns;
6741  Node *expr;
6742 
6743  /*
6744  * If it's a RowExpr that was expanded from a whole-row Var, use the
6745  * column names attached to it.
6746  */
6747  if (IsA(var, RowExpr))
6748  {
6749  RowExpr *r = (RowExpr *) var;
6750 
6751  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6752  return strVal(list_nth(r->colnames, fieldno - 1));
6753  }
6754 
6755  /*
6756  * If it's a Param of type RECORD, try to find what the Param refers to.
6757  */
6758  if (IsA(var, Param))
6759  {
6760  Param *param = (Param *) var;
6761  ListCell *ancestor_cell;
6762 
6763  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6764  if (expr)
6765  {
6766  /* Found a match, so recurse to decipher the field name */
6767  deparse_namespace save_dpns;
6768  const char *result;
6769 
6770  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6771  result = get_name_for_var_field((Var *) expr, fieldno,
6772  0, context);
6773  pop_ancestor_plan(dpns, &save_dpns);
6774  return result;
6775  }
6776  }
6777 
6778  /*
6779  * If it's a Var of type RECORD, we have to find what the Var refers to;
6780  * if not, we can use get_expr_result_tupdesc().
6781  */
6782  if (!IsA(var, Var) ||
6783  var->vartype != RECORDOID)
6784  {
6785  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
6786  /* Got the tupdesc, so we can extract the field name */
6787  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6788  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
6789  }
6790 
6791  /* Find appropriate nesting depth */
6792  netlevelsup = var->varlevelsup + levelsup;
6793  if (netlevelsup >= list_length(context->namespaces))
6794  elog(ERROR, "bogus varlevelsup: %d offset %d",
6795  var->varlevelsup, levelsup);
6796  dpns = (deparse_namespace *) list_nth(context->namespaces,
6797  netlevelsup);
6798 
6799  /*
6800  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6801  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6802  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6803  */
6804  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6805  {
6806  rte = rt_fetch(var->varno, dpns->rtable);
6807  attnum = var->varattno;
6808  }
6809  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6810  {
6811  TargetEntry *tle;
6812  deparse_namespace save_dpns;
6813  const char *result;
6814 
6815  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6816  if (!tle)
6817  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6818 
6819  Assert(netlevelsup == 0);
6820  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6821 
6822  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6823  levelsup, context);
6824 
6825  pop_child_plan(dpns, &save_dpns);
6826  return result;
6827  }
6828  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6829  {
6830  TargetEntry *tle;
6831  deparse_namespace save_dpns;
6832  const char *result;
6833 
6834  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6835  if (!tle)
6836  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6837 
6838  Assert(netlevelsup == 0);
6839  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6840 
6841  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6842  levelsup, context);
6843 
6844  pop_child_plan(dpns, &save_dpns);
6845  return result;
6846  }
6847  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6848  {
6849  TargetEntry *tle;
6850  const char *result;
6851 
6852  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6853  if (!tle)
6854  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6855 
6856  Assert(netlevelsup == 0);
6857 
6858  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6859  levelsup, context);
6860 
6861  return result;
6862  }
6863  else
6864  {
6865  elog(ERROR, "bogus varno: %d", var->varno);
6866  return NULL; /* keep compiler quiet */
6867  }
6868 
6869  if (attnum == InvalidAttrNumber)
6870  {
6871  /* Var is whole-row reference to RTE, so select the right field */
6872  return get_rte_attribute_name(rte, fieldno);
6873  }
6874 
6875  /*
6876  * This part has essentially the same logic as the parser's
6877  * expandRecordVariable() function, but we are dealing with a different
6878  * representation of the input context, and we only need one field name
6879  * not a TupleDesc. Also, we need special cases for finding subquery and
6880  * CTE subplans when deparsing Plan trees.
6881  */
6882  expr = (Node *) var; /* default if we can't drill down */
6883 
6884  switch (rte->rtekind)
6885  {
6886  case RTE_RELATION:
6887  case RTE_VALUES:
6888  case RTE_NAMEDTUPLESTORE:
6889 
6890  /*
6891  * This case should not occur: a column of a table, values list,
6892  * or ENR shouldn't have type RECORD. Fall through and fail (most
6893  * likely) at the bottom.
6894  */
6895  break;
6896  case RTE_SUBQUERY:
6897  /* Subselect-in-FROM: examine sub-select's output expr */
6898  {
6899  if (rte->subquery)
6900  {
6902  attnum);
6903 
6904  if (ste == NULL || ste->resjunk)
6905  elog(ERROR, "subquery %s does not have attribute %d",
6906  rte->eref->aliasname, attnum);
6907  expr = (Node *) ste->expr;
6908  if (IsA(expr, Var))
6909  {
6910  /*
6911  * Recurse into the sub-select to see what its Var
6912  * refers to. We have to build an additional level of
6913  * namespace to keep in step with varlevelsup in the
6914  * subselect.
6915  */
6916  deparse_namespace mydpns;
6917  const char *result;
6918 
6919  set_deparse_for_query(&mydpns, rte->subquery,
6920  context->namespaces);
6921 
6922  context->namespaces = lcons(&mydpns,
6923  context->namespaces);
6924 
6925  result = get_name_for_var_field((Var *) expr, fieldno,
6926  0, context);
6927 
6928  context->namespaces =
6929  list_delete_first(context->namespaces);
6930 
6931  return result;
6932  }
6933  /* else fall through to inspect the expression */
6934  }
6935  else
6936  {
6937  /*
6938  * We're deparsing a Plan tree so we don't have complete
6939  * RTE entries (in particular, rte->subquery is NULL). But
6940  * the only place we'd see a Var directly referencing a
6941  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6942  * look into the child plan's tlist instead.
6943  */
6944  TargetEntry *tle;
6945  deparse_namespace save_dpns;
6946  const char *result;
6947 
6948  if (!dpns->inner_planstate)
6949  elog(ERROR, "failed to find plan for subquery %s",
6950  rte->eref->aliasname);
6951  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
6952  if (!tle)
6953  elog(ERROR, "bogus varattno for subquery var: %d",
6954  attnum);
6955  Assert(netlevelsup == 0);
6956  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6957 
6958  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6959  levelsup, context);
6960 
6961  pop_child_plan(dpns, &save_dpns);
6962  return result;
6963  }
6964  }
6965  break;
6966  case RTE_JOIN:
6967  /* Join RTE --- recursively inspect the alias variable */
6968  if (rte->joinaliasvars == NIL)
6969  elog(ERROR, "cannot decompile join alias var in plan tree");
6970  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
6971  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
6972  Assert(expr != NULL);
6973  /* we intentionally don't strip implicit coercions here */
6974  if (IsA(expr, Var))
6975  return get_name_for_var_field((Var *) expr, fieldno,
6976  var->varlevelsup + levelsup,
6977  context);
6978  /* else fall through to inspect the expression */
6979  break;
6980  case RTE_FUNCTION:
6981  case RTE_TABLEFUNC:
6982 
6983  /*
6984  * We couldn't get here unless a function is declared with one of
6985  * its result columns as RECORD, which is not allowed.
6986  */
6987  break;
6988  case RTE_CTE:
6989  /* CTE reference: examine subquery's output expr */
6990  {
6991  CommonTableExpr *cte = NULL;
6992  Index ctelevelsup;
6993  ListCell *lc;
6994 
6995  /*
6996  * Try to find the referenced CTE using the namespace stack.
6997  */
6998  ctelevelsup = rte->ctelevelsup + netlevelsup;
6999  if (ctelevelsup >= list_length(context->namespaces))
7000  lc = NULL;
7001  else
7002  {
7003  deparse_namespace *ctedpns;
7004 
7005  ctedpns = (deparse_namespace *)
7006  list_nth(context->namespaces, ctelevelsup);
7007  foreach(lc, ctedpns->ctes)
7008  {
7009  cte = (CommonTableExpr *) lfirst(lc);
7010  if (strcmp(cte->ctename, rte->ctename) == 0)
7011  break;
7012  }
7013  }
7014  if (lc != NULL)
7015  {
7016  Query *ctequery = (Query *) cte->ctequery;
7018  attnum);
7019 
7020  if (ste == NULL || ste->resjunk)
7021  elog(ERROR, "subquery %s does not have attribute %d",
7022  rte->eref->aliasname, attnum);
7023  expr = (Node *) ste->expr;
7024  if (IsA(expr, Var))
7025  {
7026  /*
7027  * Recurse into the CTE to see what its Var refers to.
7028  * We have to build an additional level of namespace
7029  * to keep in step with varlevelsup in the CTE.
7030  * Furthermore it could be an outer CTE, so we may
7031  * have to delete some levels of namespace.
7032  */
7033  List *save_nslist = context->namespaces;
7034  List *new_nslist;
7035  deparse_namespace mydpns;
7036  const char *result;
7037 
7038  set_deparse_for_query(&mydpns, ctequery,
7039  context->namespaces);
7040 
7041  new_nslist = list_copy_tail(context->namespaces,
7042  ctelevelsup);
7043  context->namespaces = lcons(&mydpns, new_nslist);
7044 
7045  result = get_name_for_var_field((Var *) expr, fieldno,
7046  0, context);
7047 
7048  context->namespaces = save_nslist;
7049 
7050  return result;
7051  }
7052  /* else fall through to inspect the expression */
7053  }
7054  else
7055  {
7056  /*
7057  * We're deparsing a Plan tree so we don't have a CTE
7058  * list. But the only place we'd see a Var directly
7059  * referencing a CTE RTE is in a CteScan plan node, and we
7060  * can look into the subplan's tlist instead.
7061  */
7062  TargetEntry *tle;
7063  deparse_namespace save_dpns;
7064  const char *result;
7065 
7066  if (!dpns->inner_planstate)
7067  elog(ERROR, "failed to find plan for CTE %s",
7068  rte->eref->aliasname);
7069  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7070  if (!tle)
7071  elog(ERROR, "bogus varattno for subquery var: %d",
7072  attnum);
7073  Assert(netlevelsup == 0);
7074  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7075 
7076  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7077  levelsup, context);
7078 
7079  pop_child_plan(dpns, &save_dpns);
7080  return result;
7081  }
7082  }
7083  break;
7084  }
7085 
7086  /*
7087  * We now have an expression we can't expand any more, so see if
7088  * get_expr_result_tupdesc() can do anything with it.
7089  */
7090  tupleDesc = get_expr_result_tupdesc(expr, false);
7091  /* Got the tupdesc, so we can extract the field name */
7092  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7093  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7094 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
List * joinaliasvars
Definition: parsenodes.h:1003
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:7105
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Definition: nodes.h:513
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:168
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4606
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:160
Definition: primnodes.h:163
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
#define ERROR
Definition: elog.h:43
List * colnames
Definition: primnodes.h:1006
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:412
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:4536
#define RECORDOID
Definition: pg_type.h:680
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:166
List * outer_tlist
Definition: ruleutils.c:161
unsigned int Index
Definition: c.h:431
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6733
#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:4553
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1375
PlanState * outer_planstate
Definition: ruleutils.c:159
static int list_length(const List *l)
Definition: pg_list.h:89
Index ctelevelsup
Definition: parsenodes.h:1030
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3374
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:959
char * ctename
Definition: parsenodes.h:1029
Query * subquery
Definition: parsenodes.h:982
List * index_tlist
Definition: ruleutils.c:163
List * inner_tlist
Definition: ruleutils.c:162
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4583
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1063
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define GetCTETargetList(cte)
Definition: parsenodes.h:1406
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:154
List * list_delete_first(List *list)
Definition: list.c:666

◆ get_opclass_name()

static void get_opclass_name ( Oid  opclass,
Oid  actual_datatype,
StringInfo  buf 
)
static

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

10287 {
10288  HeapTuple ht_opc;
10289  Form_pg_opclass opcrec;
10290  char *opcname;
10291  char *nspname;
10292 
10293  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10294  if (!HeapTupleIsValid(ht_opc))
10295  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10296  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10297 
10298  if (!OidIsValid(actual_datatype) ||
10299  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10300  {
10301  /* Okay, we need the opclass name. Do we need to qualify it? */
10302  opcname = NameStr(opcrec->opcname);
10303  if (OpclassIsVisible(opclass))
10304  appendStringInfo(buf, " %s", quote_identifier(opcname));
10305  else
10306  {
10307  nspname = get_namespace_name(opcrec->opcnamespace);
10308  appendStringInfo(buf, " %s.%s",
10309  quote_identifier(nspname),
10310  quote_identifier(opcname));
10311  }
10312  }
10313  ReleaseSysCache(ht_opc);
10314 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1719
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
#define OidIsValid(objectId)
Definition: c.h:594
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1793
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68

◆ get_oper_expr()

static void get_oper_expr ( OpExpr expr,
deparse_context context 
)
static

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

8902 {
8903  StringInfo buf = context->buf;
8904  Oid opno = expr->opno;
8905  List *args = expr->args;
8906 
8907  if (!PRETTY_PAREN(context))
8908  appendStringInfoChar(buf, '(');
8909  if (list_length(args) == 2)
8910  {
8911  /* binary operator */
8912  Node *arg1 = (Node *) linitial(args);
8913  Node *arg2 = (Node *) lsecond(args);
8914 
8915  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8916  appendStringInfo(buf, " %s ",
8918  exprType(arg1),
8919  exprType(arg2)));
8920  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8921  }
8922  else
8923  {
8924  /* unary operator --- but which side? */
8925  Node *arg = (Node *) linitial(args);
8926  HeapTuple tp;
8927  Form_pg_operator optup;
8928 
8930  if (!HeapTupleIsValid(tp))
8931  elog(ERROR, "cache lookup failed for operator %u", opno);
8932  optup = (Form_pg_operator) GETSTRUCT(tp);
8933  switch (optup->oprkind)
8934  {
8935  case 'l':
8936  appendStringInfo(buf, "%s ",
8938  InvalidOid,
8939  exprType(arg)));
8940  get_rule_expr_paren(arg, context, true, (Node *) expr);
8941  break;
8942  case 'r':
8943  get_rule_expr_paren(arg, context, true, (Node *) expr);
8944  appendStringInfo(buf, " %s",
8946  exprType(arg),
8947  InvalidOid));
8948  break;
8949  default:
8950  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
8951  }
8952  ReleaseSysCache(tp);
8953  }
8954  if (!PRETTY_PAREN(context))
8955  appendStringInfoChar(buf, ')');
8956 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7604
Definition: nodes.h:513
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:116
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10773
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:96
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:57
StringInfo buf
Definition: ruleutils.c:108
void * arg
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

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

7226 {
7227  Node *expr;
7228  deparse_namespace *dpns;
7229  ListCell *ancestor_cell;
7230 
7231  /*
7232  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7233  * the parameter was computed. Note that failing to find a referent isn't
7234  * an error, since the Param might well be a subplan output rather than an
7235  * input.
7236  */
7237  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7238  if (expr)
7239  {
7240  /* Found a match, so print it */
7241  deparse_namespace save_dpns;
7242  bool save_varprefix;
7243  bool need_paren;
7244 
7245  /* Switch attention to the ancestor plan node */
7246  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7247 
7248  /*
7249  * Force prefixing of Vars, since they won't belong to the relation
7250  * being scanned in the original plan node.
7251  */
7252  save_varprefix = context->varprefix;
7253  context->varprefix = true;
7254 
7255  /*
7256  * A Param's expansion is typically a Var, Aggref, or upper-level
7257  * Param, which wouldn't need extra parentheses. Otherwise, insert
7258  * parens to ensure the expression looks atomic.
7259  */
7260  need_paren = !(IsA(expr, Var) ||
7261  IsA(expr, Aggref) ||
7262  IsA(expr, Param));
7263  if (need_paren)
7264  appendStringInfoChar(context->buf, '(');
7265 
7266  get_rule_expr(expr, context, false);
7267 
7268  if (need_paren)
7269  appendStringInfoChar(context->buf, ')');
7270 
7271  context->varprefix = save_varprefix;
7272 
7273  pop_ancestor_plan(dpns, &save_dpns);
7274 
7275  return;
7276  }
7277 
7278  /*
7279  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7280  */
7281  appendStringInfo(context->buf, "$%d", param->paramid);
7282 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7105
Definition: nodes.h:513
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4606
Definition: primnodes.h:163
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7636
int paramid
Definition: primnodes.h:245
StringInfo buf
Definition: ruleutils.c:108
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4583

◆ get_query_def()

static void get_query_def ( Query query,
StringInfo  buf,
List parentnamespace,
TupleDesc  resultDesc,
int  prettyFlags,
int  wrapColumn,
int  startIndent 
)
static

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

4889 {
4890  deparse_context context;
4891  deparse_namespace dpns;
4892 
4893  /* Guard against excessively long or deeply-nested queries */
4896 
4897  /*
4898  * Before we begin to examine the query, acquire locks on referenced
4899  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4900  * consistent results. Note we assume it's OK to scribble on the passed
4901  * querytree!
4902  *
4903  * We are only deparsing the query (we are not about to execute it), so we
4904  * only need AccessShareLock on the relations it mentions.
4905  */
4906  AcquireRewriteLocks(query, false, false);
4907 
4908  context.buf = buf;
4909  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4910  context.windowClause = NIL;
4911  context.windowTList = NIL;
4912  context.varprefix = (parentnamespace != NIL ||
4913  list_length(query->rtable) != 1);
4914  context.prettyFlags = prettyFlags;
4915  context.wrapColumn = wrapColumn;
4916  context.indentLevel = startIndent;
4917  context.special_exprkind = EXPR_KIND_NONE;
4918 
4919  set_deparse_for_query(&dpns, query, parentnamespace);
4920 
4921  switch (query->commandType)
4922  {
4923  case CMD_SELECT:
4924  get_select_query_def(query, &context, resultDesc);
4925  break;
4926 
4927  case CMD_UPDATE:
4928  get_update_query_def(query, &context);
4929  break;
4930 
4931  case CMD_INSERT:
4932  get_insert_query_def(query, &context);
4933  break;
4934 
4935  case CMD_DELETE:
4936  get_delete_query_def(query, &context);
4937  break;
4938 
4939  case CMD_NOTHING:
4940  appendStringInfoString(buf, "NOTHING");
4941  break;
4942 
4943  case CMD_UTILITY:
4944  get_utility_query_def(query, &context);
4945  break;
4946 
4947  default:
4948  elog(ERROR, "unrecognized query command type: %d",
4949  query->commandType);
4950  break;
4951  }
4952 }
List * namespaces
Definition: ruleutils.c:109
#define NIL
Definition: pg_list.h:69
List * list_copy(const List *oldlist)
Definition: list.c:1160
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:5949
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6162
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6420
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5070
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void check_stack_depth(void)
Definition: postgres.c:3154
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:116
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6369
List * windowTList
Definition: ruleutils.c:111
CmdType commandType
Definition: parsenodes.h:110
List * lcons(void *datum, List *list)
Definition: list.c:259
List * windowClause
Definition: ruleutils.c:110
static int list_length(const List *l)
Definition: pg_list.h:89
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3374
StringInfo buf
Definition: ruleutils.c:108
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219

◆ get_range_partbound_string()

char* get_range_partbound_string ( List bound_datums)

Definition at line 11004 of file ruleutils.c.

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

Referenced by check_new_partition_bound(), and get_rule_expr().

11005 {
11006  deparse_context context;
11008  ListCell *cell;
11009  char *sep;
11010 
11011  memset(&context, 0, sizeof(deparse_context));
11012  context.buf = buf;
11013 
11014  appendStringInfoString(buf, "(");
11015  sep = "";
11016  foreach(cell, bound_datums)
11017  {
11018  PartitionRangeDatum *datum =
11020 
11021  appendStringInfoString(buf, sep);
11022  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
11023  appendStringInfoString(buf, "MINVALUE");
11024  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
11025  appendStringInfoString(buf, "MAXVALUE");
11026  else
11027  {
11028  Const *val = castNode(Const, datum->value);
11029 
11030  get_const_expr(val, &context, -1);
11031  }
11032  sep = ", ";
11033  }
11034  appendStringInfoChar(buf, ')');
11035 
11036  return buf->data;
11037 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
PartitionRangeDatumKind kind
Definition: parsenodes.h:842
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9302
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:108
long val
Definition: informix.c:689

◆ get_relation_name()

static char * get_relation_name ( Oid  relid)
static

Definition at line 10541 of file ruleutils.c.

References elog, ERROR, and get_rel_name().

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

10542 {
10543  char *relname = get_rel_name(relid);
10544 
10545  if (!relname)
10546  elog(ERROR, "cache lookup failed for relation %u", relid);
10547  return relname;
10548 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730

◆ get_rtable_name()

static char * get_rtable_name ( int  rtindex,
deparse_context context 
)
static

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

4443 {
4445 
4446  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4447  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4448 }
List * namespaces
Definition: ruleutils.c:109
List * rtable_names
Definition: ruleutils.c:150
#define linitial(l)
Definition: pg_list.h:111
void * list_nth(const List *list, int n)
Definition: list.c:410
#define Assert(condition)
Definition: c.h:688
static int list_length(const List *l)
Definition: pg_list.h:89

◆ get_rule_expr()

static void get_rule_expr ( Node node,
deparse_context context,
bool  showimplicit 
)
static

Definition at line 7636 of file ruleutils.c.

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

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

7638 {
7639  StringInfo buf = context->buf;
7640 
7641  if (node == NULL)
7642  return;
7643 
7644  /* Guard against excessively long or deeply-nested queries */
7647 
7648  /*
7649  * Each level of get_rule_expr must emit an indivisible term
7650  * (parenthesized if necessary) to ensure result is reparsed into the same
7651  * expression tree. The only exception is that when the input is a List,
7652  * we emit the component items comma-separated with no surrounding
7653  * decoration; this is convenient for most callers.
7654  */
7655  switch (nodeTag(node))
7656  {
7657  case T_Var:
7658  (void) get_variable((Var *) node, 0, false, context);
7659  break;
7660 
7661  case T_Const:
7662  get_const_expr((Const *) node, context, 0);
7663  break;
7664 
7665  case T_Param:
7666  get_parameter((Param *) node, context);
7667  break;
7668 
7669  case T_Aggref:
7670  get_agg_expr((Aggref *) node, context, (Aggref *) node);
7671  break;
7672 
7673  case T_GroupingFunc:
7674  {
7675  GroupingFunc *gexpr = (GroupingFunc *) node;
7676 
7677  appendStringInfoString(buf, "GROUPING(");
7678  get_rule_expr((Node *) gexpr->args, context, true);
7679  appendStringInfoChar(buf, ')');
7680  }
7681  break;
7682 
7683  case T_WindowFunc: