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/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/guc.h"
#include "utils/hsearch.h"
#include "utils/lsyscache.h"
#include "utils/partcache.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   0x0001
 
#define PRETTYFLAG_INDENT   0x0002
 
#define PRETTYFLAG_SCHEMA   0x0004
 
#define WRAP_COLUMN_DEFAULT   0
 
#define PRETTY_PAREN(context)   ((context)->prettyFlags & PRETTYFLAG_PAREN)
 
#define PRETTY_INDENT(context)   ((context)->prettyFlags & PRETTYFLAG_INDENT)
 
#define PRETTY_SCHEMA(context)   ((context)->prettyFlags & PRETTYFLAG_SCHEMA)
 
#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 void add_cast_to (StringInfo buf, Oid typid)
 
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)
 
void generate_operator_clause (StringInfo buf, const char *leftop, Oid leftoptype, Oid opoid, const char *rightop, Oid rightoptype)
 
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 471 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)

◆ PRETTY_SCHEMA

#define PRETTY_SCHEMA (   context)    ((context)->prettyFlags & PRETTYFLAG_SCHEMA)

Definition at line 100 of file ruleutils.c.

◆ PRETTYFLAG_INDENT

◆ PRETTYFLAG_PAREN

◆ PRETTYFLAG_SCHEMA

◆ PRETTYINDENT_JOIN

#define PRETTYINDENT_JOIN   4

Definition at line 84 of file ruleutils.c.

Referenced by get_from_clause_item().

◆ PRETTYINDENT_LIMIT

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 87 of file ruleutils.c.

Referenced by appendContextKeyword().

◆ PRETTYINDENT_STD

◆ PRETTYINDENT_VAR

#define PRETTYINDENT_VAR   4

Definition at line 85 of file ruleutils.c.

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

◆ WRAP_COLUMN_DEFAULT

Function Documentation

◆ add_cast_to()

static void add_cast_to ( StringInfo  buf,
Oid  typid 
)
static

Definition at line 10947 of file ruleutils.c.

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

Referenced by generate_operator_clause().

10948 {
10949  HeapTuple typetup;
10950  Form_pg_type typform;
10951  char *typname;
10952  char *nspname;
10953 
10954  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
10955  if (!HeapTupleIsValid(typetup))
10956  elog(ERROR, "cache lookup failed for type %u", typid);
10957  typform = (Form_pg_type) GETSTRUCT(typetup);
10958 
10959  typname = NameStr(typform->typname);
10960  nspname = get_namespace_name(typform->typnamespace);
10961 
10962  appendStringInfo(buf, "::%s.%s",
10963  quote_identifier(nspname), quote_identifier(typname));
10964 
10965  ReleaseSysCache(typetup);
10966 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
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
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:247
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ appendContextKeyword()

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

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

7586 {
7587  StringInfo buf = context->buf;
7588 
7589  if (PRETTY_INDENT(context))
7590  {
7591  int indentAmount;
7592 
7593  context->indentLevel += indentBefore;
7594 
7595  /* remove any trailing spaces currently in the buffer ... */
7597  /* ... then add a newline and some spaces */
7598  appendStringInfoChar(buf, '\n');
7599 
7600  if (context->indentLevel < PRETTYINDENT_LIMIT)
7601  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7602  else
7603  {
7604  /*
7605  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7606  * to conserve horizontal space by reducing the per-level
7607  * indentation. For best results the scale factor here should
7608  * divide all the indent amounts that get added to indentLevel
7609  * (PRETTYINDENT_STD, etc). It's important that the indentation
7610  * not grow unboundedly, else deeply-nested trees use O(N^2)
7611  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7612  */
7613  indentAmount = PRETTYINDENT_LIMIT +
7614  (context->indentLevel - PRETTYINDENT_LIMIT) /
7615  (PRETTYINDENT_STD / 2);
7616  indentAmount %= PRETTYINDENT_LIMIT;
7617  /* scale/wrap logic affects indentLevel, but not indentPlus */
7618  indentAmount += indentPlus;
7619  }
7620  appendStringInfoSpaces(buf, indentAmount);
7621 
7623 
7624  context->indentLevel += indentAfter;
7625  if (context->indentLevel < 0)
7626  context->indentLevel = 0;
7627  }
7628  else
7630 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:99
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:7638
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
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:87
#define Max(x, y)
Definition: c.h:851
StringInfo buf
Definition: ruleutils.c:111

◆ colname_is_unique()

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

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

4191 {
4192  int i;
4193  ListCell *lc;
4194 
4195  /* Check against already-assigned column aliases within RTE */
4196  for (i = 0; i < colinfo->num_cols; i++)
4197  {
4198  char *oldname = colinfo->colnames[i];
4199 
4200  if (oldname && strcmp(oldname, colname) == 0)
4201  return false;
4202  }
4203 
4204  /*
4205  * If we're building a new_colnames array, check that too (this will be
4206  * partially but not completely redundant with the previous checks)
4207  */
4208  for (i = 0; i < colinfo->num_new_cols; i++)
4209  {
4210  char *oldname = colinfo->new_colnames[i];
4211 
4212  if (oldname && strcmp(oldname, colname) == 0)
4213  return false;
4214  }
4215 
4216  /* Also check against USING-column names that must be globally unique */
4217  foreach(lc, dpns->using_names)
4218  {
4219  char *oldname = (char *) lfirst(lc);
4220 
4221  if (strcmp(oldname, colname) == 0)
4222  return false;
4223  }
4224 
4225  /* Also check against names already assigned for parent-join USING cols */
4226  foreach(lc, colinfo->parentUsing)
4227  {
4228  char *oldname = (char *) lfirst(lc);
4229 
4230  if (strcmp(oldname, colname) == 0)
4231  return false;
4232  }
4233 
4234  return true;
4235 }
List * using_names
Definition: ruleutils.c:158
#define lfirst(lc)
Definition: pg_list.h:106
int i
List * parentUsing
Definition: ruleutils.c:252
char ** new_colnames
Definition: ruleutils.c:245
char ** colnames
Definition: ruleutils.c:228

◆ decompile_column_index_array()

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

Definition at line 2229 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2231 {
2232  Datum *keys;
2233  int nKeys;
2234  int j;
2235 
2236  /* Extract data from array of int16 */
2237  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2238  INT2OID, 2, true, 's',
2239  &keys, NULL, &nKeys);
2240 
2241  for (j = 0; j < nKeys; j++)
2242  {
2243  char *colName;
2244 
2245  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2246 
2247  if (j == 0)
2249  else
2250  appendStringInfo(buf, ", %s", quote_identifier(colName));
2251  }
2252 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
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 3130 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, 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().

3131 {
3132  deparse_namespace *dpns;
3133  RangeTblEntry *rte;
3134 
3135  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3136 
3137  /* Build a minimal RTE for the rel */
3138  rte = makeNode(RangeTblEntry);
3139  rte->rtekind = RTE_RELATION;
3140  rte->relid = relid;
3141  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3142  rte->alias = makeAlias(aliasname, NIL);
3143  rte->eref = rte->alias;
3144  rte->lateral = false;
3145  rte->inh = false;
3146  rte->inFromCl = true;
3147 
3148  /* Build one-element rtable */
3149  dpns->rtable = list_make1(rte);
3150  dpns->ctes = NIL;
3151  set_rtable_names(dpns, NIL, NULL);
3153 
3154  /* Return a one-deep namespace stack */
3155  return list_make1(dpns);
3156 }
#define NIL
Definition: pg_list.h:69
Alias * alias
Definition: parsenodes.h:1065
#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:3274
void * palloc0(Size size)
Definition: mcxt.c:955
#define makeNode(_type_)
Definition: nodes.h:565
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3487
RTEKind rtekind
Definition: parsenodes.h:962
Alias * eref
Definition: parsenodes.h:1066

◆ deparse_context_for_plan_rtable()

List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

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

3173 {
3174  deparse_namespace *dpns;
3175 
3176  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3177 
3178  /* Initialize fields that stay the same across the whole plan tree */
3179  dpns->rtable = rtable;
3180  dpns->rtable_names = rtable_names;
3181  dpns->ctes = NIL;
3182 
3183  /*
3184  * Set up column name aliases. We will get rather bogus results for join
3185  * RTEs, but that doesn't matter because plan trees don't contain any join
3186  * alias Vars.
3187  */
3189 
3190  /* Return a one-deep namespace stack */
3191  return list_make1(dpns);
3192 }
#define NIL
Definition: pg_list.h:69
List * rtable_names
Definition: ruleutils.c:153
#define list_make1(x1)
Definition: pg_list.h:139
void * palloc0(Size size)
Definition: mcxt.c:955
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3487

◆ deparse_expression()

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

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

3073 {
3074  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3075  showimplicit, 0, 0);
3076 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3098

◆ deparse_expression_pretty()

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

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

3101 {
3103  deparse_context context;
3104 
3105  initStringInfo(&buf);
3106  context.buf = &buf;
3107  context.namespaces = dpcontext;
3108  context.windowClause = NIL;
3109  context.windowTList = NIL;
3110  context.varprefix = forceprefix;
3111  context.prettyFlags = prettyFlags;
3112  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3113  context.indentLevel = startIndent;
3114  context.special_exprkind = EXPR_KIND_NONE;
3115 
3116  get_rule_expr(expr, &context, showimplicit);
3117 
3118  return buf.data;
3119 }
List * namespaces
Definition: ruleutils.c:112
#define NIL
Definition: pg_list.h:69
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:95
static char * buf
Definition: pg_test_fsync.c:67
ParseExprKind special_exprkind
Definition: ruleutils.c:119
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
List * windowTList
Definition: ruleutils.c:114
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7689
List * windowClause
Definition: ruleutils.c:113
StringInfo buf
Definition: ruleutils.c:111

◆ expand_colnames_array_to()

static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

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

4288 {
4289  if (n > colinfo->num_cols)
4290  {
4291  if (colinfo->colnames == NULL)
4292  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4293  else
4294  {
4295  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4296  n * sizeof(char *));
4297  memset(colinfo->colnames + colinfo->num_cols, 0,
4298  (n - colinfo->num_cols) * sizeof(char *));
4299  }
4300  colinfo->num_cols = n;
4301  }
4302 }
void * palloc0(Size size)
Definition: mcxt.c:955
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
char ** colnames
Definition: ruleutils.c:228

◆ 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 7158 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().

7160 {
7161  /* Initialize output parameters to prevent compiler warnings */
7162  *dpns_p = NULL;
7163  *ancestor_cell_p = NULL;
7164 
7165  /*
7166  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7167  * SubPlan argument. This will necessarily be in some ancestor of the
7168  * current expression's PlanState.
7169  */
7170  if (param->paramkind == PARAM_EXEC)
7171  {
7172  deparse_namespace *dpns;
7173  PlanState *child_ps;
7174  bool in_same_plan_level;
7175  ListCell *lc;
7176 
7177  dpns = (deparse_namespace *) linitial(context->namespaces);
7178  child_ps = dpns->planstate;
7179  in_same_plan_level = true;
7180 
7181  foreach(lc, dpns->ancestors)
7182  {
7183  PlanState *ps = (PlanState *) lfirst(lc);
7184  ListCell *lc2;
7185 
7186  /*
7187  * NestLoops transmit params to their inner child only; also, once
7188  * we've crawled up out of a subplan, this couldn't possibly be
7189  * the right match.
7190  */
7191  if (IsA(ps, NestLoopState) &&
7192  child_ps == innerPlanState(ps) &&
7193  in_same_plan_level)
7194  {
7195  NestLoop *nl = (NestLoop *) ps->plan;
7196 
7197  foreach(lc2, nl->nestParams)
7198  {
7199  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7200 
7201  if (nlp->paramno == param->paramid)
7202  {
7203  /* Found a match, so return it */
7204  *dpns_p = dpns;
7205  *ancestor_cell_p = lc;
7206  return (Node *) nlp->paramval;
7207  }
7208  }
7209  }
7210 
7211  /*
7212  * Check to see if we're crawling up from a subplan.
7213  */
7214  foreach(lc2, ps->subPlan)
7215  {
7216  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7217  SubPlan *subplan = sstate->subplan;
7218  ListCell *lc3;
7219  ListCell *lc4;
7220 
7221  if (child_ps != sstate->planstate)
7222  continue;
7223 
7224  /* Matched subplan, so check its arguments */
7225  forboth(lc3, subplan->parParam, lc4, subplan->args)
7226  {
7227  int paramid = lfirst_int(lc3);
7228  Node *arg = (Node *) lfirst(lc4);
7229 
7230  if (paramid == param->paramid)
7231  {
7232  /* Found a match, so return it */
7233  *dpns_p = dpns;
7234  *ancestor_cell_p = lc;
7235  return arg;
7236  }
7237  }
7238 
7239  /* Keep looking, but we are emerging from a subplan. */
7240  in_same_plan_level = false;
7241  break;
7242  }
7243 
7244  /*
7245  * Likewise check to see if we're emerging from an initplan.
7246  * Initplans never have any parParams, so no need to search that
7247  * list, but we need to know if we should reset
7248  * in_same_plan_level.
7249  */
7250  foreach(lc2, ps->initPlan)
7251  {
7252  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7253 
7254  if (child_ps != sstate->planstate)
7255  continue;
7256 
7257  /* No parameters to be had here. */
7258  Assert(sstate->subplan->parParam == NIL);
7259 
7260  /* Keep looking, but we are emerging from an initplan. */
7261  in_same_plan_level = false;
7262  break;
7263  }
7264 
7265  /* No luck, crawl up to next ancestor */
7266  child_ps = ps;
7267  }
7268  }
7269 
7270  /* No referent found */
7271  return NULL;
7272 }
List * namespaces
Definition: ruleutils.c:112
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
List * nestParams
Definition: plannodes.h:700
List * initPlan
Definition: execnodes.h:933
List * subPlan
Definition: execnodes.h:935
ParamKind paramkind
Definition: primnodes.h:245
Definition: nodes.h:517
Var * paramval
Definition: plannodes.h:707
#define linitial(l)
Definition: pg_list.h:111
struct PlanState * planstate
Definition: execnodes.h:821
SubPlan * subplan
Definition: execnodes.h:820
#define lfirst_int(lc)
Definition: pg_list.h:107
Plan * plan
Definition: execnodes.h:911
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
int paramid
Definition: primnodes.h:246
List * parParam
Definition: primnodes.h:710
PlanState * planstate
Definition: ruleutils.c:160
void * arg
#define innerPlanState(node)
Definition: execnodes.h:964
List * args
Definition: primnodes.h:711

◆ flatten_join_using_qual()

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

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

4439 {
4440  if (IsA(qual, BoolExpr))
4441  {
4442  /* Handle AND nodes by recursion */
4443  BoolExpr *b = (BoolExpr *) qual;
4444  ListCell *lc;
4445 
4446  Assert(b->boolop == AND_EXPR);
4447  foreach(lc, b->args)
4448  {
4450  leftvars, rightvars);
4451  }
4452  }
4453  else if (IsA(qual, OpExpr))
4454  {
4455  /* Otherwise we should have an equality operator */
4456  OpExpr *op = (OpExpr *) qual;
4457  Var *var;
4458 
4459  if (list_length(op->args) != 2)
4460  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4461  /* Arguments should be Vars with perhaps implicit coercions */
4462  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4463  if (!IsA(var, Var))
4464  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4465  (int) nodeTag(var));
4466  *leftvars = lappend(*leftvars, var);
4467  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4468  if (!IsA(var, Var))
4469  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4470  (int) nodeTag(var));
4471  *rightvars = lappend(*rightvars, var);
4472  }
4473  else
4474  {
4475  /* Perhaps we have an implicit coercion to boolean? */
4476  Node *q = strip_implicit_coercions(qual);
4477 
4478  if (q != qual)
4479  flatten_join_using_qual(q, leftvars, rightvars);
4480  else
4481  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4482  (int) nodeTag(qual));
4483  }
4484 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Definition: nodes.h:517
Definition: primnodes.h:164
#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:563
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:4438
#define Assert(condition)
Definition: c.h:699
#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:564
#define nodeTag(nodeptr)
Definition: nodes.h:522
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:503
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

Definition at line 11056 of file ruleutils.c.

References 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, and value.

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

11057 {
11058  char *result = NULL;
11059  HeapTuple tuple;
11060  Datum reloptions;
11061  bool isnull;
11062 
11063  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11064  if (!HeapTupleIsValid(tuple))
11065  elog(ERROR, "cache lookup failed for relation %u", relid);
11066 
11067  reloptions = SysCacheGetAttr(RELOID, tuple,
11068  Anum_pg_class_reloptions, &isnull);
11069  if (!isnull)
11070  {
11072  Datum *options;
11073  int noptions;
11074  int i;
11075 
11076  initStringInfo(&buf);
11077 
11079  TEXTOID, -1, false, 'i',
11080  &options, NULL, &noptions);
11081 
11082  for (i = 0; i < noptions; i++)
11083  {
11084  char *option = TextDatumGetCString(options[i]);
11085  char *name;
11086  char *separator;
11087  char *value;
11088 
11089  /*
11090  * Each array element should have the form name=value. If the "="
11091  * is missing for some reason, treat it like an empty value.
11092  */
11093  name = option;
11094  separator = strchr(option, '=');
11095  if (separator)
11096  {
11097  *separator = '\0';
11098  value = separator + 1;
11099  }
11100  else
11101  value = "";
11102 
11103  if (i > 0)
11104  appendStringInfoString(&buf, ", ");
11105  appendStringInfo(&buf, "%s=", quote_identifier(name));
11106 
11107  /*
11108  * In general we need to quote the value; but to avoid unnecessary
11109  * clutter, do not quote if it is an identifier that would not
11110  * need quoting. (We could also allow numbers, but that is a bit
11111  * trickier than it looks --- for example, are leading zeroes
11112  * significant? We don't want to assume very much here about what
11113  * custom reloptions might mean.)
11114  */
11115  if (quote_identifier(value) == value)
11116  appendStringInfoString(&buf, value);
11117  else
11118  simple_quote_literal(&buf, value);
11119 
11120  pfree(option);
11121  }
11122 
11123  result = buf.data;
11124  }
11125 
11126  ReleaseSysCache(tuple);
11127 
11128  return result;
11129 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
void pfree(void *pointer)
Definition: mcxt.c:1031
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:9510
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:96
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
static struct @131 value
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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 11011 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().

11012 {
11013  HeapTuple tp;
11014  Form_pg_collation colltup;
11015  char *collname;
11016  char *nspname;
11017  char *result;
11018 
11019  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11020  if (!HeapTupleIsValid(tp))
11021  elog(ERROR, "cache lookup failed for collation %u", collid);
11022  colltup = (Form_pg_collation) GETSTRUCT(tp);
11023  collname = NameStr(colltup->collname);
11024 
11025  if (!CollationIsVisible(collid))
11026  nspname = get_namespace_name(colltup->collnamespace);
11027  else
11028  nspname = NULL;
11029 
11030  result = quote_qualified_identifier(nspname, collname);
11031 
11032  ReleaseSysCache(tp);
11033 
11034  return result;
11035 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:2027
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10574
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:49
#define NameStr(name)
Definition: c.h:576
#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 10716 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().

10719 {
10720  char *result;
10721  HeapTuple proctup;
10722  Form_pg_proc procform;
10723  char *proname;
10724  bool use_variadic;
10725  char *nspname;
10726  FuncDetailCode p_result;
10727  Oid p_funcid;
10728  Oid p_rettype;
10729  bool p_retset;
10730  int p_nvargs;
10731  Oid p_vatype;
10732  Oid *p_true_typeids;
10733  bool force_qualify = false;
10734 
10735  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10736  if (!HeapTupleIsValid(proctup))
10737  elog(ERROR, "cache lookup failed for function %u", funcid);
10738  procform = (Form_pg_proc) GETSTRUCT(proctup);
10739  proname = NameStr(procform->proname);
10740 
10741  /*
10742  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10743  * qualification in some special cases.
10744  */
10745  if (special_exprkind == EXPR_KIND_GROUP_BY)
10746  {
10747  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10748  force_qualify = true;
10749  }
10750 
10751  /*
10752  * Determine whether VARIADIC should be printed. We must do this first
10753  * since it affects the lookup rules in func_get_detail().
10754  *
10755  * Currently, we always print VARIADIC if the function has a merged
10756  * variadic-array argument. Note that this is always the case for
10757  * functions taking a VARIADIC argument type other than VARIADIC ANY.
10758  *
10759  * In principle, if VARIADIC wasn't originally specified and the array
10760  * actual argument is deconstructable, we could print the array elements
10761  * separately and not print VARIADIC, thus more nearly reproducing the
10762  * original input. For the moment that seems like too much complication
10763  * for the benefit, and anyway we do not know whether VARIADIC was
10764  * originally specified if it's a non-ANY type.
10765  */
10766  if (use_variadic_p)
10767  {
10768  /* Parser should not have set funcvariadic unless fn is variadic */
10769  Assert(!has_variadic || OidIsValid(procform->provariadic));
10770  use_variadic = has_variadic;
10771  *use_variadic_p = use_variadic;
10772  }
10773  else
10774  {
10775  Assert(!has_variadic);
10776  use_variadic = false;
10777  }
10778 
10779  /*
10780  * The idea here is to schema-qualify only if the parser would fail to
10781  * resolve the correct function given the unqualified func name with the
10782  * specified argtypes and VARIADIC flag. But if we already decided to
10783  * force qualification, then we can skip the lookup and pretend we didn't
10784  * find it.
10785  */
10786  if (!force_qualify)
10787  p_result = func_get_detail(list_make1(makeString(proname)),
10788  NIL, argnames, nargs, argtypes,
10789  !use_variadic, true,
10790  &p_funcid, &p_rettype,
10791  &p_retset, &p_nvargs, &p_vatype,
10792  &p_true_typeids, NULL);
10793  else
10794  {
10795  p_result = FUNCDETAIL_NOTFOUND;
10796  p_funcid = InvalidOid;
10797  }
10798 
10799  if ((p_result == FUNCDETAIL_NORMAL ||
10800  p_result == FUNCDETAIL_AGGREGATE ||
10801  p_result == FUNCDETAIL_WINDOWFUNC) &&
10802  p_funcid == funcid)
10803  nspname = NULL;
10804  else
10805  nspname = get_namespace_name(procform->pronamespace);
10806 
10807  result = quote_qualified_identifier(nspname, proname);
10808 
10809  ReleaseSysCache(proctup);
10810 
10811  return result;
10812 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#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:10574
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:132
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
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:576
#define elog
Definition: elog.h:219

◆ generate_operator_clause()

void generate_operator_clause ( StringInfo  buf,
const char *  leftop,
Oid  leftoptype,
Oid  opoid,
const char *  rightop,
Oid  rightoptype 
)

Definition at line 10907 of file ruleutils.c.

References add_cast_to(), appendStringInfo(), appendStringInfoString(), Assert, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OPEROID, quote_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by refresh_by_match_merge(), and ri_GenerateQual().

10911 {
10912  HeapTuple opertup;
10913  Form_pg_operator operform;
10914  char *oprname;
10915  char *nspname;
10916 
10917  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
10918  if (!HeapTupleIsValid(opertup))
10919  elog(ERROR, "cache lookup failed for operator %u", opoid);
10920  operform = (Form_pg_operator) GETSTRUCT(opertup);
10921  Assert(operform->oprkind == 'b');
10922  oprname = NameStr(operform->oprname);
10923 
10924  nspname = get_namespace_name(operform->oprnamespace);
10925 
10926  appendStringInfoString(buf, leftop);
10927  if (leftoptype != operform->oprleft)
10928  add_cast_to(buf, operform->oprleft);
10929  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
10930  appendStringInfoString(buf, oprname);
10931  appendStringInfo(buf, ") %s", rightop);
10932  if (rightoptype != operform->oprright)
10933  add_cast_to(buf, operform->oprright);
10934 
10935  ReleaseSysCache(opertup);
10936 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:10947
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
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
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ generate_operator_name()

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

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

10827 {
10829  HeapTuple opertup;
10830  Form_pg_operator operform;
10831  char *oprname;
10832  char *nspname;
10833  Operator p_result;
10834 
10835  initStringInfo(&buf);
10836 
10837  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10838  if (!HeapTupleIsValid(opertup))
10839  elog(ERROR, "cache lookup failed for operator %u", operid);
10840  operform = (Form_pg_operator) GETSTRUCT(opertup);
10841  oprname = NameStr(operform->oprname);
10842 
10843  /*
10844  * The idea here is to schema-qualify only if the parser would fail to
10845  * resolve the correct operator given the unqualified op name with the
10846  * specified argtypes.
10847  */
10848  switch (operform->oprkind)
10849  {
10850  case 'b':
10851  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10852  true, -1);
10853  break;
10854  case 'l':
10855  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10856  true, -1);
10857  break;
10858  case 'r':
10859  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10860  true, -1);
10861  break;
10862  default:
10863  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10864  p_result = NULL; /* keep compiler quiet */
10865  break;
10866  }
10867 
10868  if (p_result != NULL && oprid(p_result) == operid)
10869  nspname = NULL;
10870  else
10871  {
10872  nspname = get_namespace_name(operform->oprnamespace);
10873  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
10874  }
10875 
10876  appendStringInfoString(&buf, oprname);
10877 
10878  if (nspname)
10879  appendStringInfoChar(&buf, ')');
10880 
10881  if (p_result != NULL)
10882  ReleaseSysCache(p_result);
10883 
10884  ReleaseSysCache(opertup);
10885 
10886  return buf.data;
10887 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
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:78
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
#define NameStr(name)
Definition: c.h:576
#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 10674 of file ruleutils.c.

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

Referenced by make_ruledef(), pg_get_constraintdef_worker(), pg_get_indexdef_worker(), pg_get_serial_sequence(), and pg_get_triggerdef_worker().

10675 {
10676  HeapTuple tp;
10677  Form_pg_class reltup;
10678  char *relname;
10679  char *nspname;
10680  char *result;
10681 
10682  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10683  if (!HeapTupleIsValid(tp))
10684  elog(ERROR, "cache lookup failed for relation %u", relid);
10685  reltup = (Form_pg_class) GETSTRUCT(tp);
10686  relname = NameStr(reltup->relname);
10687 
10688  nspname = get_namespace_name(reltup->relnamespace);
10689  if (!nspname)
10690  elog(ERROR, "cache lookup failed for namespace %u",
10691  reltup->relnamespace);
10692 
10693  result = quote_qualified_identifier(nspname, relname);
10694 
10695  ReleaseSysCache(tp);
10696 
10697  return result;
10698 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:10574
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

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

10979 {
10980  HeapTuple tp;
10981  Form_pg_type typtup;
10982  char *typname;
10983  char *nspname;
10984  char *result;
10985 
10987  if (!HeapTupleIsValid(tp))
10988  elog(ERROR, "cache lookup failed for type %u", typid);
10989  typtup = (Form_pg_type) GETSTRUCT(tp);
10990  typname = NameStr(typtup->typname);
10991 
10992  nspname = get_namespace_name(typtup->typnamespace);
10993  if (!nspname)
10994  elog(ERROR, "cache lookup failed for namespace %u",
10995  typtup->typnamespace);
10996 
10997  result = quote_qualified_identifier(nspname, typname);
10998 
10999  ReleaseSysCache(tp);
11000 
11001  return result;
11002 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:10574
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:247
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ generate_relation_name()

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

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

10615 {
10616  HeapTuple tp;
10617  Form_pg_class reltup;
10618  bool need_qual;
10619  ListCell *nslist;
10620  char *relname;
10621  char *nspname;
10622  char *result;
10623 
10624  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10625  if (!HeapTupleIsValid(tp))
10626  elog(ERROR, "cache lookup failed for relation %u", relid);
10627  reltup = (Form_pg_class) GETSTRUCT(tp);
10628  relname = NameStr(reltup->relname);
10629 
10630  /* Check for conflicting CTE name */
10631  need_qual = false;
10632  foreach(nslist, namespaces)
10633  {
10634  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10635  ListCell *ctlist;
10636 
10637  foreach(ctlist, dpns->ctes)
10638  {
10639  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10640 
10641  if (strcmp(cte->ctename, relname) == 0)
10642  {
10643  need_qual = true;
10644  break;
10645  }
10646  }
10647  if (need_qual)
10648  break;
10649  }
10650 
10651  /* Otherwise, qualify the name if not visible in search path */
10652  if (!need_qual)
10653  need_qual = !RelationIsVisible(relid);
10654 
10655  if (need_qual)
10656  nspname = get_namespace_name(reltup->relnamespace);
10657  else
10658  nspname = NULL;
10659 
10660  result = quote_qualified_identifier(nspname, relname);
10661 
10662  ReleaseSysCache(tp);
10663 
10664  return result;
10665 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:10574
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:106
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
bool RelationIsVisible(Oid relid)
Definition: namespace.c:701
#define NameStr(name)
Definition: c.h:576
#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 9206 of file ruleutils.c.

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

Referenced by get_agg_expr().

9207 {
9208  Aggref *aggref;
9209  Aggref *original_aggref = private;
9210 
9211  if (!IsA(node, Aggref))
9212  elog(ERROR, "combining Aggref does not point to an Aggref");
9213 
9214  aggref = (Aggref *) node;
9215  get_agg_expr(aggref, context, original_aggref);
9216 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9100
#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 9100 of file ruleutils.c.

References Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggkind, 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().

9102 {
9103  StringInfo buf = context->buf;
9104  Oid argtypes[FUNC_MAX_ARGS];
9105  int nargs;
9106  bool use_variadic;
9107 
9108  /*
9109  * For a combining aggregate, we look up and deparse the corresponding
9110  * partial aggregate instead. This is necessary because our input
9111  * argument list has been replaced; the new argument list always has just
9112  * one element, which will point to a partial Aggref that supplies us with
9113  * transition states to combine.
9114  */
9115  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9116  {
9117  TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
9118 
9119  Assert(list_length(aggref->args) == 1);
9120  resolve_special_varno((Node *) tle->expr, context, original_aggref,
9122  return;
9123  }
9124 
9125  /*
9126  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9127  * to avoid printing this when recursing from the code just above.
9128  */
9129  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9130  appendStringInfoString(buf, "PARTIAL ");
9131 
9132  /* Extract the argument types as seen by the parser */
9133  nargs = get_aggregate_argtypes(aggref, argtypes);
9134 
9135  /* Print the aggregate name, schema-qualified if needed */
9136  appendStringInfo(buf, "%s(%s",
9137  generate_function_name(aggref->aggfnoid, nargs,
9138  NIL, argtypes,
9139  aggref->aggvariadic,
9140  &use_variadic,
9141  context->special_exprkind),
9142  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9143 
9144  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9145  {
9146  /*
9147  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9148  * worry about inserting VARIADIC. So we can just dump the direct
9149  * args as-is.
9150  */
9151  Assert(!aggref->aggvariadic);
9152  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9153  Assert(aggref->aggorder != NIL);
9154  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9155  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9156  }
9157  else
9158  {
9159  /* aggstar can be set only in zero-argument aggregates */
9160  if (aggref->aggstar)
9161  appendStringInfoChar(buf, '*');
9162  else
9163  {
9164  ListCell *l;
9165  int i;
9166 
9167  i = 0;
9168  foreach(l, aggref->args)
9169  {
9170  TargetEntry *tle = (TargetEntry *) lfirst(l);
9171  Node *arg = (Node *) tle->expr;
9172 
9173  Assert(!IsA(arg, NamedArgExpr));
9174  if (tle->resjunk)
9175  continue;
9176  if (i++ > 0)
9177  appendStringInfoString(buf, ", ");
9178  if (use_variadic && i == nargs)
9179  appendStringInfoString(buf, "VARIADIC ");
9180  get_rule_expr(arg, context, true);
9181  }
9182  }
9183 
9184  if (aggref->aggorder != NIL)
9185  {
9186  appendStringInfoString(buf, " ORDER BY ");
9187  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9188  }
9189  }
9190 
9191  if (aggref->aggfilter != NULL)
9192  {
9193  appendStringInfoString(buf, ") FILTER (WHERE ");
9194  get_rule_expr((Node *) aggref->aggfilter, context, false);
9195  }
9196 
9197  appendStringInfoChar(buf, ')');
9198 }
List * aggdistinct
Definition: primnodes.h:304
#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:10716
bool aggvariadic
Definition: primnodes.h:307
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6701
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5803
Definition: nodes.h:517
List * args
Definition: primnodes.h:302
bool aggstar
Definition: primnodes.h:306
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:776
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1383
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:303
List * aggdirectargs
Definition: primnodes.h:301
ParseExprKind special_exprkind
Definition: ruleutils.c:119
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
Oid aggfnoid
Definition: primnodes.h:295
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:9206
#define Assert(condition)
Definition: c.h:699
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7689
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1376
AggSplit aggsplit
Definition: primnodes.h:311
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:777
Expr * aggfilter
Definition: primnodes.h:305
StringInfo buf
Definition: ruleutils.c:111
int i
void * arg
char aggkind
Definition: primnodes.h:309
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 5296 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().

5298 {
5299  StringInfo buf = context->buf;
5300  RangeTblEntry *values_rte;
5301  char *sep;
5302  ListCell *l;
5303 
5304  if (PRETTY_INDENT(context))
5305  {
5306  context->indentLevel += PRETTYINDENT_STD;
5307  appendStringInfoChar(buf, ' ');
5308  }
5309 
5310  /*
5311  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5312  * VALUES part. This reverses what transformValuesClause() did at parse
5313  * time.
5314  */
5315  values_rte = get_simple_values_rte(query);
5316  if (values_rte)
5317  {
5318  get_values_def(values_rte->values_lists, context);
5319  return;
5320  }
5321 
5322  /*
5323  * Build up the query string - first we say SELECT
5324  */
5325  appendStringInfoString(buf, "SELECT");
5326 
5327  /* Add the DISTINCT clause if given */
5328  if (query->distinctClause != NIL)
5329  {
5330  if (query->hasDistinctOn)
5331  {
5332  appendStringInfoString(buf, " DISTINCT ON (");
5333  sep = "";
5334  foreach(l, query->distinctClause)
5335  {
5336  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5337 
5338  appendStringInfoString(buf, sep);
5340  false, context);
5341  sep = ", ";
5342  }
5343  appendStringInfoChar(buf, ')');
5344  }
5345  else
5346  appendStringInfoString(buf, " DISTINCT");
5347  }
5348 
5349  /* Then we tell what to select (the targetlist) */
5350  get_target_list(query->targetList, context, resultDesc);
5351 
5352  /* Add the FROM clause if needed */
5353  get_from_clause(query, " FROM ", context);
5354 
5355  /* Add the WHERE clause if given */
5356  if (query->jointree->quals != NULL)
5357  {
5358  appendContextKeyword(context, " WHERE ",
5360  get_rule_expr(query->jointree->quals, context, false);
5361  }
5362 
5363  /* Add the GROUP BY clause if given */
5364  if (query->groupClause != NULL || query->groupingSets != NULL)
5365  {
5366  ParseExprKind save_exprkind;
5367 
5368  appendContextKeyword(context, " GROUP BY ",
5370 
5371  save_exprkind = context->special_exprkind;
5373 
5374  if (query->groupingSets == NIL)
5375  {
5376  sep = "";
5377  foreach(l, query->groupClause)
5378  {
5379  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5380 
5381  appendStringInfoString(buf, sep);
5383  false, context);
5384  sep = ", ";
5385  }
5386  }
5387  else
5388  {
5389  sep = "";
5390  foreach(l, query->groupingSets)
5391  {
5392  GroupingSet *grp = lfirst(l);
5393 
5394  appendStringInfoString(buf, sep);
5395  get_rule_groupingset(grp, query->targetList, true, context);
5396  sep = ", ";
5397  }
5398  }
5399 
5400  context->special_exprkind = save_exprkind;
5401  }
5402 
5403  /* Add the HAVING clause if given */
5404  if (query->havingQual != NULL)
5405  {
5406  appendContextKeyword(context, " HAVING ",
5408  get_rule_expr(query->havingQual, context, false);
5409  }
5410 
5411  /* Add the WINDOW clause if needed */
5412  if (query->windowClause != NIL)
5413  get_rule_windowclause(query, context);
5414 }
#define NIL
Definition: pg_list.h:69
FromExpr * jointree
Definition: parsenodes.h:138
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5423
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5687
Index tleSortGroupRef
Definition: parsenodes.h:1207
List * groupingSets
Definition: parsenodes.h:150
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9780
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5861
#define PRETTY_INDENT(context)
Definition: ruleutils.c:99
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:1027
Node * quals
Definition: primnodes.h:1480
bool hasDistinctOn
Definition: parsenodes.h:129
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * distinctClause
Definition: parsenodes.h:156
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:7584
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5743
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
ParseExprKind special_exprkind
Definition: ruleutils.c:119
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:7689
#define lfirst(lc)
Definition: pg_list.h:106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5012
List * groupClause
Definition: parsenodes.h:148
StringInfo buf
Definition: ruleutils.c:111
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:5240
Node * havingQual
Definition: parsenodes.h:152

◆ get_coercion_expr()

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

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

9302 {
9303  StringInfo buf = context->buf;
9304 
9305  /*
9306  * Since parse_coerce.c doesn't immediately collapse application of
9307  * length-coercion functions to constants, what we'll typically see in
9308  * such cases is a Const with typmod -1 and a length-coercion function
9309  * right above it. Avoid generating redundant output. However, beware of
9310  * suppressing casts when the user actually wrote something like
9311  * 'foo'::text::char(3).
9312  *
9313  * Note: it might seem that we are missing the possibility of needing to
9314  * print a COLLATE clause for such a Const. However, a Const could only
9315  * have nondefault collation in a post-constant-folding tree, in which the
9316  * length coercion would have been folded too. See also the special
9317  * handling of CollateExpr in coerce_to_target_type(): any collation
9318  * marking will be above the coercion node, not below it.
9319  */
9320  if (arg && IsA(arg, Const) &&
9321  ((Const *) arg)->consttype == resulttype &&
9322  ((Const *) arg)->consttypmod == -1)
9323  {
9324  /* Show the constant without normal ::typename decoration */
9325  get_const_expr((Const *) arg, context, -1);
9326  }
9327  else
9328  {
9329  if (!PRETTY_PAREN(context))
9330  appendStringInfoChar(buf, '(');
9331  get_rule_expr_paren(arg, context, false, parentNode);
9332  if (!PRETTY_PAREN(context))
9333  appendStringInfoChar(buf, ')');
9334  }
9335  appendStringInfo(buf, "::%s",
9336  format_type_with_typemod(resulttype, resulttypmod));
9337 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7657
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9355
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:98
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:347
StringInfo buf
Definition: ruleutils.c:111

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

10202 {
10203  StringInfo buf = context->buf;
10204  int i;
10205  bool first = true;
10206 
10207  /* Don't print aliases if not needed */
10208  if (!colinfo->printaliases)
10209  return;
10210 
10211  for (i = 0; i < colinfo->num_new_cols; i++)
10212  {
10213  char *colname = colinfo->new_colnames[i];
10214 
10215  if (first)
10216  {
10217  appendStringInfoChar(buf, '(');
10218  first = false;
10219  }
10220  else
10221  appendStringInfoString(buf, ", ");
10223  }
10224  if (!first)
10225  appendStringInfoChar(buf, ')');
10226 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
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:111
int i
char ** new_colnames
Definition: ruleutils.c:245

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9491 {
9492  StringInfo buf = context->buf;
9493 
9494  if (OidIsValid(constval->constcollid))
9495  {
9496  Oid typcollation = get_typcollation(constval->consttype);
9497 
9498  if (constval->constcollid != typcollation)
9499  {
9500  appendStringInfo(buf, " COLLATE %s",
9502  }
9503  }
9504 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11011
Oid consttype
Definition: primnodes.h:193
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
Oid constcollid
Definition: primnodes.h:195
static char * buf
Definition: pg_test_fsync.c:67
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2799
StringInfo buf
Definition: ruleutils.c:111

◆ get_const_expr()

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

Definition at line 9355 of file ruleutils.c.

References appendStringInfo(), appendStringInfoString(), buf, deparse_context::buf, Const::constisnull, Const::consttype, Const::consttypmod, Const::constvalue, format_type_with_typemod(), get_const_collation(), getTypeOutputInfo(), OidOutputFunctionCall(), pfree(), and simple_quote_literal().

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

9356 {
9357  StringInfo buf = context->buf;
9358  Oid typoutput;
9359  bool typIsVarlena;
9360  char *extval;
9361  bool needlabel = false;
9362 
9363  if (constval->constisnull)
9364  {
9365  /*
9366  * Always label the type of a NULL constant to prevent misdecisions
9367  * about type when reparsing.
9368  */
9369  appendStringInfoString(buf, "NULL");
9370  if (showtype >= 0)
9371  {
9372  appendStringInfo(buf, "::%s",
9374  constval->consttypmod));
9375  get_const_collation(constval, context);
9376  }
9377  return;
9378  }
9379 
9380  getTypeOutputInfo(constval->consttype,
9381  &typoutput, &typIsVarlena);
9382 
9383  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9384 
9385  switch (constval->consttype)
9386  {
9387  case INT4OID:
9388 
9389  /*
9390  * INT4 can be printed without any decoration, unless it is
9391  * negative; in that case print it as '-nnn'::integer to ensure
9392  * that the output will re-parse as a constant, not as a constant
9393  * plus operator. In most cases we could get away with printing
9394  * (-nnn) instead, because of the way that gram.y handles negative
9395  * literals; but that doesn't work for INT_MIN, and it doesn't
9396  * seem that much prettier anyway.
9397  */
9398  if (extval[0] != '-')
9399  appendStringInfoString(buf, extval);
9400  else
9401  {
9402  appendStringInfo(buf, "'%s'", extval);
9403  needlabel = true; /* we must attach a cast */
9404  }
9405  break;
9406 
9407  case NUMERICOID:
9408 
9409  /*
9410  * NUMERIC can be printed without quotes if it looks like a float
9411  * constant (not an integer, and not Infinity or NaN) and doesn't
9412  * have a leading sign (for the same reason as for INT4).
9413  */
9414  if (isdigit((unsigned char) extval[0]) &&
9415  strcspn(extval, "eE.") != strlen(extval))
9416  {
9417  appendStringInfoString(buf, extval);
9418  }
9419  else
9420  {
9421  appendStringInfo(buf, "'%s'", extval);
9422  needlabel = true; /* we must attach a cast */
9423  }
9424  break;
9425 
9426  case BITOID:
9427  case VARBITOID:
9428  appendStringInfo(buf, "B'%s'", extval);
9429  break;
9430 
9431  case BOOLOID:
9432  if (strcmp(extval, "t") == 0)
9433  appendStringInfoString(buf, "true");
9434  else
9435  appendStringInfoString(buf, "false");
9436  break;
9437 
9438  default:
9439  simple_quote_literal(buf, extval);
9440  break;
9441  }
9442 
9443  pfree(extval);
9444 
9445  if (showtype < 0)
9446  return;
9447 
9448  /*
9449  * For showtype == 0, append ::typename unless the constant will be
9450  * implicitly typed as the right type when it is read in.
9451  *
9452  * XXX this code has to be kept in sync with the behavior of the parser,
9453  * especially make_const.
9454  */
9455  switch (constval->consttype)
9456  {
9457  case BOOLOID:
9458  case UNKNOWNOID:
9459  /* These types can be left unlabeled */
9460  needlabel = false;
9461  break;
9462  case INT4OID:
9463  /* We determined above whether a label is needed */
9464  break;
9465  case NUMERICOID:
9466 
9467  /*
9468  * Float-looking constants will be typed as numeric, which we
9469  * checked above; but if there's a nondefault typmod we need to
9470  * show it.
9471  */
9472  needlabel |= (constval->consttypmod >= 0);
9473  break;
9474  default:
9475  needlabel = true;
9476  break;
9477  }
9478  if (needlabel || showtype > 0)
9479  appendStringInfo(buf, "::%s",
9481  constval->consttypmod));
9482 
9483  get_const_collation(constval, context);
9484 }
Datum constvalue
Definition: primnodes.h:197
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:193
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9510
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9490
static char * buf
Definition: pg_test_fsync.c:67
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:347
int32 consttypmod
Definition: primnodes.h:194
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1832
StringInfo buf
Definition: ruleutils.c:111
bool constisnull
Definition: primnodes.h:198

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6423 {
6424  StringInfo buf = context->buf;
6425  RangeTblEntry *rte;
6426 
6427  /* Insert the WITH clause if given */
6428  get_with_clause(query, context);
6429 
6430  /*
6431  * Start the query with DELETE FROM relname
6432  */
6433  rte = rt_fetch(query->resultRelation, query->rtable);
6434  Assert(rte->rtekind == RTE_RELATION);
6435  if (PRETTY_INDENT(context))
6436  {
6437  appendStringInfoChar(buf, ' ');
6438  context->indentLevel += PRETTYINDENT_STD;
6439  }
6440  appendStringInfo(buf, "DELETE FROM %s%s",
6441  only_marker(rte),
6443  if (rte->alias != NULL)
6444  appendStringInfo(buf, " %s",
6446 
6447  /* Add the USING clause if given */
6448  get_from_clause(query, " USING ", context);
6449 
6450  /* Add a WHERE clause if given */
6451  if (query->jointree->quals != NULL)
6452  {
6453  appendContextKeyword(context, " WHERE ",
6455  get_rule_expr(query->jointree->quals, context, false);
6456  }
6457 
6458  /* Add RETURNING if present */
6459  if (query->returningList)
6460  {
6461  appendContextKeyword(context, " RETURNING",
6463  get_target_list(query->returningList, context, NULL);
6464  }
6465 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5055
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
Alias * alias
Definition: parsenodes.h:1065
FromExpr * jointree
Definition: parsenodes.h:138
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5423
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9780
#define PRETTY_INDENT(context)
Definition: ruleutils.c:99
Node * quals
Definition: primnodes.h:1480
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10614
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
List * rtable
Definition: parsenodes.h:137
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:7584
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define Assert(condition)
Definition: c.h:699
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7689
char * aliasname
Definition: primnodes.h:43
#define only_marker(rte)
Definition: ruleutils.c:471
RTEKind rtekind
Definition: parsenodes.h:962
StringInfo buf
Definition: ruleutils.c:111

◆ get_from_clause()

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

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

9781 {
9782  StringInfo buf = context->buf;
9783  bool first = true;
9784  ListCell *l;
9785 
9786  /*
9787  * We use the query's jointree as a guide to what to print. However, we
9788  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9789  * only appear at the top level of the jointree, so it's sufficient to
9790  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9791  * for NEW and OLD.
9792  */
9793  foreach(l, query->jointree->fromlist)
9794  {
9795  Node *jtnode = (Node *) lfirst(l);
9796 
9797  if (IsA(jtnode, RangeTblRef))
9798  {
9799  int varno = ((RangeTblRef *) jtnode)->rtindex;
9800  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9801 
9802  if (!rte->inFromCl)
9803  continue;
9804  }
9805 
9806  if (first)
9807  {
9808  appendContextKeyword(context, prefix,
9810  first = false;
9811 
9812  get_from_clause_item(jtnode, query, context);
9813  }
9814  else
9815  {
9816  StringInfoData itembuf;
9817 
9818  appendStringInfoString(buf, ", ");
9819 
9820  /*
9821  * Put the new FROM item's text into itembuf so we can decide
9822  * after we've got it whether or not it needs to go on a new line.
9823  */
9824  initStringInfo(&itembuf);
9825  context->buf = &itembuf;
9826 
9827  get_from_clause_item(jtnode, query, context);
9828 
9829  /* Restore context's output buffer */
9830  context->buf = buf;
9831 
9832  /* Consider line-wrapping if enabled */
9833  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9834  {
9835  /* Does the new item start with a new line? */
9836  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9837  {
9838  /* If so, we shouldn't add anything */
9839  /* instead, remove any trailing spaces currently in buf */
9841  }
9842  else
9843  {
9844  char *trailing_nl;
9845 
9846  /* Locate the start of the current line in the buffer */
9847  trailing_nl = strrchr(buf->data, '\n');
9848  if (trailing_nl == NULL)
9849  trailing_nl = buf->data;
9850  else
9851  trailing_nl++;
9852 
9853  /*
9854  * Add a newline, plus some indentation, if the new item
9855  * would cause an overflow.
9856  */
9857  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9858  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9861  }
9862  }
9863 
9864  /* Add the new item */
9865  appendStringInfoString(buf, itembuf.data);
9866 
9867  /* clean up */
9868  pfree(itembuf.data);
9869  }
9870  }
9871 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
FromExpr * jointree
Definition: parsenodes.h:138
#define PRETTYINDENT_VAR
Definition: ruleutils.c:85
Definition: nodes.h:517
#define PRETTY_INDENT(context)
Definition: ruleutils.c:99
List * fromlist
Definition: primnodes.h:1479
void pfree(void *pointer)
Definition: mcxt.c:1031
List * rtable
Definition: parsenodes.h:137
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:7584
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7638
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:111
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9874

◆ get_from_clause_coldeflist()

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

Definition at line 10241 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, attcollation, attname, atttypid, 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().

10244 {
10245  StringInfo buf = context->buf;
10246  ListCell *l1;
10247  ListCell *l2;
10248  ListCell *l3;
10249  ListCell *l4;
10250  int i;
10251 
10252  appendStringInfoChar(buf, '(');
10253 
10254  /* there's no forfour(), so must chase one list the hard way */
10255  i = 0;
10256  l4 = list_head(rtfunc->funccolnames);
10257  forthree(l1, rtfunc->funccoltypes,
10258  l2, rtfunc->funccoltypmods,
10259  l3, rtfunc->funccolcollations)
10260  {
10261  Oid atttypid = lfirst_oid(l1);
10262  int32 atttypmod = lfirst_int(l2);
10263  Oid attcollation = lfirst_oid(l3);
10264  char *attname;
10265 
10266  if (colinfo)
10267  attname = colinfo->colnames[i];
10268  else
10269  attname = strVal(lfirst(l4));
10270 
10271  Assert(attname); /* shouldn't be any dropped columns here */
10272 
10273  if (i > 0)
10274  appendStringInfoString(buf, ", ");
10275  appendStringInfo(buf, "%s %s",
10276  quote_identifier(attname),
10277  format_type_with_typemod(atttypid, atttypmod));
10278  if (OidIsValid(attcollation) &&
10279  attcollation != get_typcollation(atttypid))
10280  appendStringInfo(buf, " COLLATE %s",
10281  generate_collation_name(attcollation));
10282 
10283  l4 = lnext(l4);
10284  i++;
10285  }
10286 
10287  appendStringInfoChar(buf, ')');
10288 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
#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:605
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11011
signed int int32
Definition: c.h:313
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
NameData attname
Definition: pg_attribute.h:40
#define lfirst_int(lc)
Definition: pg_list.h:107
Oid attcollation
Definition: pg_attribute.h:161
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
Oid atttypid
Definition: pg_attribute.h:49
#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:347
List * funccoltypmods
Definition: parsenodes.h:1103
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2799
List * funccolcollations
Definition: parsenodes.h:1104
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
StringInfo buf
Definition: ruleutils.c:111
int i
#define lfirst_oid(lc)
Definition: pg_list.h:108
char ** colnames
Definition: ruleutils.c:228

◆ get_from_clause_item()

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

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

9875 {
9876  StringInfo buf = context->buf;
9878 
9879  if (IsA(jtnode, RangeTblRef))
9880  {
9881  int varno = ((RangeTblRef *) jtnode)->rtindex;
9882  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9883  char *refname = get_rtable_name(varno, context);
9884  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
9885  RangeTblFunction *rtfunc1 = NULL;
9886  bool printalias;
9887 
9888  if (rte->lateral)
9889  appendStringInfoString(buf, "LATERAL ");
9890 
9891  /* Print the FROM item proper */
9892  switch (rte->rtekind)
9893  {
9894  case RTE_RELATION:
9895  /* Normal relation RTE */
9896  appendStringInfo(buf, "%s%s",
9897  only_marker(rte),
9899  context->namespaces));
9900  break;
9901  case RTE_SUBQUERY:
9902  /* Subquery RTE */
9903  appendStringInfoChar(buf, '(');
9904  get_query_def(rte->subquery, buf, context->namespaces, NULL,
9905  context->prettyFlags, context->wrapColumn,
9906  context->indentLevel);
9907  appendStringInfoChar(buf, ')');
9908  break;
9909  case RTE_FUNCTION:
9910  /* Function RTE */
9911  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
9912 
9913  /*
9914  * Omit ROWS FROM() syntax for just one function, unless it
9915  * has both a coldeflist and WITH ORDINALITY. If it has both,
9916  * we must use ROWS FROM() syntax to avoid ambiguity about
9917  * whether the coldeflist includes the ordinality column.
9918  */
9919  if (list_length(rte->functions) == 1 &&
9920  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
9921  {
9922  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
9923  /* we'll print the coldeflist below, if it has one */
9924  }
9925  else
9926  {
9927  bool all_unnest;
9928  ListCell *lc;
9929 
9930  /*
9931  * If all the function calls in the list are to unnest,
9932  * and none need a coldeflist, then collapse the list back
9933  * down to UNNEST(args). (If we had more than one
9934  * built-in unnest function, this would get more
9935  * difficult.)
9936  *
9937  * XXX This is pretty ugly, since it makes not-terribly-
9938  * future-proof assumptions about what the parser would do
9939  * with the output; but the alternative is to emit our
9940  * nonstandard ROWS FROM() notation for what might have
9941  * been a perfectly spec-compliant multi-argument
9942  * UNNEST().
9943  */
9944  all_unnest = true;
9945  foreach(lc, rte->functions)
9946  {
9947  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9948 
9949  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
9950  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
9951  rtfunc->funccolnames != NIL)
9952  {
9953  all_unnest = false;
9954  break;
9955  }
9956  }
9957 
9958  if (all_unnest)
9959  {
9960  List *allargs = NIL;
9961 
9962  foreach(lc, rte->functions)
9963  {
9964  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9965  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
9966 
9967  allargs = list_concat(allargs, list_copy(args));
9968  }
9969 
9970  appendStringInfoString(buf, "UNNEST(");
9971  get_rule_expr((Node *) allargs, context, true);
9972  appendStringInfoChar(buf, ')');
9973  }
9974  else
9975  {
9976  int funcno = 0;
9977 
9978  appendStringInfoString(buf, "ROWS FROM(");
9979  foreach(lc, rte->functions)
9980  {
9981  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
9982 
9983  if (funcno > 0)
9984  appendStringInfoString(buf, ", ");
9985  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
9986  if (rtfunc->funccolnames != NIL)
9987  {
9988  /* Reconstruct the column definition list */
9989  appendStringInfoString(buf, " AS ");
9991  NULL,
9992  context);
9993  }
9994  funcno++;
9995  }
9996  appendStringInfoChar(buf, ')');
9997  }
9998  /* prevent printing duplicate coldeflist below */
9999  rtfunc1 = NULL;
10000  }
10001  if (rte->funcordinality)
10002  appendStringInfoString(buf, " WITH ORDINALITY");
10003  break;
10004  case RTE_TABLEFUNC:
10005  get_tablefunc(rte->tablefunc, context, true);
10006  break;
10007  case RTE_VALUES:
10008  /* Values list RTE */
10009  appendStringInfoChar(buf, '(');
10010  get_values_def(rte->values_lists, context);
10011  appendStringInfoChar(buf, ')');
10012  break;
10013  case RTE_CTE:
10015  break;
10016  default:
10017  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10018  break;
10019  }
10020 
10021  /* Print the relation alias, if needed */
10022  printalias = false;
10023  if (rte->alias != NULL)
10024  {
10025  /* Always print alias if user provided one */
10026  printalias = true;
10027  }
10028  else if (colinfo->printaliases)
10029  {
10030  /* Always print alias if we need to print column aliases */
10031  printalias = true;
10032  }
10033  else if (rte->rtekind == RTE_RELATION)
10034  {
10035  /*
10036  * No need to print alias if it's same as relation name (this
10037  * would normally be the case, but not if set_rtable_names had to
10038  * resolve a conflict).
10039  */
10040  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10041  printalias = true;
10042  }
10043  else if (rte->rtekind == RTE_FUNCTION)
10044  {
10045  /*
10046  * For a function RTE, always print alias. This covers possible
10047  * renaming of the function and/or instability of the
10048  * FigureColname rules for things that aren't simple functions.
10049  * Note we'd need to force it anyway for the columndef list case.
10050  */
10051  printalias = true;
10052  }
10053  else if (rte->rtekind == RTE_VALUES)
10054  {
10055  /* Alias is syntactically required for VALUES */
10056  printalias = true;
10057  }
10058  else if (rte->rtekind == RTE_CTE)
10059  {
10060  /*
10061  * No need to print alias if it's same as CTE name (this would
10062  * normally be the case, but not if set_rtable_names had to
10063  * resolve a conflict).
10064  */
10065  if (strcmp(refname, rte->ctename) != 0)
10066  printalias = true;
10067  }
10068  if (printalias)
10069  appendStringInfo(buf, " %s", quote_identifier(refname));
10070 
10071  /* Print the column definitions or aliases, if needed */
10072  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10073  {
10074  /* Reconstruct the columndef list, which is also the aliases */
10075  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10076  }
10077  else
10078  {
10079  /* Else print column aliases as needed */
10080  get_column_alias_list(colinfo, context);
10081  }
10082 
10083  /* Tablesample clause must go after any alias */
10084  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10085  get_tablesample_def(rte->tablesample, context);
10086  }
10087  else if (IsA(jtnode, JoinExpr))
10088  {
10089  JoinExpr *j = (JoinExpr *) jtnode;
10090  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10091  bool need_paren_on_right;
10092 
10093  need_paren_on_right = PRETTY_PAREN(context) &&
10094  !IsA(j->rarg, RangeTblRef) &&
10095  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
10096 
10097  if (!PRETTY_PAREN(context) || j->alias != NULL)
10098  appendStringInfoChar(buf, '(');
10099 
10100  get_from_clause_item(j->larg, query, context);
10101 
10102  switch (j->jointype)
10103  {
10104  case JOIN_INNER:
10105  if (j->quals)
10106  appendContextKeyword(context, " JOIN ",
10110  else
10111  appendContextKeyword(context, " CROSS JOIN ",
10115  break;
10116  case JOIN_LEFT:
10117  appendContextKeyword(context, " LEFT JOIN ",
10121  break;
10122  case JOIN_FULL:
10123  appendContextKeyword(context, " FULL JOIN ",
10127  break;
10128  case JOIN_RIGHT:
10129  appendContextKeyword(context, " RIGHT JOIN ",
10133  break;
10134  default:
10135  elog(ERROR, "unrecognized join type: %d",
10136  (int) j->jointype);
10137  }
10138 
10139  if (need_paren_on_right)
10140  appendStringInfoChar(buf, '(');
10141  get_from_clause_item(j->rarg, query, context);
10142  if (need_paren_on_right)
10143  appendStringInfoChar(buf, ')');
10144 
10145  if (j->usingClause)
10146  {
10147  ListCell *lc;
10148  bool first = true;
10149 
10150  appendStringInfoString(buf, " USING (");
10151  /* Use the assigned names, not what's in usingClause */
10152  foreach(lc, colinfo->usingNames)
10153  {
10154  char *colname = (char *) lfirst(lc);
10155 
10156  if (first)
10157  first = false;
10158  else
10159  appendStringInfoString(buf, ", ");
10161  }
10162  appendStringInfoChar(buf, ')');
10163  }
10164  else if (j->quals)
10165  {
10166  appendStringInfoString(buf, " ON ");
10167  if (!PRETTY_PAREN(context))
10168  appendStringInfoChar(buf, '(');
10169  get_rule_expr(j->quals, context, false);
10170  if (!PRETTY_PAREN(context))
10171  appendStringInfoChar(buf, ')');
10172  }
10173  else if (j->jointype != JOIN_INNER)
10174  {
10175  /* If we didn't say CROSS JOIN above, we must provide an ON */
10176  appendStringInfoString(buf, " ON TRUE");
10177  }
10178 
10179  if (!PRETTY_PAREN(context) || j->alias != NULL)
10180  appendStringInfoChar(buf, ')');
10181 
10182  /* Yes, it's correct to put alias after the right paren ... */
10183  if (j->alias != NULL)
10184  {
10185  appendStringInfo(buf, " %s",
10187  get_column_alias_list(colinfo, context);
10188  }
10189  }
10190  else
10191  elog(ERROR, "unrecognized node type: %d",
10192  (int) nodeTag(jtnode));
10193 }
List * namespaces
Definition: ruleutils.c:112
#define NIL
Definition: pg_list.h:69
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10594
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:84
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
Alias * alias
Definition: parsenodes.h:1065
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:517
List * list_concat(List *list1, List *list2)
Definition: list.c:321
bool funcordinality
Definition: parsenodes.h:1017
List * values_lists
Definition: parsenodes.h:1027
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10614
Node * larg
Definition: primnodes.h:1459
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10294
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:274
TableFunc * tablefunc
Definition: parsenodes.h:1022
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:98
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7584
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:278
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
List * usingClause
Definition: primnodes.h:1461
Node * quals
Definition: primnodes.h:1462
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9662
Node * rarg
Definition: primnodes.h:1460
Alias * alias
Definition: primnodes.h:1463
JoinType jointype
Definition: primnodes.h:1457
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7689
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:43
List * functions
Definition: parsenodes.h:1016
#define only_marker(rte)
Definition: ruleutils.c:471
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:4939
#define nodeTag(nodeptr)
Definition: nodes.h:522
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5012
RTEKind rtekind
Definition: parsenodes.h:962
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10201
char * ctename
Definition: parsenodes.h:1032
Query * subquery
Definition: parsenodes.h:985
StringInfo buf
Definition: ruleutils.c:111
#define elog
Definition: elog.h:219
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10241
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8904
int rtindex
Definition: primnodes.h:1464
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:980
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4492
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:9874

◆ get_func_expr()

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

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

9017 {
9018  StringInfo buf = context->buf;
9019  Oid funcoid = expr->funcid;
9020  Oid argtypes[FUNC_MAX_ARGS];
9021  int nargs;
9022  List *argnames;
9023  bool use_variadic;
9024  ListCell *l;
9025 
9026  /*
9027  * If the function call came from an implicit coercion, then just show the
9028  * first argument --- unless caller wants to see implicit coercions.
9029  */
9030  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9031  {
9032  get_rule_expr_paren((Node *) linitial(expr->args), context,
9033  false, (Node *) expr);
9034  return;
9035  }
9036 
9037  /*
9038  * If the function call came from a cast, then show the first argument
9039  * plus an explicit cast operation.
9040  */
9041  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9043  {
9044  Node *arg = linitial(expr->args);
9045  Oid rettype = expr->funcresulttype;
9046  int32 coercedTypmod;
9047 
9048  /* Get the typmod if this is a length-coercion function */
9049  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9050 
9051  get_coercion_expr(arg, context,
9052  rettype, coercedTypmod,
9053  (Node *) expr);
9054 
9055  return;
9056  }
9057 
9058  /*
9059  * Normal function: display as proname(args). First we need to extract
9060  * the argument datatypes.
9061  */
9062  if (list_length(expr->args) > FUNC_MAX_ARGS)
9063  ereport(ERROR,
9064  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9065  errmsg("too many arguments")));
9066  nargs = 0;
9067  argnames = NIL;
9068  foreach(l, expr->args)
9069  {
9070  Node *arg = (Node *) lfirst(l);
9071 
9072  if (IsA(arg, NamedArgExpr))
9073  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9074  argtypes[nargs] = exprType(arg);
9075  nargs++;
9076  }
9077 
9078  appendStringInfo(buf, "%s(",
9079  generate_function_name(funcoid, nargs,
9080  argnames, argtypes,
9081  expr->funcvariadic,
9082  &use_variadic,
9083  context->special_exprkind));
9084  nargs = 0;
9085  foreach(l, expr->args)
9086  {
9087  if (nargs++ > 0)
9088  appendStringInfoString(buf, ", ");
9089  if (use_variadic && lnext(l) == NULL)
9090  appendStringInfoString(buf, "VARIADIC ");
9091  get_rule_expr((Node *) lfirst(l), context, true);
9092  }
9093  appendStringInfoChar(buf, ')');
9094 }
Oid funcresulttype
Definition: primnodes.h:451
#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:10716
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7657
List * args
Definition: primnodes.h:458
Definition: nodes.h:517
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:313
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:455
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:450
#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:9299
ParseExprKind special_exprkind
Definition: ruleutils.c:119
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:7689
#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:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
Definition: pg_list.h:45
bool funcvariadic
Definition: primnodes.h:453

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

6003 {
6004  StringInfo buf = context->buf;
6005  RangeTblEntry *select_rte = NULL;
6006  RangeTblEntry *values_rte = NULL;
6007  RangeTblEntry *rte;
6008  char *sep;
6009  ListCell *l;
6010  List *strippedexprs;
6011 
6012  /* Insert the WITH clause if given */
6013  get_with_clause(query, context);
6014 
6015  /*
6016  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6017  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6018  */
6019  foreach(l, query->rtable)
6020  {
6021  rte = (RangeTblEntry *) lfirst(l);
6022 
6023  if (rte->rtekind == RTE_SUBQUERY)
6024  {
6025  if (select_rte)
6026  elog(ERROR, "too many subquery RTEs in INSERT");
6027  select_rte = rte;
6028  }
6029 
6030  if (rte->rtekind == RTE_VALUES)
6031  {
6032  if (values_rte)
6033  elog(ERROR, "too many values RTEs in INSERT");
6034  values_rte = rte;
6035  }
6036  }
6037  if (select_rte && values_rte)
6038  elog(ERROR, "both subquery and values RTEs in INSERT");
6039 
6040  /*
6041  * Start the query with INSERT INTO relname
6042  */
6043  rte = rt_fetch(query->resultRelation, query->rtable);
6044  Assert(rte->rtekind == RTE_RELATION);
6045 
6046  if (PRETTY_INDENT(context))
6047  {
6048  context->indentLevel += PRETTYINDENT_STD;
6049  appendStringInfoChar(buf, ' ');
6050  }
6051  appendStringInfo(buf, "INSERT INTO %s ",
6053  /* INSERT requires AS keyword for target alias */
6054  if (rte->alias != NULL)
6055  appendStringInfo(buf, "AS %s ",
6057 
6058  /*
6059  * Add the insert-column-names list. Any indirection decoration needed on
6060  * the column names can be inferred from the top targetlist.
6061  */
6062  strippedexprs = NIL;
6063  sep = "";
6064  if (query->targetList)
6065  appendStringInfoChar(buf, '(');
6066  foreach(l, query->targetList)
6067  {
6068  TargetEntry *tle = (TargetEntry *) lfirst(l);
6069 
6070  if (tle->resjunk)
6071  continue; /* ignore junk entries */
6072 
6073  appendStringInfoString(buf, sep);
6074  sep = ", ";
6075 
6076  /*
6077  * Put out name of target column; look in the catalogs, not at
6078  * tle->resname, since resname will fail to track RENAME.
6079  */
6082  tle->resno,
6083  false)));
6084 
6085  /*
6086  * Print any indirection needed (subfields or subscripts), and strip
6087  * off the top-level nodes representing the indirection assignments.
6088  * Add the stripped expressions to strippedexprs. (If it's a
6089  * single-VALUES statement, the stripped expressions are the VALUES to
6090  * print below. Otherwise they're just Vars and not really
6091  * interesting.)
6092  */
6093  strippedexprs = lappend(strippedexprs,
6094  processIndirection((Node *) tle->expr,
6095  context));
6096  }
6097  if (query->targetList)
6098  appendStringInfoString(buf, ") ");
6099 
6100  if (query->override)
6101  {
6102  if (query->override == OVERRIDING_SYSTEM_VALUE)
6103  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6104  else if (query->override == OVERRIDING_USER_VALUE)
6105  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6106  }
6107 
6108  if (select_rte)
6109  {
6110  /* Add the SELECT */
6111  get_query_def(select_rte->subquery, buf, NIL, NULL,
6112  context->prettyFlags, context->wrapColumn,
6113  context->indentLevel);
6114  }
6115  else if (values_rte)
6116  {
6117  /* Add the multi-VALUES expression lists */
6118  get_values_def(values_rte->values_lists, context);
6119  }
6120  else if (strippedexprs)
6121  {
6122  /* Add the single-VALUES expression list */
6123  appendContextKeyword(context, "VALUES (",
6125  get_rule_expr((Node *) strippedexprs, context, false);
6126  appendStringInfoChar(buf, ')');
6127  }
6128  else
6129  {
6130  /* No expressions, so it must be DEFAULT VALUES */
6131  appendStringInfoString(buf, "DEFAULT VALUES");
6132  }
6133 
6134  /* Add ON CONFLICT if present */
6135  if (query->onConflict)
6136  {
6137  OnConflictExpr *confl = query->onConflict;
6138 
6139  appendStringInfoString(buf, " ON CONFLICT");
6140 
6141  if (confl->arbiterElems)
6142  {
6143  /* Add the single-VALUES expression list */
6144  appendStringInfoChar(buf, '(');
6145  get_rule_expr((Node *) confl->arbiterElems, context, false);
6146  appendStringInfoChar(buf, ')');
6147 
6148  /* Add a WHERE clause (for partial indexes) if given */
6149  if (confl->arbiterWhere != NULL)
6150  {
6151  bool save_varprefix;
6152 
6153  /*
6154  * Force non-prefixing of Vars, since parser assumes that they
6155  * belong to target relation. WHERE clause does not use
6156  * InferenceElem, so this is separately required.
6157  */
6158  save_varprefix = context->varprefix;
6159  context->varprefix = false;
6160 
6161  appendContextKeyword(context, " WHERE ",
6163  get_rule_expr(confl->arbiterWhere, context, false);
6164 
6165  context->varprefix = save_varprefix;
6166  }
6167  }
6168  else if (OidIsValid(confl->constraint))
6169  {
6170  char *constraint = get_constraint_name(confl->constraint);
6171 
6172  if (!constraint)
6173  elog(ERROR, "cache lookup failed for constraint %u",
6174  confl->constraint);
6175  appendStringInfo(buf, " ON CONSTRAINT %s",
6176  quote_identifier(constraint));
6177  }
6178 
6179  if (confl->action == ONCONFLICT_NOTHING)
6180  {
6181  appendStringInfoString(buf, " DO NOTHING");
6182  }
6183  else
6184  {
6185  appendStringInfoString(buf, " DO UPDATE SET ");
6186  /* Deparse targetlist */
6188  context, rte);
6189 
6190  /* Add a WHERE clause if given */
6191  if (confl->onConflictWhere != NULL)
6192  {
6193  appendContextKeyword(context, " WHERE ",
6195  get_rule_expr(confl->onConflictWhere, context, false);
6196  }
6197  }
6198  }
6199 
6200  /* Add RETURNING if present */
6201  if (query->returningList)
6202  {
6203  appendContextKeyword(context, " RETURNING",
6205  get_target_list(query->returningList, context, NULL);
6206  }
6207 }
#define NIL
Definition: pg_list.h:69
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5055
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
Alias * alias
Definition: parsenodes.h:1065
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:982
OnConflictExpr * onConflict
Definition: parsenodes.h:144
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10381
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5423
Definition: nodes.h:517
#define PRETTY_INDENT(context)
Definition: ruleutils.c:99
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6270
#define OidIsValid(objectId)
Definition: c.h:605
List * values_lists
Definition: parsenodes.h:1027
List * targetList
Definition: parsenodes.h:140
List * arbiterElems
Definition: primnodes.h:1498
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10614
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1383
List * rtable
Definition: parsenodes.h:137
#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:7584
AttrNumber resno
Definition: primnodes.h:1377
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:83
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1495
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
OverridingKind override
Definition: parsenodes.h:142
#define Assert(condition)
Definition: c.h:699
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7689
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:43
Expr * expr
Definition: primnodes.h:1376
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4939
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5012
RTEKind rtekind
Definition: parsenodes.h:962
Node * arbiterWhere
Definition: primnodes.h:1500
Query * subquery
Definition: parsenodes.h:985
StringInfo buf
Definition: ruleutils.c:111
List * onConflictSet
Definition: primnodes.h:1504
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:1505
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 6786 of file ruleutils.c.

References Alias::aliasname, Assert, attname, attnum, 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(), 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().

6788 {
6789  RangeTblEntry *rte;
6791  int netlevelsup;
6792  deparse_namespace *dpns;
6794  Node *expr;
6795 
6796  /*
6797  * If it's a RowExpr that was expanded from a whole-row Var, use the
6798  * column names attached to it.
6799  */
6800  if (IsA(var, RowExpr))
6801  {
6802  RowExpr *r = (RowExpr *) var;
6803 
6804  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6805  return strVal(list_nth(r->colnames, fieldno - 1));
6806  }
6807 
6808  /*
6809  * If it's a Param of type RECORD, try to find what the Param refers to.
6810  */
6811  if (IsA(var, Param))
6812  {
6813  Param *param = (Param *) var;
6814  ListCell *ancestor_cell;
6815 
6816  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6817  if (expr)
6818  {
6819  /* Found a match, so recurse to decipher the field name */
6820  deparse_namespace save_dpns;
6821  const char *result;
6822 
6823  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6824  result = get_name_for_var_field((Var *) expr, fieldno,
6825  0, context);
6826  pop_ancestor_plan(dpns, &save_dpns);
6827  return result;
6828  }
6829  }
6830 
6831  /*
6832  * If it's a Var of type RECORD, we have to find what the Var refers to;
6833  * if not, we can use get_expr_result_tupdesc().
6834  */
6835  if (!IsA(var, Var) ||
6836  var->vartype != RECORDOID)
6837  {
6838  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
6839  /* Got the tupdesc, so we can extract the field name */
6840  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6841  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
6842  }
6843 
6844  /* Find appropriate nesting depth */
6845  netlevelsup = var->varlevelsup + levelsup;
6846  if (netlevelsup >= list_length(context->namespaces))
6847  elog(ERROR, "bogus varlevelsup: %d offset %d",
6848  var->varlevelsup, levelsup);
6849  dpns = (deparse_namespace *) list_nth(context->namespaces,
6850  netlevelsup);
6851 
6852  /*
6853  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6854  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6855  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6856  */
6857  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6858  {
6859  rte = rt_fetch(var->varno, dpns->rtable);
6860  attnum = var->varattno;
6861  }
6862  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
6863  {
6864  TargetEntry *tle;
6865  deparse_namespace save_dpns;
6866  const char *result;
6867 
6868  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
6869  if (!tle)
6870  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
6871 
6872  Assert(netlevelsup == 0);
6873  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
6874 
6875  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6876  levelsup, context);
6877 
6878  pop_child_plan(dpns, &save_dpns);
6879  return result;
6880  }
6881  else if (var->varno == INNER_VAR && dpns->inner_tlist)
6882  {
6883  TargetEntry *tle;
6884  deparse_namespace save_dpns;
6885  const char *result;
6886 
6887  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
6888  if (!tle)
6889  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
6890 
6891  Assert(netlevelsup == 0);
6892  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
6893 
6894  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6895  levelsup, context);
6896 
6897  pop_child_plan(dpns, &save_dpns);
6898  return result;
6899  }
6900  else if (var->varno == INDEX_VAR && dpns->index_tlist)
6901  {
6902  TargetEntry *tle;
6903  const char *result;
6904 
6905  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
6906  if (!tle)
6907  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
6908 
6909  Assert(netlevelsup == 0);
6910 
6911  result = get_name_for_var_field((Var *) tle->expr, fieldno,
6912  levelsup, context);
6913 
6914  return result;
6915  }
6916  else
6917  {
6918  elog(ERROR, "bogus varno: %d", var->varno);
6919  return NULL; /* keep compiler quiet */
6920  }
6921 
6922  if (attnum == InvalidAttrNumber)
6923  {
6924  /* Var is whole-row reference to RTE, so select the right field */
6925  return get_rte_attribute_name(rte, fieldno);
6926  }
6927 
6928  /*
6929  * This part has essentially the same logic as the parser's
6930  * expandRecordVariable() function, but we are dealing with a different
6931  * representation of the input context, and we only need one field name
6932  * not a TupleDesc. Also, we need special cases for finding subquery and
6933  * CTE subplans when deparsing Plan trees.
6934  */
6935  expr = (Node *) var; /* default if we can't drill down */
6936 
6937  switch (rte->rtekind)
6938  {
6939  case RTE_RELATION:
6940  case RTE_VALUES:
6941  case RTE_NAMEDTUPLESTORE:
6942 
6943  /*
6944  * This case should not occur: a column of a table, values list,
6945  * or ENR shouldn't have type RECORD. Fall through and fail (most
6946  * likely) at the bottom.
6947  */
6948  break;
6949  case RTE_SUBQUERY:
6950  /* Subselect-in-FROM: examine sub-select's output expr */
6951  {
6952  if (rte->subquery)
6953  {
6955  attnum);
6956 
6957  if (ste == NULL || ste->resjunk)
6958  elog(ERROR, "subquery %s does not have attribute %d",
6959  rte->eref->aliasname, attnum);
6960  expr = (Node *) ste->expr;
6961  if (IsA(expr, Var))
6962  {
6963  /*
6964  * Recurse into the sub-select to see what its Var
6965  * refers to. We have to build an additional level of
6966  * namespace to keep in step with varlevelsup in the
6967  * subselect.
6968  */
6969  deparse_namespace mydpns;
6970  const char *result;
6971 
6972  set_deparse_for_query(&mydpns, rte->subquery,
6973  context->namespaces);
6974 
6975  context->namespaces = lcons(&mydpns,
6976  context->namespaces);
6977 
6978  result = get_name_for_var_field((Var *) expr, fieldno,
6979  0, context);
6980 
6981  context->namespaces =
6982  list_delete_first(context->namespaces);
6983 
6984  return result;
6985  }
6986  /* else fall through to inspect the expression */
6987  }
6988  else
6989  {
6990  /*
6991  * We're deparsing a Plan tree so we don't have complete
6992  * RTE entries (in particular, rte->subquery is NULL). But
6993  * the only place we'd see a Var directly referencing a
6994  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
6995  * look into the child plan's tlist instead.
6996  */
6997  TargetEntry *tle;
6998  deparse_namespace save_dpns;
6999  const char *result;
7000 
7001  if (!dpns->inner_planstate)
7002  elog(ERROR, "failed to find plan for subquery %s",
7003  rte->eref->aliasname);
7004  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7005  if (!tle)
7006  elog(ERROR, "bogus varattno for subquery var: %d",
7007  attnum);
7008  Assert(netlevelsup == 0);
7009  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7010 
7011  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7012  levelsup, context);
7013 
7014  pop_child_plan(dpns, &save_dpns);
7015  return result;
7016  }
7017  }
7018  break;
7019  case RTE_JOIN:
7020  /* Join RTE --- recursively inspect the alias variable */
7021  if (rte->joinaliasvars == NIL)
7022  elog(ERROR, "cannot decompile join alias var in plan tree");
7023  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7024  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7025  Assert(expr != NULL);
7026  /* we intentionally don't strip implicit coercions here */
7027  if (IsA(expr, Var))
7028  return get_name_for_var_field((Var *) expr, fieldno,
7029  var->varlevelsup + levelsup,
7030  context);
7031  /* else fall through to inspect the expression */
7032  break;
7033  case RTE_FUNCTION:
7034  case RTE_TABLEFUNC:
7035 
7036  /*
7037  * We couldn't get here unless a function is declared with one of
7038  * its result columns as RECORD, which is not allowed.
7039  */
7040  break;
7041  case RTE_CTE:
7042  /* CTE reference: examine subquery's output expr */
7043  {
7044  CommonTableExpr *cte = NULL;
7045  Index ctelevelsup;
7046  ListCell *lc;
7047 
7048  /*
7049  * Try to find the referenced CTE using the namespace stack.
7050  */
7051  ctelevelsup = rte->ctelevelsup + netlevelsup;
7052  if (ctelevelsup >= list_length(context->namespaces))
7053  lc = NULL;
7054  else
7055  {
7056  deparse_namespace *ctedpns;
7057 
7058  ctedpns = (deparse_namespace *)
7059  list_nth(context->namespaces, ctelevelsup);
7060  foreach(lc, ctedpns->ctes)
7061  {
7062  cte = (CommonTableExpr *) lfirst(lc);
7063  if (strcmp(cte->ctename, rte->ctename) == 0)
7064  break;
7065  }
7066  }
7067  if (lc != NULL)
7068  {
7069  Query *ctequery = (Query *) cte->ctequery;
7071  attnum);
7072 
7073  if (ste == NULL || ste->resjunk)
7074  elog(ERROR, "subquery %s does not have attribute %d",
7075  rte->eref->aliasname, attnum);
7076  expr = (Node *) ste->expr;
7077  if (IsA(expr, Var))
7078  {
7079  /*
7080  * Recurse into the CTE to see what its Var refers to.
7081  * We have to build an additional level of namespace
7082  * to keep in step with varlevelsup in the CTE.
7083  * Furthermore it could be an outer CTE, so we may
7084  * have to delete some levels of namespace.
7085  */
7086  List *save_nslist = context->namespaces;
7087  List *new_nslist;
7088  deparse_namespace mydpns;
7089  const char *result;
7090 
7091  set_deparse_for_query(&mydpns, ctequery,
7092  context->namespaces);
7093 
7094  new_nslist = list_copy_tail(context->namespaces,
7095  ctelevelsup);
7096  context->namespaces = lcons(&mydpns, new_nslist);
7097 
7098  result = get_name_for_var_field((Var *) expr, fieldno,
7099  0, context);
7100 
7101  context->namespaces = save_nslist;
7102 
7103  return result;
7104  }
7105  /* else fall through to inspect the expression */
7106  }
7107  else
7108  {
7109  /*
7110  * We're deparsing a Plan tree so we don't have a CTE
7111  * list. But the only place we'd see a Var directly
7112  * referencing a CTE RTE is in a CteScan plan node, and we
7113  * can look into the subplan's tlist instead.
7114  */
7115  TargetEntry *tle;
7116  deparse_namespace save_dpns;
7117  const char *result;
7118 
7119  if (!dpns->inner_planstate)
7120  elog(ERROR, "failed to find plan for CTE %s",
7121  rte->eref->aliasname);
7122  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7123  if (!tle)
7124  elog(ERROR, "bogus varattno for subquery var: %d",
7125  attnum);
7126  Assert(netlevelsup == 0);
7127  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7128 
7129  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7130  levelsup, context);
7131 
7132  pop_child_plan(dpns, &save_dpns);
7133  return result;
7134  }
7135  }
7136  break;
7137  }
7138 
7139  /*
7140  * We now have an expression we can't expand any more, so see if
7141  * get_expr_result_tupdesc() can do anything with it.
7142  */
7143  tupleDesc = get_expr_result_tupdesc(expr, false);
7144  /* Got the tupdesc, so we can extract the field name */
7145  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7146  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7147 }
List * namespaces
Definition: ruleutils.c:112
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
List * joinaliasvars
Definition: parsenodes.h:1006
Index varlevelsup
Definition: primnodes.h:174
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7158
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Definition: nodes.h:517
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:169
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4656
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
PlanState * inner_planstate
Definition: ruleutils.c:163
Definition: primnodes.h:164
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1383
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
List * colnames
Definition: primnodes.h:1007
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:412
Oid vartype
Definition: primnodes.h:171
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:4586
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:167
List * outer_tlist
Definition: ruleutils.c:164
unsigned int Index
Definition: c.h:442
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6786
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:154
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:4603
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:43
Expr * expr
Definition: primnodes.h:1376
PlanState * outer_planstate
Definition: ruleutils.c:162
static int list_length(const List *l)
Definition: pg_list.h:89
Index ctelevelsup
Definition: parsenodes.h:1033
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3424
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:962
char * ctename
Definition: parsenodes.h:1032
Query * subquery
Definition: parsenodes.h:985
List * index_tlist
Definition: ruleutils.c:166
List * inner_tlist
Definition: ruleutils.c:165
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4633
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1066
#define INDEX_VAR
Definition: primnodes.h:156
Definition: pg_list.h:45
#define GetCTETargetList(cte)
Definition: parsenodes.h:1409
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:155
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 10338 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().

10340 {
10341  HeapTuple ht_opc;
10342  Form_pg_opclass opcrec;
10343  char *opcname;
10344  char *nspname;
10345 
10346  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10347  if (!HeapTupleIsValid(ht_opc))
10348  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10349  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10350 
10351  if (!OidIsValid(actual_datatype) ||
10352  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10353  {
10354  /* Okay, we need the opclass name. Do we need to qualify it? */
10355  opcname = NameStr(opcrec->opcname);
10356  if (OpclassIsVisible(opclass))
10357  appendStringInfo(buf, " %s", quote_identifier(opcname));
10358  else
10359  {
10360  nspname = get_namespace_name(opcrec->opcnamespace);
10361  appendStringInfo(buf, " %s.%s",
10362  quote_identifier(nspname),
10363  quote_identifier(opcname));
10364  }
10365  }
10366  ReleaseSysCache(ht_opc);
10367 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1797
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
#define OidIsValid(objectId)
Definition: c.h:605
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:1812
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:81

◆ get_oper_expr()

static void get_oper_expr ( OpExpr expr,
deparse_context context 
)
static

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

8955 {
8956  StringInfo buf = context->buf;
8957  Oid opno = expr->opno;
8958  List *args = expr->args;
8959 
8960  if (!PRETTY_PAREN(context))
8961  appendStringInfoChar(buf, '(');
8962  if (list_length(args) == 2)
8963  {
8964  /* binary operator */
8965  Node *arg1 = (Node *) linitial(args);
8966  Node *arg2 = (Node *) lsecond(args);
8967 
8968  get_rule_expr_paren(arg1, context, true, (Node *) expr);
8969  appendStringInfo(buf, " %s ",
8971  exprType(arg1),
8972  exprType(arg2)));
8973  get_rule_expr_paren(arg2, context, true, (Node *) expr);
8974  }
8975  else
8976  {
8977  /* unary operator --- but which side? */
8978  Node *arg = (Node *) linitial(args);
8979  HeapTuple tp;
8980  Form_pg_operator optup;
8981 
8983  if (!HeapTupleIsValid(tp))
8984  elog(ERROR, "cache lookup failed for operator %u", opno);
8985  optup = (Form_pg_operator) GETSTRUCT(tp);
8986  switch (optup->oprkind)
8987  {
8988  case 'l':
8989  appendStringInfo(buf, "%s ",
8991  InvalidOid,
8992  exprType(arg)));
8993  get_rule_expr_paren(arg, context, true, (Node *) expr);
8994  break;
8995  case 'r':
8996  get_rule_expr_paren(arg, context, true, (Node *) expr);
8997  appendStringInfo(buf, " %s",
8999  exprType(arg),
9000  InvalidOid));
9001  break;
9002  default:
9003  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
9004  }
9005  ReleaseSysCache(tp);
9006  }
9007  if (!PRETTY_PAREN(context))
9008  appendStringInfoChar(buf, ')');
9009 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7657
Definition: nodes.h:517
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:10826
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:98
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:78
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:82
StringInfo buf
Definition: ruleutils.c:111
void * arg
Oid opno
Definition: primnodes.h:497
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:503
Definition: pg_list.h:45

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

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

7279 {
7280  Node *expr;
7281  deparse_namespace *dpns;
7282  ListCell *ancestor_cell;
7283 
7284  /*
7285  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7286  * the parameter was computed. Note that failing to find a referent isn't
7287  * an error, since the Param might well be a subplan output rather than an
7288  * input.
7289  */
7290  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7291  if (expr)
7292  {
7293  /* Found a match, so print it */
7294  deparse_namespace save_dpns;
7295  bool save_varprefix;
7296  bool need_paren;
7297 
7298  /* Switch attention to the ancestor plan node */
7299  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7300 
7301  /*
7302  * Force prefixing of Vars, since they won't belong to the relation
7303  * being scanned in the original plan node.
7304  */
7305  save_varprefix = context->varprefix;
7306  context->varprefix = true;
7307 
7308  /*
7309  * A Param's expansion is typically a Var, Aggref, or upper-level
7310  * Param, which wouldn't need extra parentheses. Otherwise, insert
7311  * parens to ensure the expression looks atomic.
7312  */
7313  need_paren = !(IsA(expr, Var) ||
7314  IsA(expr, Aggref) ||
7315  IsA(expr, Param));
7316  if (need_paren)
7317  appendStringInfoChar(context->buf, '(');
7318 
7319  get_rule_expr(expr, context, false);
7320 
7321  if (need_paren)
7322  appendStringInfoChar(context->buf, ')');
7323 
7324  context->varprefix = save_varprefix;
7325 
7326  pop_ancestor_plan(dpns, &save_dpns);
7327 
7328  return;
7329  }
7330 
7331  /*
7332  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7333  */
7334  appendStringInfo(context->buf, "$%d", param->paramid);
7335 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7158
Definition: nodes.h:517
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4656
Definition: primnodes.h:164
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:7689
int paramid
Definition: primnodes.h:246
StringInfo buf
Definition: ruleutils.c:111
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4633

◆ 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 4939 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().

4942 {
4943  deparse_context context;
4944  deparse_namespace dpns;
4945 
4946  /* Guard against excessively long or deeply-nested queries */
4949 
4950  /*
4951  * Before we begin to examine the query, acquire locks on referenced
4952  * relations, and fix up deleted columns in JOIN RTEs. This ensures
4953  * consistent results. Note we assume it's OK to scribble on the passed
4954  * querytree!
4955  *
4956  * We are only deparsing the query (we are not about to execute it), so we
4957  * only need AccessShareLock on the relations it mentions.
4958  */
4959  AcquireRewriteLocks(query, false, false);
4960 
4961  context.buf = buf;
4962  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
4963  context.windowClause = NIL;
4964  context.windowTList = NIL;
4965  context.varprefix = (parentnamespace != NIL ||
4966  list_length(query->rtable) != 1);
4967  context.prettyFlags = prettyFlags;
4968  context.wrapColumn = wrapColumn;
4969  context.indentLevel = startIndent;
4970  context.special_exprkind = EXPR_KIND_NONE;
4971 
4972  set_deparse_for_query(&dpns, query, parentnamespace);
4973 
4974  switch (query->commandType)
4975  {
4976  case CMD_SELECT:
4977  get_select_query_def(query, &context, resultDesc);
4978  break;
4979 
4980  case CMD_UPDATE:
4981  get_update_query_def(query, &context);
4982  break;
4983 
4984  case CMD_INSERT:
4985  get_insert_query_def(query, &context);
4986  break;
4987 
4988  case CMD_DELETE:
4989  get_delete_query_def(query, &context);
4990  break;
4991 
4992  case CMD_NOTHING:
4993  appendStringInfoString(buf, "NOTHING");
4994  break;
4995 
4996  case CMD_UTILITY:
4997  get_utility_query_def(query, &context);
4998  break;
4999 
5000  default:
5001  elog(ERROR, "unrecognized query command type: %d",
5002  query->commandType);
5003  break;
5004  }
5005 }
List * namespaces
Definition: ruleutils.c:112
#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:6002
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6215
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6473
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5123
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:3155
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:119
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6422
List * windowTList
Definition: ruleutils.c:114
CmdType commandType
Definition: parsenodes.h:112
List * lcons(void *datum, List *list)
Definition: list.c:259
List * windowClause
Definition: ruleutils.c:113
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:3424
StringInfo buf
Definition: ruleutils.c:111
#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 11136 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().

11137 {
11138  deparse_context context;
11140  ListCell *cell;
11141  char *sep;
11142 
11143  memset(&context, 0, sizeof(deparse_context));
11144  context.buf = buf;
11145 
11146  appendStringInfoString(buf, "(");
11147  sep = "";
11148  foreach(cell, bound_datums)
11149  {
11150  PartitionRangeDatum *datum =
11152 
11153  appendStringInfoString(buf, sep);
11154  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
11155  appendStringInfoString(buf, "MINVALUE");
11156  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
11157  appendStringInfoString(buf, "MAXVALUE");
11158  else
11159  {
11160  Const *val = castNode(Const, datum->value);
11161 
11162  get_const_expr(val, &context, -1);
11163  }
11164  sep = ", ";
11165  }
11166  appendStringInfoChar(buf, ')');
11167 
11168  return buf->data;
11169 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
PartitionRangeDatumKind kind
Definition: parsenodes.h:845
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9355
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:111
long val
Definition: informix.c:689

◆ get_relation_name()

static char * get_relation_name ( Oid  relid)
static

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

10595 {
10596  char *relname = get_rel_name(relid);
10597 
10598  if (!relname)
10599  elog(ERROR, "cache lookup failed for relation %u", relid);
10600  return relname;
10601 }
#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 4492 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().

4493 {
4495 
4496  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4497  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4498 }
List * namespaces
Definition: ruleutils.c:112
List * rtable_names
Definition: ruleutils.c:153
#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:699
static int list_length(const List *l)
Definition: pg_list.h:89

◆ get_rule_expr()