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/relation.h"
#include "access/sysattr.h"
#include "access/table.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/optimizer.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/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 int 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 keysOnly, 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 (SubscriptingRef *sbsref, 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)
 
char * pg_get_partconstrdef_string (Oid partitionId, char *aliasname)
 
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 473 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 101 of file ruleutils.c.

◆ PRETTYFLAG_INDENT

◆ PRETTYFLAG_PAREN

◆ PRETTYFLAG_SCHEMA

◆ PRETTYINDENT_JOIN

#define PRETTYINDENT_JOIN   4

Definition at line 85 of file ruleutils.c.

Referenced by get_from_clause_item().

◆ PRETTYINDENT_LIMIT

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 88 of file ruleutils.c.

Referenced by appendContextKeyword().

◆ PRETTYINDENT_STD

◆ PRETTYINDENT_VAR

#define PRETTYINDENT_VAR   4

Definition at line 86 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 11080 of file ruleutils.c.

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

Referenced by generate_operator_clause().

11081 {
11082  HeapTuple typetup;
11083  Form_pg_type typform;
11084  char *typname;
11085  char *nspname;
11086 
11087  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11088  if (!HeapTupleIsValid(typetup))
11089  elog(ERROR, "cache lookup failed for type %u", typid);
11090  typform = (Form_pg_type) GETSTRUCT(typetup);
11091 
11092  typname = NameStr(typform->typname);
11093  nspname = get_namespace_name(typform->typnamespace);
11094 
11095  appendStringInfo(buf, "::%s.%s",
11096  quote_identifier(nspname), quote_identifier(typname));
11097 
11098  ReleaseSysCache(typetup);
11099 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
NameData typname
Definition: pg_type.h:42
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ appendContextKeyword()

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

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

7727 {
7728  StringInfo buf = context->buf;
7729 
7730  if (PRETTY_INDENT(context))
7731  {
7732  int indentAmount;
7733 
7734  context->indentLevel += indentBefore;
7735 
7736  /* remove any trailing spaces currently in the buffer ... */
7738  /* ... then add a newline and some spaces */
7739  appendStringInfoChar(buf, '\n');
7740 
7741  if (context->indentLevel < PRETTYINDENT_LIMIT)
7742  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7743  else
7744  {
7745  /*
7746  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7747  * to conserve horizontal space by reducing the per-level
7748  * indentation. For best results the scale factor here should
7749  * divide all the indent amounts that get added to indentLevel
7750  * (PRETTYINDENT_STD, etc). It's important that the indentation
7751  * not grow unboundedly, else deeply-nested trees use O(N^2)
7752  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7753  */
7754  indentAmount = PRETTYINDENT_LIMIT +
7755  (context->indentLevel - PRETTYINDENT_LIMIT) /
7756  (PRETTYINDENT_STD / 2);
7757  indentAmount %= PRETTYINDENT_LIMIT;
7758  /* scale/wrap logic affects indentLevel, but not indentPlus */
7759  indentAmount += indentPlus;
7760  }
7761  appendStringInfoSpaces(buf, indentAmount);
7762 
7764 
7765  context->indentLevel += indentAfter;
7766  if (context->indentLevel < 0)
7767  context->indentLevel = 0;
7768  }
7769  else
7771 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7779
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:193
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:88
#define Max(x, y)
Definition: c.h:898
StringInfo buf
Definition: ruleutils.c:112

◆ colname_is_unique()

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

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

4320 {
4321  int i;
4322  ListCell *lc;
4323 
4324  /* Check against already-assigned column aliases within RTE */
4325  for (i = 0; i < colinfo->num_cols; i++)
4326  {
4327  char *oldname = colinfo->colnames[i];
4328 
4329  if (oldname && strcmp(oldname, colname) == 0)
4330  return false;
4331  }
4332 
4333  /*
4334  * If we're building a new_colnames array, check that too (this will be
4335  * partially but not completely redundant with the previous checks)
4336  */
4337  for (i = 0; i < colinfo->num_new_cols; i++)
4338  {
4339  char *oldname = colinfo->new_colnames[i];
4340 
4341  if (oldname && strcmp(oldname, colname) == 0)
4342  return false;
4343  }
4344 
4345  /* Also check against USING-column names that must be globally unique */
4346  foreach(lc, dpns->using_names)
4347  {
4348  char *oldname = (char *) lfirst(lc);
4349 
4350  if (strcmp(oldname, colname) == 0)
4351  return false;
4352  }
4353 
4354  /* Also check against names already assigned for parent-join USING cols */
4355  foreach(lc, colinfo->parentUsing)
4356  {
4357  char *oldname = (char *) lfirst(lc);
4358 
4359  if (strcmp(oldname, colname) == 0)
4360  return false;
4361  }
4362 
4363  return true;
4364 }
List * using_names
Definition: ruleutils.c:159
#define lfirst(lc)
Definition: pg_list.h:190
int i
List * parentUsing
Definition: ruleutils.c:253
char ** new_colnames
Definition: ruleutils.c:246
char ** colnames
Definition: ruleutils.c:229

◆ decompile_column_index_array()

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

Definition at line 2316 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2318 {
2319  Datum *keys;
2320  int nKeys;
2321  int j;
2322 
2323  /* Extract data from array of int16 */
2324  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2325  INT2OID, 2, true, 's',
2326  &keys, NULL, &nKeys);
2327 
2328  for (j = 0; j < nKeys; j++)
2329  {
2330  char *colName;
2331 
2332  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2333 
2334  if (j == 0)
2336  else
2337  appendStringInfo(buf, ", %s", quote_identifier(colName));
2338  }
2339 
2340  return nKeys;
2341 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
#define DatumGetInt16(X)
Definition: postgres.h:444
uintptr_t Datum
Definition: postgres.h:367
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ deparse_context_for()

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

Definition at line 3258 of file ruleutils.c.

References AccessShareLock, RangeTblEntry::alias, deparse_namespace::ctes, RangeTblEntry::eref, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, list_make1, makeAlias(), makeNode, NIL, palloc0(), RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, 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_partconstrdef_string(), pg_get_partition_constraintdef(), pg_get_partkeydef_worker(), transformPartitionBound(), and transformPartitionRangeBounds().

3259 {
3260  deparse_namespace *dpns;
3261  RangeTblEntry *rte;
3262 
3263  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3264 
3265  /* Build a minimal RTE for the rel */
3266  rte = makeNode(RangeTblEntry);
3267  rte->rtekind = RTE_RELATION;
3268  rte->relid = relid;
3269  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3271  rte->alias = makeAlias(aliasname, NIL);
3272  rte->eref = rte->alias;
3273  rte->lateral = false;
3274  rte->inh = false;
3275  rte->inFromCl = true;
3276 
3277  /* Build one-element rtable */
3278  dpns->rtable = list_make1(rte);
3279  dpns->ctes = NIL;
3280  set_rtable_names(dpns, NIL, NULL);
3282 
3283  /* Return a one-deep namespace stack */
3284  return list_make1(dpns);
3285 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1091
#define AccessShareLock
Definition: lockdefs.h:36
#define list_make1(x1)
Definition: pg_list.h:227
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:385
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3403
void * palloc0(Size size)
Definition: mcxt.c:955
#define makeNode(_type_)
Definition: nodes.h:572
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3616
RTEKind rtekind
Definition: parsenodes.h:974
Alias * eref
Definition: parsenodes.h:1092

◆ deparse_context_for_plan_rtable()

List* deparse_context_for_plan_rtable ( List rtable,
List rtable_names 
)

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

3302 {
3303  deparse_namespace *dpns;
3304 
3305  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3306 
3307  /* Initialize fields that stay the same across the whole plan tree */
3308  dpns->rtable = rtable;
3309  dpns->rtable_names = rtable_names;
3310  dpns->ctes = NIL;
3311 
3312  /*
3313  * Set up column name aliases. We will get rather bogus results for join
3314  * RTEs, but that doesn't matter because plan trees don't contain any join
3315  * alias Vars.
3316  */
3318 
3319  /* Return a one-deep namespace stack */
3320  return list_make1(dpns);
3321 }
#define NIL
Definition: pg_list.h:65
List * rtable_names
Definition: ruleutils.c:154
#define list_make1(x1)
Definition: pg_list.h:227
void * palloc0(Size size)
Definition: mcxt.c:955
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3616

◆ deparse_expression()

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

Definition at line 3199 of file ruleutils.c.

References deparse_expression_pretty().

Referenced by AlterDomainDefault(), DefineDomain(), pg_get_function_arg_default(), pg_get_partconstrdef_string(), print_function_arguments(), show_expression(), show_grouping_set_keys(), show_plan_tlist(), show_sort_group_keys(), show_tablesample(), transformPartitionBound(), and transformPartitionRangeBounds().

3201 {
3202  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3203  showimplicit, 0, 0);
3204 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3226

◆ deparse_expression_pretty()

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

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

3229 {
3231  deparse_context context;
3232 
3233  initStringInfo(&buf);
3234  context.buf = &buf;
3235  context.namespaces = dpcontext;
3236  context.windowClause = NIL;
3237  context.windowTList = NIL;
3238  context.varprefix = forceprefix;
3239  context.prettyFlags = prettyFlags;
3240  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3241  context.indentLevel = startIndent;
3242  context.special_exprkind = EXPR_KIND_NONE;
3243 
3244  get_rule_expr(expr, &context, showimplicit);
3245 
3246  return buf.data;
3247 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:96
static char * buf
Definition: pg_test_fsync.c:68
ParseExprKind special_exprkind
Definition: ruleutils.c:120
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
List * windowTList
Definition: ruleutils.c:115
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
List * windowClause
Definition: ruleutils.c:114
StringInfo buf
Definition: ruleutils.c:112

◆ expand_colnames_array_to()

static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

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

4417 {
4418  if (n > colinfo->num_cols)
4419  {
4420  if (colinfo->colnames == NULL)
4421  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4422  else
4423  {
4424  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4425  n * sizeof(char *));
4426  memset(colinfo->colnames + colinfo->num_cols, 0,
4427  (n - colinfo->num_cols) * sizeof(char *));
4428  }
4429  colinfo->num_cols = n;
4430  }
4431 }
void * palloc0(Size size)
Definition: mcxt.c:955
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
char ** colnames
Definition: ruleutils.c:229

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

7301 {
7302  /* Initialize output parameters to prevent compiler warnings */
7303  *dpns_p = NULL;
7304  *ancestor_cell_p = NULL;
7305 
7306  /*
7307  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7308  * SubPlan argument. This will necessarily be in some ancestor of the
7309  * current expression's PlanState.
7310  */
7311  if (param->paramkind == PARAM_EXEC)
7312  {
7313  deparse_namespace *dpns;
7314  PlanState *child_ps;
7315  bool in_same_plan_level;
7316  ListCell *lc;
7317 
7318  dpns = (deparse_namespace *) linitial(context->namespaces);
7319  child_ps = dpns->planstate;
7320  in_same_plan_level = true;
7321 
7322  foreach(lc, dpns->ancestors)
7323  {
7324  PlanState *ps = (PlanState *) lfirst(lc);
7325  ListCell *lc2;
7326 
7327  /*
7328  * NestLoops transmit params to their inner child only; also, once
7329  * we've crawled up out of a subplan, this couldn't possibly be
7330  * the right match.
7331  */
7332  if (IsA(ps, NestLoopState) &&
7333  child_ps == innerPlanState(ps) &&
7334  in_same_plan_level)
7335  {
7336  NestLoop *nl = (NestLoop *) ps->plan;
7337 
7338  foreach(lc2, nl->nestParams)
7339  {
7340  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7341 
7342  if (nlp->paramno == param->paramid)
7343  {
7344  /* Found a match, so return it */
7345  *dpns_p = dpns;
7346  *ancestor_cell_p = lc;
7347  return (Node *) nlp->paramval;
7348  }
7349  }
7350  }
7351 
7352  /*
7353  * Check to see if we're crawling up from a subplan.
7354  */
7355  foreach(lc2, ps->subPlan)
7356  {
7357  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7358  SubPlan *subplan = sstate->subplan;
7359  ListCell *lc3;
7360  ListCell *lc4;
7361 
7362  if (child_ps != sstate->planstate)
7363  continue;
7364 
7365  /* Matched subplan, so check its arguments */
7366  forboth(lc3, subplan->parParam, lc4, subplan->args)
7367  {
7368  int paramid = lfirst_int(lc3);
7369  Node *arg = (Node *) lfirst(lc4);
7370 
7371  if (paramid == param->paramid)
7372  {
7373  /* Found a match, so return it */
7374  *dpns_p = dpns;
7375  *ancestor_cell_p = lc;
7376  return arg;
7377  }
7378  }
7379 
7380  /* Keep looking, but we are emerging from a subplan. */
7381  in_same_plan_level = false;
7382  break;
7383  }
7384 
7385  /*
7386  * Likewise check to see if we're emerging from an initplan.
7387  * Initplans never have any parParams, so no need to search that
7388  * list, but we need to know if we should reset
7389  * in_same_plan_level.
7390  */
7391  foreach(lc2, ps->initPlan)
7392  {
7393  SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
7394 
7395  if (child_ps != sstate->planstate)
7396  continue;
7397 
7398  /* No parameters to be had here. */
7399  Assert(sstate->subplan->parParam == NIL);
7400 
7401  /* Keep looking, but we are emerging from an initplan. */
7402  in_same_plan_level = false;
7403  break;
7404  }
7405 
7406  /* No luck, crawl up to next ancestor */
7407  child_ps = ps;
7408  }
7409  }
7410 
7411  /* No referent found */
7412  return NULL;
7413 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
List * nestParams
Definition: plannodes.h:699
List * initPlan
Definition: execnodes.h:970
List * subPlan
Definition: execnodes.h:972
ParamKind paramkind
Definition: primnodes.h:248
Definition: nodes.h:524
Var * paramval
Definition: plannodes.h:706
#define linitial(l)
Definition: pg_list.h:195
struct PlanState * planstate
Definition: execnodes.h:853
SubPlan * subplan
Definition: execnodes.h:852
#define lfirst_int(lc)
Definition: pg_list.h:191
Plan * plan
Definition: execnodes.h:945
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
int paramid
Definition: primnodes.h:249
List * parParam
Definition: primnodes.h:715
PlanState * planstate
Definition: ruleutils.c:161
void * arg
#define innerPlanState(node)
Definition: execnodes.h:1038
List * args
Definition: primnodes.h:716

◆ flatten_join_using_qual()

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

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

4568 {
4569  if (IsA(qual, BoolExpr))
4570  {
4571  /* Handle AND nodes by recursion */
4572  BoolExpr *b = (BoolExpr *) qual;
4573  ListCell *lc;
4574 
4575  Assert(b->boolop == AND_EXPR);
4576  foreach(lc, b->args)
4577  {
4579  leftvars, rightvars);
4580  }
4581  }
4582  else if (IsA(qual, OpExpr))
4583  {
4584  /* Otherwise we should have an equality operator */
4585  OpExpr *op = (OpExpr *) qual;
4586  Var *var;
4587 
4588  if (list_length(op->args) != 2)
4589  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4590  /* Arguments should be Vars with perhaps implicit coercions */
4591  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4592  if (!IsA(var, Var))
4593  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4594  (int) nodeTag(var));
4595  *leftvars = lappend(*leftvars, var);
4596  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4597  if (!IsA(var, Var))
4598  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4599  (int) nodeTag(var));
4600  *rightvars = lappend(*rightvars, var);
4601  }
4602  else
4603  {
4604  /* Perhaps we have an implicit coercion to boolean? */
4605  Node *q = strip_implicit_coercions(qual);
4606 
4607  if (q != qual)
4608  flatten_join_using_qual(q, leftvars, rightvars);
4609  else
4610  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4611  (int) nodeTag(qual));
4612  }
4613 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
Definition: nodes.h:524
Definition: primnodes.h:167
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:568
List * lappend(List *list, void *datum)
Definition: list.c:321
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:4567
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
List * args
Definition: primnodes.h:569
#define nodeTag(nodeptr)
Definition: nodes.h:529
#define elog(elevel,...)
Definition: elog.h:226
List * args
Definition: primnodes.h:508
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

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

11190 {
11191  char *result = NULL;
11192  HeapTuple tuple;
11193  Datum reloptions;
11194  bool isnull;
11195 
11196  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11197  if (!HeapTupleIsValid(tuple))
11198  elog(ERROR, "cache lookup failed for relation %u", relid);
11199 
11200  reloptions = SysCacheGetAttr(RELOID, tuple,
11201  Anum_pg_class_reloptions, &isnull);
11202  if (!isnull)
11203  {
11205  Datum *options;
11206  int noptions;
11207  int i;
11208 
11209  initStringInfo(&buf);
11210 
11212  TEXTOID, -1, false, 'i',
11213  &options, NULL, &noptions);
11214 
11215  for (i = 0; i < noptions; i++)
11216  {
11217  char *option = TextDatumGetCString(options[i]);
11218  char *name;
11219  char *separator;
11220  char *value;
11221 
11222  /*
11223  * Each array element should have the form name=value. If the "="
11224  * is missing for some reason, treat it like an empty value.
11225  */
11226  name = option;
11227  separator = strchr(option, '=');
11228  if (separator)
11229  {
11230  *separator = '\0';
11231  value = separator + 1;
11232  }
11233  else
11234  value = "";
11235 
11236  if (i > 0)
11237  appendStringInfoString(&buf, ", ");
11238  appendStringInfo(&buf, "%s=", quote_identifier(name));
11239 
11240  /*
11241  * In general we need to quote the value; but to avoid unnecessary
11242  * clutter, do not quote if it is an identifier that would not
11243  * need quoting. (We could also allow numbers, but that is a bit
11244  * trickier than it looks --- for example, are leading zeroes
11245  * significant? We don't want to assume very much here about what
11246  * custom reloptions might mean.)
11247  */
11248  if (quote_identifier(value) == value)
11249  appendStringInfoString(&buf, value);
11250  else
11251  simple_quote_literal(&buf, value);
11252 
11253  pfree(option);
11254  }
11255 
11256  result = buf.data;
11257  }
11258 
11259  ReleaseSysCache(tuple);
11260 
11261  return result;
11262 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
static struct @144 value
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:507
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9656
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
#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:3461
#define elog(elevel,...)
Definition: elog.h:226
int i
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

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

11145 {
11146  HeapTuple tp;
11147  Form_pg_collation colltup;
11148  char *collname;
11149  char *nspname;
11150  char *result;
11151 
11152  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11153  if (!HeapTupleIsValid(tp))
11154  elog(ERROR, "cache lookup failed for collation %u", collid);
11155  colltup = (Form_pg_collation) GETSTRUCT(tp);
11156  collname = NameStr(colltup->collname);
11157 
11158  if (!CollationIsVisible(collid))
11159  nspname = get_namespace_name(colltup->collnamespace);
11160  else
11161  nspname = NULL;
11162 
11163  result = quote_qualified_identifier(nspname, collname);
11164 
11165  ReleaseSysCache(tp);
11166 
11167  return result;
11168 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2040
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10712
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ 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 10854 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, proname, quote_qualified_identifier(), ReleaseSysCache(), and SearchSysCache1().

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

10857 {
10858  char *result;
10859  HeapTuple proctup;
10860  Form_pg_proc procform;
10861  char *proname;
10862  bool use_variadic;
10863  char *nspname;
10864  FuncDetailCode p_result;
10865  Oid p_funcid;
10866  Oid p_rettype;
10867  bool p_retset;
10868  int p_nvargs;
10869  Oid p_vatype;
10870  Oid *p_true_typeids;
10871  bool force_qualify = false;
10872 
10873  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10874  if (!HeapTupleIsValid(proctup))
10875  elog(ERROR, "cache lookup failed for function %u", funcid);
10876  procform = (Form_pg_proc) GETSTRUCT(proctup);
10877  proname = NameStr(procform->proname);
10878 
10879  /*
10880  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10881  * qualification in some special cases.
10882  */
10883  if (special_exprkind == EXPR_KIND_GROUP_BY)
10884  {
10885  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10886  force_qualify = true;
10887  }
10888 
10889  /*
10890  * Determine whether VARIADIC should be printed. We must do this first
10891  * since it affects the lookup rules in func_get_detail().
10892  *
10893  * We always print VARIADIC if the function has a merged variadic-array
10894  * argument. Note that this is always the case for functions taking a
10895  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
10896  * and printed the array elements as separate arguments, the call could
10897  * match a newer non-VARIADIC function.
10898  */
10899  if (use_variadic_p)
10900  {
10901  /* Parser should not have set funcvariadic unless fn is variadic */
10902  Assert(!has_variadic || OidIsValid(procform->provariadic));
10903  use_variadic = has_variadic;
10904  *use_variadic_p = use_variadic;
10905  }
10906  else
10907  {
10908  Assert(!has_variadic);
10909  use_variadic = false;
10910  }
10911 
10912  /*
10913  * The idea here is to schema-qualify only if the parser would fail to
10914  * resolve the correct function given the unqualified func name with the
10915  * specified argtypes and VARIADIC flag. But if we already decided to
10916  * force qualification, then we can skip the lookup and pretend we didn't
10917  * find it.
10918  */
10919  if (!force_qualify)
10920  p_result = func_get_detail(list_make1(makeString(proname)),
10921  NIL, argnames, nargs, argtypes,
10922  !use_variadic, true,
10923  &p_funcid, &p_rettype,
10924  &p_retset, &p_nvargs, &p_vatype,
10925  &p_true_typeids, NULL);
10926  else
10927  {
10928  p_result = FUNCDETAIL_NOTFOUND;
10929  p_funcid = InvalidOid;
10930  }
10931 
10932  if ((p_result == FUNCDETAIL_NORMAL ||
10933  p_result == FUNCDETAIL_AGGREGATE ||
10934  p_result == FUNCDETAIL_WINDOWFUNC) &&
10935  p_funcid == funcid)
10936  nspname = NULL;
10937  else
10938  nspname = get_namespace_name(procform->pronamespace);
10939 
10940  result = quote_qualified_identifier(nspname, proname);
10941 
10942  ReleaseSysCache(proctup);
10943 
10944  return result;
10945 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:36
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define list_make1(x1)
Definition: pg_list.h:227
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10712
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
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:1382
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ generate_operator_clause()

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

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

11044 {
11045  HeapTuple opertup;
11046  Form_pg_operator operform;
11047  char *oprname;
11048  char *nspname;
11049 
11050  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11051  if (!HeapTupleIsValid(opertup))
11052  elog(ERROR, "cache lookup failed for operator %u", opoid);
11053  operform = (Form_pg_operator) GETSTRUCT(opertup);
11054  Assert(operform->oprkind == 'b');
11055  oprname = NameStr(operform->oprname);
11056 
11057  nspname = get_namespace_name(operform->oprnamespace);
11058 
11059  appendStringInfoString(buf, leftop);
11060  if (leftoptype != operform->oprleft)
11061  add_cast_to(buf, operform->oprleft);
11062  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11063  appendStringInfoString(buf, oprname);
11064  appendStringInfo(buf, ") %s", rightop);
11065  if (rightoptype != operform->oprright)
11066  add_cast_to(buf, operform->oprright);
11067 
11068  ReleaseSysCache(opertup);
11069 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11080
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:84
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ generate_operator_name()

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

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

10960 {
10962  HeapTuple opertup;
10963  Form_pg_operator operform;
10964  char *oprname;
10965  char *nspname;
10966  Operator p_result;
10967 
10968  initStringInfo(&buf);
10969 
10970  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
10971  if (!HeapTupleIsValid(opertup))
10972  elog(ERROR, "cache lookup failed for operator %u", operid);
10973  operform = (Form_pg_operator) GETSTRUCT(opertup);
10974  oprname = NameStr(operform->oprname);
10975 
10976  /*
10977  * The idea here is to schema-qualify only if the parser would fail to
10978  * resolve the correct operator given the unqualified op name with the
10979  * specified argtypes.
10980  */
10981  switch (operform->oprkind)
10982  {
10983  case 'b':
10984  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
10985  true, -1);
10986  break;
10987  case 'l':
10988  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
10989  true, -1);
10990  break;
10991  case 'r':
10992  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
10993  true, -1);
10994  break;
10995  default:
10996  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
10997  p_result = NULL; /* keep compiler quiet */
10998  break;
10999  }
11000 
11001  if (p_result != NULL && oprid(p_result) == operid)
11002  nspname = NULL;
11003  else
11004  {
11005  nspname = get_namespace_name(operform->oprnamespace);
11006  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11007  }
11008 
11009  appendStringInfoString(&buf, oprname);
11010 
11011  if (nspname)
11012  appendStringInfoChar(&buf, ')');
11013 
11014  if (p_result != NULL)
11015  ReleaseSysCache(p_result);
11016 
11017  ReleaseSysCache(opertup);
11018 
11019  return buf.data;
11020 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define list_make1(x1)
Definition: pg_list.h:227
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:163
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:84
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
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 10812 of file ruleutils.c.

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

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

10813 {
10814  HeapTuple tp;
10815  Form_pg_class reltup;
10816  char *relname;
10817  char *nspname;
10818  char *result;
10819 
10820  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10821  if (!HeapTupleIsValid(tp))
10822  elog(ERROR, "cache lookup failed for relation %u", relid);
10823  reltup = (Form_pg_class) GETSTRUCT(tp);
10824  relname = NameStr(reltup->relname);
10825 
10826  nspname = get_namespace_name(reltup->relnamespace);
10827  if (!nspname)
10828  elog(ERROR, "cache lookup failed for namespace %u",
10829  reltup->relnamespace);
10830 
10831  result = quote_qualified_identifier(nspname, relname);
10832 
10833  ReleaseSysCache(tp);
10834 
10835  return result;
10836 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10712
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

Definition at line 11111 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

11112 {
11113  HeapTuple tp;
11114  Form_pg_type typtup;
11115  char *typname;
11116  char *nspname;
11117  char *result;
11118 
11120  if (!HeapTupleIsValid(tp))
11121  elog(ERROR, "cache lookup failed for type %u", typid);
11122  typtup = (Form_pg_type) GETSTRUCT(tp);
11123  typname = NameStr(typtup->typname);
11124 
11125  nspname = get_namespace_name(typtup->typnamespace);
11126  if (!nspname)
11127  elog(ERROR, "cache lookup failed for namespace %u",
11128  typtup->typnamespace);
11129 
11130  result = quote_qualified_identifier(nspname, typname);
11131 
11132  ReleaseSysCache(tp);
11133 
11134  return result;
11135 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
NameData typname
Definition: pg_type.h:42
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10712
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ generate_relation_name()

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

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

10753 {
10754  HeapTuple tp;
10755  Form_pg_class reltup;
10756  bool need_qual;
10757  ListCell *nslist;
10758  char *relname;
10759  char *nspname;
10760  char *result;
10761 
10762  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10763  if (!HeapTupleIsValid(tp))
10764  elog(ERROR, "cache lookup failed for relation %u", relid);
10765  reltup = (Form_pg_class) GETSTRUCT(tp);
10766  relname = NameStr(reltup->relname);
10767 
10768  /* Check for conflicting CTE name */
10769  need_qual = false;
10770  foreach(nslist, namespaces)
10771  {
10772  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10773  ListCell *ctlist;
10774 
10775  foreach(ctlist, dpns->ctes)
10776  {
10777  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10778 
10779  if (strcmp(cte->ctename, relname) == 0)
10780  {
10781  need_qual = true;
10782  break;
10783  }
10784  }
10785  if (need_qual)
10786  break;
10787  }
10788 
10789  /* Otherwise, qualify the name if not visible in search path */
10790  if (!need_qual)
10791  need_qual = !RelationIsVisible(relid);
10792 
10793  if (need_qual)
10794  nspname = get_namespace_name(reltup->relnamespace);
10795  else
10796  nspname = NULL;
10797 
10798  result = quote_qualified_identifier(nspname, relname);
10799 
10800  ReleaseSysCache(tp);
10801 
10802  return result;
10803 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10712
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:190
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
bool RelationIsVisible(Oid relid)
Definition: namespace.c:700
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609

◆ get_agg_combine_expr()

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

Definition at line 9349 of file ruleutils.c.

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

Referenced by get_agg_expr().

9350 {
9351  Aggref *aggref;
9352  Aggref *original_aggref = private;
9353 
9354  if (!IsA(node, Aggref))
9355  elog(ERROR, "combining Aggref does not point to an Aggref");
9356 
9357  aggref = (Aggref *) node;
9358  get_agg_expr(aggref, context, original_aggref);
9359 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9243
#define elog(elevel,...)
Definition: elog.h:226

◆ get_agg_expr()

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

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

9245 {
9246  StringInfo buf = context->buf;
9247  Oid argtypes[FUNC_MAX_ARGS];
9248  int nargs;
9249  bool use_variadic;
9250 
9251  /*
9252  * For a combining aggregate, we look up and deparse the corresponding
9253  * partial aggregate instead. This is necessary because our input
9254  * argument list has been replaced; the new argument list always has just
9255  * one element, which will point to a partial Aggref that supplies us with
9256  * transition states to combine.
9257  */
9258  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9259  {
9260  TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
9261 
9262  Assert(list_length(aggref->args) == 1);
9263  resolve_special_varno((Node *) tle->expr, context, original_aggref,
9265  return;
9266  }
9267 
9268  /*
9269  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9270  * to avoid printing this when recursing from the code just above.
9271  */
9272  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9273  appendStringInfoString(buf, "PARTIAL ");
9274 
9275  /* Extract the argument types as seen by the parser */
9276  nargs = get_aggregate_argtypes(aggref, argtypes);
9277 
9278  /* Print the aggregate name, schema-qualified if needed */
9279  appendStringInfo(buf, "%s(%s",
9280  generate_function_name(aggref->aggfnoid, nargs,
9281  NIL, argtypes,
9282  aggref->aggvariadic,
9283  &use_variadic,
9284  context->special_exprkind),
9285  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9286 
9287  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9288  {
9289  /*
9290  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9291  * worry about inserting VARIADIC. So we can just dump the direct
9292  * args as-is.
9293  */
9294  Assert(!aggref->aggvariadic);
9295  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9296  Assert(aggref->aggorder != NIL);
9297  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9298  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9299  }
9300  else
9301  {
9302  /* aggstar can be set only in zero-argument aggregates */
9303  if (aggref->aggstar)
9304  appendStringInfoChar(buf, '*');
9305  else
9306  {
9307  ListCell *l;
9308  int i;
9309 
9310  i = 0;
9311  foreach(l, aggref->args)
9312  {
9313  TargetEntry *tle = (TargetEntry *) lfirst(l);
9314  Node *arg = (Node *) tle->expr;
9315 
9316  Assert(!IsA(arg, NamedArgExpr));
9317  if (tle->resjunk)
9318  continue;
9319  if (i++ > 0)
9320  appendStringInfoString(buf, ", ");
9321  if (use_variadic && i == nargs)
9322  appendStringInfoString(buf, "VARIADIC ");
9323  get_rule_expr(arg, context, true);
9324  }
9325  }
9326 
9327  if (aggref->aggorder != NIL)
9328  {
9329  appendStringInfoString(buf, " ORDER BY ");
9330  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9331  }
9332  }
9333 
9334  if (aggref->aggfilter != NULL)
9335  {
9336  appendStringInfoString(buf, ") FILTER (WHERE ");
9337  get_rule_expr((Node *) aggref->aggfilter, context, false);
9338  }
9339 
9340  appendStringInfoChar(buf, ')');
9341 }
List * aggdistinct
Definition: primnodes.h:307
#define NIL
Definition: pg_list.h:65
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:10854
bool aggvariadic
Definition: primnodes.h:310
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
static void resolve_special_varno(Node *node, deparse_context *context, void *private, void(*callback)(Node *, deparse_context *, void *))
Definition: ruleutils.c:6841
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5942
Definition: nodes.h:524
List * args
Definition: primnodes.h:305
bool aggstar
Definition: primnodes.h:309
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:198
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:786
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1400
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
List * aggorder
Definition: primnodes.h:306
List * aggdirectargs
Definition: primnodes.h:304
ParseExprKind special_exprkind
Definition: ruleutils.c:120
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
Oid aggfnoid
Definition: primnodes.h:298
static void get_agg_combine_expr(Node *node, deparse_context *context, void *private)
Definition: ruleutils.c:9349
#define Assert(condition)
Definition: c.h:732
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
AggSplit aggsplit
Definition: primnodes.h:314
static int list_length(const List *l)
Definition: pg_list.h:169
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:787
Expr * aggfilter
Definition: primnodes.h:308
StringInfo buf
Definition: ruleutils.c:112
int i
void * arg
char aggkind
Definition: primnodes.h:312
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1819

◆ get_basic_select_query()

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

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

5437 {
5438  StringInfo buf = context->buf;
5439  RangeTblEntry *values_rte;
5440  char *sep;
5441  ListCell *l;
5442 
5443  if (PRETTY_INDENT(context))
5444  {
5445  context->indentLevel += PRETTYINDENT_STD;
5446  appendStringInfoChar(buf, ' ');
5447  }
5448 
5449  /*
5450  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5451  * VALUES part. This reverses what transformValuesClause() did at parse
5452  * time.
5453  */
5454  values_rte = get_simple_values_rte(query);
5455  if (values_rte)
5456  {
5457  get_values_def(values_rte->values_lists, context);
5458  return;
5459  }
5460 
5461  /*
5462  * Build up the query string - first we say SELECT
5463  */
5464  appendStringInfoString(buf, "SELECT");
5465 
5466  /* Add the DISTINCT clause if given */
5467  if (query->distinctClause != NIL)
5468  {
5469  if (query->hasDistinctOn)
5470  {
5471  appendStringInfoString(buf, " DISTINCT ON (");
5472  sep = "";
5473  foreach(l, query->distinctClause)
5474  {
5475  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5476 
5477  appendStringInfoString(buf, sep);
5479  false, context);
5480  sep = ", ";
5481  }
5482  appendStringInfoChar(buf, ')');
5483  }
5484  else
5485  appendStringInfoString(buf, " DISTINCT");
5486  }
5487 
5488  /* Then we tell what to select (the targetlist) */
5489  get_target_list(query->targetList, context, resultDesc);
5490 
5491  /* Add the FROM clause if needed */
5492  get_from_clause(query, " FROM ", context);
5493 
5494  /* Add the WHERE clause if given */
5495  if (query->jointree->quals != NULL)
5496  {
5497  appendContextKeyword(context, " WHERE ",
5499  get_rule_expr(query->jointree->quals, context, false);
5500  }
5501 
5502  /* Add the GROUP BY clause if given */
5503  if (query->groupClause != NULL || query->groupingSets != NULL)
5504  {
5505  ParseExprKind save_exprkind;
5506 
5507  appendContextKeyword(context, " GROUP BY ",
5509 
5510  save_exprkind = context->special_exprkind;
5512 
5513  if (query->groupingSets == NIL)
5514  {
5515  sep = "";
5516  foreach(l, query->groupClause)
5517  {
5518  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5519 
5520  appendStringInfoString(buf, sep);
5522  false, context);
5523  sep = ", ";
5524  }
5525  }
5526  else
5527  {
5528  sep = "";
5529  foreach(l, query->groupingSets)
5530  {
5531  GroupingSet *grp = lfirst(l);
5532 
5533  appendStringInfoString(buf, sep);
5534  get_rule_groupingset(grp, query->targetList, true, context);
5535  sep = ", ";
5536  }
5537  }
5538 
5539  context->special_exprkind = save_exprkind;
5540  }
5541 
5542  /* Add the HAVING clause if given */
5543  if (query->havingQual != NULL)
5544  {
5545  appendContextKeyword(context, " HAVING ",
5547  get_rule_expr(query->havingQual, context, false);
5548  }
5549 
5550  /* Add the WINDOW clause if needed */
5551  if (query->windowClause != NIL)
5552  get_rule_windowclause(query, context);
5553 }
#define NIL
Definition: pg_list.h:65
FromExpr * jointree
Definition: parsenodes.h:138
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5562
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5826
Index tleSortGroupRef
Definition: parsenodes.h:1234
List * groupingSets
Definition: parsenodes.h:150
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9913
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:6000
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:1051
Node * quals
Definition: primnodes.h:1497
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:163
static char * buf
Definition: pg_test_fsync.c:68
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7725
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5882
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
ParseExprKind special_exprkind
Definition: ruleutils.c:120
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
#define lfirst(lc)
Definition: pg_list.h:190
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5139
List * groupClause
Definition: parsenodes.h:148
StringInfo buf
Definition: ruleutils.c:112
static RangeTblEntry * get_simple_values_rte(Query *query)
Definition: ruleutils.c:5379
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 9442 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().

9445 {
9446  StringInfo buf = context->buf;
9447 
9448  /*
9449  * Since parse_coerce.c doesn't immediately collapse application of
9450  * length-coercion functions to constants, what we'll typically see in
9451  * such cases is a Const with typmod -1 and a length-coercion function
9452  * right above it. Avoid generating redundant output. However, beware of
9453  * suppressing casts when the user actually wrote something like
9454  * 'foo'::text::char(3).
9455  *
9456  * Note: it might seem that we are missing the possibility of needing to
9457  * print a COLLATE clause for such a Const. However, a Const could only
9458  * have nondefault collation in a post-constant-folding tree, in which the
9459  * length coercion would have been folded too. See also the special
9460  * handling of CollateExpr in coerce_to_target_type(): any collation
9461  * marking will be above the coercion node, not below it.
9462  */
9463  if (arg && IsA(arg, Const) &&
9464  ((Const *) arg)->consttype == resulttype &&
9465  ((Const *) arg)->consttypmod == -1)
9466  {
9467  /* Show the constant without normal ::typename decoration */
9468  get_const_expr((Const *) arg, context, -1);
9469  }
9470  else
9471  {
9472  if (!PRETTY_PAREN(context))
9473  appendStringInfoChar(buf, '(');
9474  get_rule_expr_paren(arg, context, false, parentNode);
9475  if (!PRETTY_PAREN(context))
9476  appendStringInfoChar(buf, ')');
9477  }
9478 
9479  /*
9480  * Never emit resulttype(arg) functional notation. A pg_proc entry could
9481  * take precedence, and a resulttype in pg_temp would require schema
9482  * qualification that format_type_with_typemod() would usually omit. We've
9483  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
9484  * would work fine.
9485  */
9486  appendStringInfo(buf, "::%s",
9487  format_type_with_typemod(resulttype, resulttypmod));
9488 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7798
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9506
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:99
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:345
StringInfo buf
Definition: ruleutils.c:112

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

10343 {
10344  StringInfo buf = context->buf;
10345  int i;
10346  bool first = true;
10347 
10348  /* Don't print aliases if not needed */
10349  if (!colinfo->printaliases)
10350  return;
10351 
10352  for (i = 0; i < colinfo->num_new_cols; i++)
10353  {
10354  char *colname = colinfo->new_colnames[i];
10355 
10356  if (first)
10357  {
10358  appendStringInfoChar(buf, '(');
10359  first = false;
10360  }
10361  else
10362  appendStringInfoString(buf, ", ");
10364  }
10365  if (!first)
10366  appendStringInfoChar(buf, ')');
10367 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
StringInfo buf
Definition: ruleutils.c:112
int i
char ** new_colnames
Definition: ruleutils.c:246

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9637 {
9638  StringInfo buf = context->buf;
9639 
9640  if (OidIsValid(constval->constcollid))
9641  {
9642  Oid typcollation = get_typcollation(constval->consttype);
9643 
9644  if (constval->constcollid != typcollation)
9645  {
9646  appendStringInfo(buf, " COLLATE %s",
9648  }
9649  }
9650 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11144
Oid consttype
Definition: primnodes.h:196
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
Oid constcollid
Definition: primnodes.h:198
static char * buf
Definition: pg_test_fsync.c:68
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2823
StringInfo buf
Definition: ruleutils.c:112

◆ get_const_expr()

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

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

9507 {
9508  StringInfo buf = context->buf;
9509  Oid typoutput;
9510  bool typIsVarlena;
9511  char *extval;
9512  bool needlabel = false;
9513 
9514  if (constval->constisnull)
9515  {
9516  /*
9517  * Always label the type of a NULL constant to prevent misdecisions
9518  * about type when reparsing.
9519  */
9520  appendStringInfoString(buf, "NULL");
9521  if (showtype >= 0)
9522  {
9523  appendStringInfo(buf, "::%s",
9525  constval->consttypmod));
9526  get_const_collation(constval, context);
9527  }
9528  return;
9529  }
9530 
9531  getTypeOutputInfo(constval->consttype,
9532  &typoutput, &typIsVarlena);
9533 
9534  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9535 
9536  switch (constval->consttype)
9537  {
9538  case INT4OID:
9539 
9540  /*
9541  * INT4 can be printed without any decoration, unless it is
9542  * negative; in that case print it as '-nnn'::integer to ensure
9543  * that the output will re-parse as a constant, not as a constant
9544  * plus operator. In most cases we could get away with printing
9545  * (-nnn) instead, because of the way that gram.y handles negative
9546  * literals; but that doesn't work for INT_MIN, and it doesn't
9547  * seem that much prettier anyway.
9548  */
9549  if (extval[0] != '-')
9550  appendStringInfoString(buf, extval);
9551  else
9552  {
9553  appendStringInfo(buf, "'%s'", extval);
9554  needlabel = true; /* we must attach a cast */
9555  }
9556  break;
9557 
9558  case NUMERICOID:
9559 
9560  /*
9561  * NUMERIC can be printed without quotes if it looks like a float
9562  * constant (not an integer, and not Infinity or NaN) and doesn't
9563  * have a leading sign (for the same reason as for INT4).
9564  */
9565  if (isdigit((unsigned char) extval[0]) &&
9566  strcspn(extval, "eE.") != strlen(extval))
9567  {
9568  appendStringInfoString(buf, extval);
9569  }
9570  else
9571  {
9572  appendStringInfo(buf, "'%s'", extval);
9573  needlabel = true; /* we must attach a cast */
9574  }
9575  break;
9576 
9577  case BOOLOID:
9578  if (strcmp(extval, "t") == 0)
9579  appendStringInfoString(buf, "true");
9580  else
9581  appendStringInfoString(buf, "false");
9582  break;
9583 
9584  default:
9585  simple_quote_literal(buf, extval);
9586  break;
9587  }
9588 
9589  pfree(extval);
9590 
9591  if (showtype < 0)
9592  return;
9593 
9594  /*
9595  * For showtype == 0, append ::typename unless the constant will be
9596  * implicitly typed as the right type when it is read in.
9597  *
9598  * XXX this code has to be kept in sync with the behavior of the parser,
9599  * especially make_const.
9600  */
9601  switch (constval->consttype)
9602  {
9603  case BOOLOID:
9604  case UNKNOWNOID:
9605  /* These types can be left unlabeled */
9606  needlabel = false;
9607  break;
9608  case INT4OID:
9609  /* We determined above whether a label is needed */
9610  break;
9611  case NUMERICOID:
9612 
9613  /*
9614  * Float-looking constants will be typed as numeric, which we
9615  * checked above; but if there's a nondefault typmod we need to
9616  * show it.
9617  */
9618  needlabel |= (constval->consttypmod >= 0);
9619  break;
9620  default:
9621  needlabel = true;
9622  break;
9623  }
9624  if (needlabel || showtype > 0)
9625  appendStringInfo(buf, "::%s",
9627  constval->consttypmod));
9628 
9629  get_const_collation(constval, context);
9630 }
Datum constvalue
Definition: primnodes.h:200
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:196
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:9656
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9636
static char * buf
Definition: pg_test_fsync.c:68
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:345
int32 consttypmod
Definition: primnodes.h:197
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1655
StringInfo buf
Definition: ruleutils.c:112
bool constisnull
Definition: primnodes.h:201

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6563 {
6564  StringInfo buf = context->buf;
6565  RangeTblEntry *rte;
6566 
6567  /* Insert the WITH clause if given */
6568  get_with_clause(query, context);
6569 
6570  /*
6571  * Start the query with DELETE FROM relname
6572  */
6573  rte = rt_fetch(query->resultRelation, query->rtable);
6574  Assert(rte->rtekind == RTE_RELATION);
6575  if (PRETTY_INDENT(context))
6576  {
6577  appendStringInfoChar(buf, ' ');
6578  context->indentLevel += PRETTYINDENT_STD;
6579  }
6580  appendStringInfo(buf, "DELETE FROM %s%s",
6581  only_marker(rte),
6583  if (rte->alias != NULL)
6584  appendStringInfo(buf, " %s",
6586 
6587  /* Add the USING clause if given */
6588  get_from_clause(query, " USING ", context);
6589 
6590  /* Add a WHERE clause if given */
6591  if (query->jointree->quals != NULL)
6592  {
6593  appendContextKeyword(context, " WHERE ",
6595  get_rule_expr(query->jointree->quals, context, false);
6596  }
6597 
6598  /* Add RETURNING if present */
6599  if (query->returningList)
6600  {
6601  appendContextKeyword(context, " RETURNING",
6603  get_target_list(query->returningList, context, NULL);
6604  }
6605 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5182
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
Alias * alias
Definition: parsenodes.h:1091
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:5562
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9913
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
Node * quals
Definition: primnodes.h:1497
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10752
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:68
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7725
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define Assert(condition)
Definition: c.h:732
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:473
RTEKind rtekind
Definition: parsenodes.h:974
StringInfo buf
Definition: ruleutils.c:112

◆ get_from_clause()

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

Definition at line 9913 of file ruleutils.c.

References appendBinaryStringInfo(), 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().

9914 {
9915  StringInfo buf = context->buf;
9916  bool first = true;
9917  ListCell *l;
9918 
9919  /*
9920  * We use the query's jointree as a guide to what to print. However, we
9921  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9922  * only appear at the top level of the jointree, so it's sufficient to
9923  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9924  * for NEW and OLD.
9925  */
9926  foreach(l, query->jointree->fromlist)
9927  {
9928  Node *jtnode = (Node *) lfirst(l);
9929 
9930  if (IsA(jtnode, RangeTblRef))
9931  {
9932  int varno = ((RangeTblRef *) jtnode)->rtindex;
9933  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9934 
9935  if (!rte->inFromCl)
9936  continue;
9937  }
9938 
9939  if (first)
9940  {
9941  appendContextKeyword(context, prefix,
9943  first = false;
9944 
9945  get_from_clause_item(jtnode, query, context);
9946  }
9947  else
9948  {
9949  StringInfoData itembuf;
9950 
9951  appendStringInfoString(buf, ", ");
9952 
9953  /*
9954  * Put the new FROM item's text into itembuf so we can decide
9955  * after we've got it whether or not it needs to go on a new line.
9956  */
9957  initStringInfo(&itembuf);
9958  context->buf = &itembuf;
9959 
9960  get_from_clause_item(jtnode, query, context);
9961 
9962  /* Restore context's output buffer */
9963  context->buf = buf;
9964 
9965  /* Consider line-wrapping if enabled */
9966  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
9967  {
9968  /* Does the new item start with a new line? */
9969  if (itembuf.len > 0 && itembuf.data[0] == '\n')
9970  {
9971  /* If so, we shouldn't add anything */
9972  /* instead, remove any trailing spaces currently in buf */
9974  }
9975  else
9976  {
9977  char *trailing_nl;
9978 
9979  /* Locate the start of the current line in the buffer */
9980  trailing_nl = strrchr(buf->data, '\n');
9981  if (trailing_nl == NULL)
9982  trailing_nl = buf->data;
9983  else
9984  trailing_nl++;
9985 
9986  /*
9987  * Add a newline, plus some indentation, if the new item
9988  * would cause an overflow.
9989  */
9990  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
9991  appendContextKeyword(context, "", -PRETTYINDENT_STD,
9994  }
9995  }
9996 
9997  /* Add the new item */
9998  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
9999 
10000  /* clean up */
10001  pfree(itembuf.data);
10002  }
10003  }
10004 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
FromExpr * jointree
Definition: parsenodes.h:138
#define PRETTYINDENT_VAR
Definition: ruleutils.c:86
Definition: nodes.h:524
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
List * fromlist
Definition: primnodes.h:1496
void pfree(void *pointer)
Definition: mcxt.c:1031
List * rtable
Definition: parsenodes.h:137
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7725
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7779
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define lfirst(lc)
Definition: pg_list.h:190
StringInfo buf
Definition: ruleutils.c:112
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:214
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10007

◆ get_from_clause_coldeflist()

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

Definition at line 10382 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, attcollation, attname, atttypid, buf, deparse_context::buf, deparse_columns::colnames, forfour, format_type_with_typemod(), RangeTblFunction::funccolcollations, RangeTblFunction::funccolnames, RangeTblFunction::funccoltypes, RangeTblFunction::funccoltypmods, generate_collation_name(), get_typcollation(), i, lfirst, lfirst_int, lfirst_oid, OidIsValid, quote_identifier(), and strVal.

Referenced by get_from_clause_item().

10385 {
10386  StringInfo buf = context->buf;
10387  ListCell *l1;
10388  ListCell *l2;
10389  ListCell *l3;
10390  ListCell *l4;
10391  int i;
10392 
10393  appendStringInfoChar(buf, '(');
10394 
10395  i = 0;
10396  forfour(l1, rtfunc->funccoltypes,
10397  l2, rtfunc->funccoltypmods,
10398  l3, rtfunc->funccolcollations,
10399  l4, rtfunc->funccolnames)
10400  {
10401  Oid atttypid = lfirst_oid(l1);
10402  int32 atttypmod = lfirst_int(l2);
10403  Oid attcollation = lfirst_oid(l3);
10404  char *attname;
10405 
10406  if (colinfo)
10407  attname = colinfo->colnames[i];
10408  else
10409  attname = strVal(lfirst(l4));
10410 
10411  Assert(attname); /* shouldn't be any dropped columns here */
10412 
10413  if (i > 0)
10414  appendStringInfoString(buf, ", ");
10415  appendStringInfo(buf, "%s %s",
10416  quote_identifier(attname),
10417  format_type_with_typemod(atttypid, atttypmod));
10418  if (OidIsValid(attcollation) &&
10419  attcollation != get_typcollation(atttypid))
10420  appendStringInfo(buf, " COLLATE %s",
10421  generate_collation_name(attcollation));
10422 
10423  i++;
10424  }
10425 
10426  appendStringInfoChar(buf, ')');
10427 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11144
signed int int32
Definition: c.h:346
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:191
Oid attcollation
Definition: pg_attribute.h:164
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
Oid atttypid
Definition: pg_attribute.h:49
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:345
List * funccoltypmods
Definition: parsenodes.h:1130
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2823
List * funccolcollations
Definition: parsenodes.h:1131
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:476
StringInfo buf
Definition: ruleutils.c:112
int i
#define lfirst_oid(lc)
Definition: pg_list.h:192
char ** colnames
Definition: ruleutils.c:229

◆ get_from_clause_item()

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

Definition at line 10007 of file ruleutils.c.

References RangeTblEntry::alias, JoinExpr::alias, 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_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().

10008 {
10009  StringInfo buf = context->buf;
10011 
10012  if (IsA(jtnode, RangeTblRef))
10013  {
10014  int varno = ((RangeTblRef *) jtnode)->rtindex;
10015  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10016  char *refname = get_rtable_name(varno, context);
10017  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10018  RangeTblFunction *rtfunc1 = NULL;
10019  bool printalias;
10020 
10021  if (rte->lateral)
10022  appendStringInfoString(buf, "LATERAL ");
10023 
10024  /* Print the FROM item proper */
10025  switch (rte->rtekind)
10026  {
10027  case RTE_RELATION:
10028  /* Normal relation RTE */
10029  appendStringInfo(buf, "%s%s",
10030  only_marker(rte),
10032  context->namespaces));
10033  break;
10034  case RTE_SUBQUERY:
10035  /* Subquery RTE */
10036  appendStringInfoChar(buf, '(');
10037  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10038  context->prettyFlags, context->wrapColumn,
10039  context->indentLevel);
10040  appendStringInfoChar(buf, ')');
10041  break;
10042  case RTE_FUNCTION:
10043  /* Function RTE */
10044  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10045 
10046  /*
10047  * Omit ROWS FROM() syntax for just one function, unless it
10048  * has both a coldeflist and WITH ORDINALITY. If it has both,
10049  * we must use ROWS FROM() syntax to avoid ambiguity about
10050  * whether the coldeflist includes the ordinality column.
10051  */
10052  if (list_length(rte->functions) == 1 &&
10053  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10054  {
10055  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10056  /* we'll print the coldeflist below, if it has one */
10057  }
10058  else
10059  {
10060  bool all_unnest;
10061  ListCell *lc;
10062 
10063  /*
10064  * If all the function calls in the list are to unnest,
10065  * and none need a coldeflist, then collapse the list back
10066  * down to UNNEST(args). (If we had more than one
10067  * built-in unnest function, this would get more
10068  * difficult.)
10069  *
10070  * XXX This is pretty ugly, since it makes not-terribly-
10071  * future-proof assumptions about what the parser would do
10072  * with the output; but the alternative is to emit our
10073  * nonstandard ROWS FROM() notation for what might have
10074  * been a perfectly spec-compliant multi-argument
10075  * UNNEST().
10076  */
10077  all_unnest = true;
10078  foreach(lc, rte->functions)
10079  {
10080  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10081 
10082  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10083  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
10084  rtfunc->funccolnames != NIL)
10085  {
10086  all_unnest = false;
10087  break;
10088  }
10089  }
10090 
10091  if (all_unnest)
10092  {
10093  List *allargs = NIL;
10094 
10095  foreach(lc, rte->functions)
10096  {
10097  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10098  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10099 
10100  allargs = list_concat(allargs, args);
10101  }
10102 
10103  appendStringInfoString(buf, "UNNEST(");
10104  get_rule_expr((Node *) allargs, context, true);
10105  appendStringInfoChar(buf, ')');
10106  }
10107  else
10108  {
10109  int funcno = 0;
10110 
10111  appendStringInfoString(buf, "ROWS FROM(");
10112  foreach(lc, rte->functions)
10113  {
10114  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10115 
10116  if (funcno > 0)
10117  appendStringInfoString(buf, ", ");
10118  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10119  if (rtfunc->funccolnames != NIL)
10120  {
10121  /* Reconstruct the column definition list */
10122  appendStringInfoString(buf, " AS ");
10124  NULL,
10125  context);
10126  }
10127  funcno++;
10128  }
10129  appendStringInfoChar(buf, ')');
10130  }
10131  /* prevent printing duplicate coldeflist below */
10132  rtfunc1 = NULL;
10133  }
10134  if (rte->funcordinality)
10135  appendStringInfoString(buf, " WITH ORDINALITY");
10136  break;
10137  case RTE_TABLEFUNC:
10138  get_tablefunc(rte->tablefunc, context, true);
10139  break;
10140  case RTE_VALUES:
10141  /* Values list RTE */
10142  appendStringInfoChar(buf, '(');
10143  get_values_def(rte->values_lists, context);
10144  appendStringInfoChar(buf, ')');
10145  break;
10146  case RTE_CTE:
10148  break;
10149  default:
10150  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10151  break;
10152  }
10153 
10154  /* Print the relation alias, if needed */
10155  printalias = false;
10156  if (rte->alias != NULL)
10157  {
10158  /* Always print alias if user provided one */
10159  printalias = true;
10160  }
10161  else if (colinfo->printaliases)
10162  {
10163  /* Always print alias if we need to print column aliases */
10164  printalias = true;
10165  }
10166  else if (rte->rtekind == RTE_RELATION)
10167  {
10168  /*
10169  * No need to print alias if it's same as relation name (this
10170  * would normally be the case, but not if set_rtable_names had to
10171  * resolve a conflict).
10172  */
10173  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10174  printalias = true;
10175  }
10176  else if (rte->rtekind == RTE_FUNCTION)
10177  {
10178  /*
10179  * For a function RTE, always print alias. This covers possible
10180  * renaming of the function and/or instability of the
10181  * FigureColname rules for things that aren't simple functions.
10182  * Note we'd need to force it anyway for the columndef list case.
10183  */
10184  printalias = true;
10185  }
10186  else if (rte->rtekind == RTE_VALUES)
10187  {
10188  /* Alias is syntactically required for VALUES */
10189  printalias = true;
10190  }
10191  else if (rte->rtekind == RTE_CTE)
10192  {
10193  /*
10194  * No need to print alias if it's same as CTE name (this would
10195  * normally be the case, but not if set_rtable_names had to
10196  * resolve a conflict).
10197  */
10198  if (strcmp(refname, rte->ctename) != 0)
10199  printalias = true;
10200  }
10201  if (printalias)
10202  appendStringInfo(buf, " %s", quote_identifier(refname));
10203 
10204  /* Print the column definitions or aliases, if needed */
10205  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10206  {
10207  /* Reconstruct the columndef list, which is also the aliases */
10208  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10209  }
10210  else
10211  {
10212  /* Else print column aliases as needed */
10213  get_column_alias_list(colinfo, context);
10214  }
10215 
10216  /* Tablesample clause must go after any alias */
10217  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10218  get_tablesample_def(rte->tablesample, context);
10219  }
10220  else if (IsA(jtnode, JoinExpr))
10221  {
10222  JoinExpr *j = (JoinExpr *) jtnode;
10223  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10224  bool need_paren_on_right;
10225 
10226  need_paren_on_right = PRETTY_PAREN(context) &&
10227  !IsA(j->rarg, RangeTblRef) &&
10228  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
10229 
10230  if (!PRETTY_PAREN(context) || j->alias != NULL)
10231  appendStringInfoChar(buf, '(');
10232 
10233  get_from_clause_item(j->larg, query, context);
10234 
10235  switch (j->jointype)
10236  {
10237  case JOIN_INNER:
10238  if (j->quals)
10239  appendContextKeyword(context, " JOIN ",
10243  else
10244  appendContextKeyword(context, " CROSS JOIN ",
10248  break;
10249  case JOIN_LEFT:
10250  appendContextKeyword(context, " LEFT JOIN ",
10254  break;
10255  case JOIN_FULL:
10256  appendContextKeyword(context, " FULL JOIN ",
10260  break;
10261  case JOIN_RIGHT:
10262  appendContextKeyword(context, " RIGHT JOIN ",
10266  break;
10267  default:
10268  elog(ERROR, "unrecognized join type: %d",
10269  (int) j->jointype);
10270  }
10271 
10272  if (need_paren_on_right)
10273  appendStringInfoChar(buf, '(');
10274  get_from_clause_item(j->rarg, query, context);
10275  if (need_paren_on_right)
10276  appendStringInfoChar(buf, ')');
10277 
10278  if (j->usingClause)
10279  {
10280  ListCell *lc;
10281  bool first = true;
10282 
10283  appendStringInfoString(buf, " USING (");
10284  /* Use the assigned names, not what's in usingClause */
10285  foreach(lc, colinfo->usingNames)
10286  {
10287  char *colname = (char *) lfirst(lc);
10288 
10289  if (first)
10290  first = false;
10291  else
10292  appendStringInfoString(buf, ", ");
10294  }
10295  appendStringInfoChar(buf, ')');
10296  }
10297  else if (j->quals)
10298  {
10299  appendStringInfoString(buf, " ON ");
10300  if (!PRETTY_PAREN(context))
10301  appendStringInfoChar(buf, '(');
10302  get_rule_expr(j->quals, context, false);
10303  if (!PRETTY_PAREN(context))
10304  appendStringInfoChar(buf, ')');
10305  }
10306  else if (j->jointype != JOIN_INNER)
10307  {
10308  /* If we didn't say CROSS JOIN above, we must provide an ON */
10309  appendStringInfoString(buf, " ON TRUE");
10310  }
10311 
10312  if (!PRETTY_PAREN(context) || j->alias != NULL)
10313  appendStringInfoChar(buf, ')');
10314 
10315  /* Yes, it's correct to put alias after the right paren ... */
10316  if (j->alias != NULL)
10317  {
10318  /*
10319  * Note that it's correct to emit an alias clause if and only if
10320  * there was one originally. Otherwise we'd be converting a named
10321  * join to unnamed or vice versa, which creates semantic
10322  * subtleties we don't want. However, we might print a different
10323  * alias name than was there originally.
10324  */
10325  appendStringInfo(buf, " %s",
10327  context)));
10328  get_column_alias_list(colinfo, context);
10329  }
10330  }
10331  else
10332  elog(ERROR, "unrecognized node type: %d",
10333  (int) nodeTag(jtnode));
10334 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10732
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:85
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
Alias * alias
Definition: parsenodes.h:1091
Definition: nodes.h:524
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
bool funcordinality
Definition: parsenodes.h:1041
List * values_lists
Definition: parsenodes.h:1051
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10752
Node * larg
Definition: primnodes.h:1476
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10433
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:195
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:275
TableFunc * tablefunc
Definition: parsenodes.h:1046
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:99
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7725
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:279
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
List * usingClause
Definition: primnodes.h:1478
Node * quals
Definition: primnodes.h:1479
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9808
Node * rarg
Definition: primnodes.h:1477
Alias * alias
Definition: primnodes.h:1480
JoinType jointype
Definition: primnodes.h:1474
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
#define lfirst(lc)
Definition: pg_list.h:190
List * functions
Definition: parsenodes.h:1040
#define only_marker(rte)
Definition: ruleutils.c:473
static int list_length(const List *l)
Definition: pg_list.h:169
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5066
#define nodeTag(nodeptr)
Definition: nodes.h:529
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5139
RTEKind rtekind
Definition: parsenodes.h:974
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10342
char * ctename
Definition: parsenodes.h:1056
Query * subquery
Definition: parsenodes.h:1009
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:226
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10382
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9047
int rtindex
Definition: primnodes.h:1481
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1004
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4621
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10007

◆ get_func_expr()

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

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

9160 {
9161  StringInfo buf = context->buf;
9162  Oid funcoid = expr->funcid;
9163  Oid argtypes[FUNC_MAX_ARGS];
9164  int nargs;
9165  List *argnames;
9166  bool use_variadic;
9167  ListCell *l;
9168 
9169  /*
9170  * If the function call came from an implicit coercion, then just show the
9171  * first argument --- unless caller wants to see implicit coercions.
9172  */
9173  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9174  {
9175  get_rule_expr_paren((Node *) linitial(expr->args), context,
9176  false, (Node *) expr);
9177  return;
9178  }
9179 
9180  /*
9181  * If the function call came from a cast, then show the first argument
9182  * plus an explicit cast operation.
9183  */
9184  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9186  {
9187  Node *arg = linitial(expr->args);
9188  Oid rettype = expr->funcresulttype;
9189  int32 coercedTypmod;
9190 
9191  /* Get the typmod if this is a length-coercion function */
9192  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9193 
9194  get_coercion_expr(arg, context,
9195  rettype, coercedTypmod,
9196  (Node *) expr);
9197 
9198  return;
9199  }
9200 
9201  /*
9202  * Normal function: display as proname(args). First we need to extract
9203  * the argument datatypes.
9204  */
9205  if (list_length(expr->args) > FUNC_MAX_ARGS)
9206  ereport(ERROR,
9207  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9208  errmsg("too many arguments")));
9209  nargs = 0;
9210  argnames = NIL;
9211  foreach(l, expr->args)
9212  {
9213  Node *arg = (Node *) lfirst(l);
9214 
9215  if (IsA(arg, NamedArgExpr))
9216  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9217  argtypes[nargs] = exprType(arg);
9218  nargs++;
9219  }
9220 
9221  appendStringInfo(buf, "%s(",
9222  generate_function_name(funcoid, nargs,
9223  argnames, argtypes,
9224  expr->funcvariadic,
9225  &use_variadic,
9226  context->special_exprkind));
9227  nargs = 0;
9228  foreach(l, expr->args)
9229  {
9230  if (nargs++ > 0)
9231  appendStringInfoString(buf, ", ");
9232  if (use_variadic && lnext(expr->args, l) == NULL)
9233  appendStringInfoString(buf, "VARIADIC ");
9234  get_rule_expr((Node *) lfirst(l), context, true);
9235  }
9236  appendStringInfoChar(buf, ')');
9237 }
Oid funcresulttype
Definition: primnodes.h:456
#define NIL
Definition: pg_list.h:65
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:10854
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7798
List * args
Definition: primnodes.h:463
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
Definition: nodes.h:524
int errcode(int sqlerrcode)
Definition: elog.c:570
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:346
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:460
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:195
Oid funcid
Definition: primnodes.h:455
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
#define ereport(elevel, rest)
Definition: elog.h:141
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:9442
ParseExprKind special_exprkind
Definition: ruleutils.c:120
List * lappend(List *list, void *datum)
Definition: list.c:321
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
#define lfirst(lc)
Definition: pg_list.h:190
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:169
StringInfo buf
Definition: ruleutils.c:112
int errmsg(const char *fmt,...)
Definition: elog.c:784
void * arg
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:458

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

6142 {
6143  StringInfo buf = context->buf;
6144  RangeTblEntry *select_rte = NULL;
6145  RangeTblEntry *values_rte = NULL;
6146  RangeTblEntry *rte;
6147  char *sep;
6148  ListCell *l;
6149  List *strippedexprs;
6150 
6151  /* Insert the WITH clause if given */
6152  get_with_clause(query, context);
6153 
6154  /*
6155  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6156  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6157  */
6158  foreach(l, query->rtable)
6159  {
6160  rte = (RangeTblEntry *) lfirst(l);
6161 
6162  if (rte->rtekind == RTE_SUBQUERY)
6163  {
6164  if (select_rte)
6165  elog(ERROR, "too many subquery RTEs in INSERT");
6166  select_rte = rte;
6167  }
6168 
6169  if (rte->rtekind == RTE_VALUES)
6170  {
6171  if (values_rte)
6172  elog(ERROR, "too many values RTEs in INSERT");
6173  values_rte = rte;
6174  }
6175  }
6176  if (select_rte && values_rte)
6177  elog(ERROR, "both subquery and values RTEs in INSERT");
6178 
6179  /*
6180  * Start the query with INSERT INTO relname
6181  */
6182  rte = rt_fetch(query->resultRelation, query->rtable);
6183  Assert(rte->rtekind == RTE_RELATION);
6184 
6185  if (PRETTY_INDENT(context))
6186  {
6187  context->indentLevel += PRETTYINDENT_STD;
6188  appendStringInfoChar(buf, ' ');
6189  }
6190  appendStringInfo(buf, "INSERT INTO %s ",
6192  /* INSERT requires AS keyword for target alias */
6193  if (rte->alias != NULL)
6194  appendStringInfo(buf, "AS %s ",
6196 
6197  /*
6198  * Add the insert-column-names list. Any indirection decoration needed on
6199  * the column names can be inferred from the top targetlist.
6200  */
6201  strippedexprs = NIL;
6202  sep = "";
6203  if (query->targetList)
6204  appendStringInfoChar(buf, '(');
6205  foreach(l, query->targetList)
6206  {
6207  TargetEntry *tle = (TargetEntry *) lfirst(l);
6208 
6209  if (tle->resjunk)
6210  continue; /* ignore junk entries */
6211 
6212  appendStringInfoString(buf, sep);
6213  sep = ", ";
6214 
6215  /*
6216  * Put out name of target column; look in the catalogs, not at
6217  * tle->resname, since resname will fail to track RENAME.
6218  */
6221  tle->resno,
6222  false)));
6223 
6224  /*
6225  * Print any indirection needed (subfields or subscripts), and strip
6226  * off the top-level nodes representing the indirection assignments.
6227  * Add the stripped expressions to strippedexprs. (If it's a
6228  * single-VALUES statement, the stripped expressions are the VALUES to
6229  * print below. Otherwise they're just Vars and not really
6230  * interesting.)
6231  */
6232  strippedexprs = lappend(strippedexprs,
6233  processIndirection((Node *) tle->expr,
6234  context));
6235  }
6236  if (query->targetList)
6237  appendStringInfoString(buf, ") ");
6238 
6239  if (query->override)
6240  {
6241  if (query->override == OVERRIDING_SYSTEM_VALUE)
6242  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6243  else if (query->override == OVERRIDING_USER_VALUE)
6244  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6245  }
6246 
6247  if (select_rte)
6248  {
6249  /* Add the SELECT */
6250  get_query_def(select_rte->subquery, buf, NIL, NULL,
6251  context->prettyFlags, context->wrapColumn,
6252  context->indentLevel);
6253  }
6254  else if (values_rte)
6255  {
6256  /* Add the multi-VALUES expression lists */
6257  get_values_def(values_rte->values_lists, context);
6258  }
6259  else if (strippedexprs)
6260  {
6261  /* Add the single-VALUES expression list */
6262  appendContextKeyword(context, "VALUES (",
6264  get_rule_expr((Node *) strippedexprs, context, false);
6265  appendStringInfoChar(buf, ')');
6266  }
6267  else
6268  {
6269  /* No expressions, so it must be DEFAULT VALUES */
6270  appendStringInfoString(buf, "DEFAULT VALUES");
6271  }
6272 
6273  /* Add ON CONFLICT if present */
6274  if (query->onConflict)
6275  {
6276  OnConflictExpr *confl = query->onConflict;
6277 
6278  appendStringInfoString(buf, " ON CONFLICT");
6279 
6280  if (confl->arbiterElems)
6281  {
6282  /* Add the single-VALUES expression list */
6283  appendStringInfoChar(buf, '(');
6284  get_rule_expr((Node *) confl->arbiterElems, context, false);
6285  appendStringInfoChar(buf, ')');
6286 
6287  /* Add a WHERE clause (for partial indexes) if given */
6288  if (confl->arbiterWhere != NULL)
6289  {
6290  bool save_varprefix;
6291 
6292  /*
6293  * Force non-prefixing of Vars, since parser assumes that they
6294  * belong to target relation. WHERE clause does not use
6295  * InferenceElem, so this is separately required.
6296  */
6297  save_varprefix = context->varprefix;
6298  context->varprefix = false;
6299 
6300  appendContextKeyword(context, " WHERE ",
6302  get_rule_expr(confl->arbiterWhere, context, false);
6303 
6304  context->varprefix = save_varprefix;
6305  }
6306  }
6307  else if (OidIsValid(confl->constraint))
6308  {
6309  char *constraint = get_constraint_name(confl->constraint);
6310 
6311  if (!constraint)
6312  elog(ERROR, "cache lookup failed for constraint %u",
6313  confl->constraint);
6314  appendStringInfo(buf, " ON CONSTRAINT %s",
6315  quote_identifier(constraint));
6316  }
6317 
6318  if (confl->action == ONCONFLICT_NOTHING)
6319  {
6320  appendStringInfoString(buf, " DO NOTHING");
6321  }
6322  else
6323  {
6324  appendStringInfoString(buf, " DO UPDATE SET ");
6325  /* Deparse targetlist */
6327  context, rte);
6328 
6329  /* Add a WHERE clause if given */
6330  if (confl->onConflictWhere != NULL)
6331  {
6332  appendContextKeyword(context, " WHERE ",
6334  get_rule_expr(confl->onConflictWhere, context, false);
6335  }
6336  }
6337  }
6338 
6339  /* Add RETURNING if present */
6340  if (query->returningList)
6341  {
6342  appendContextKeyword(context, " RETURNING",
6344  get_target_list(query->returningList, context, NULL);
6345  }
6346 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5182
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
Alias * alias
Definition: parsenodes.h:1091
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:969
OnConflictExpr * onConflict
Definition: parsenodes.h:144
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10520
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5562
Definition: nodes.h:524
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6409
#define OidIsValid(objectId)
Definition: c.h:638
List * values_lists
Definition: parsenodes.h:1051
List * targetList
Definition: parsenodes.h:140
List * arbiterElems
Definition: primnodes.h:1515
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10752
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1400
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7725
AttrNumber resno
Definition: primnodes.h:1394
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
List * lappend(List *list, void *datum)
Definition: list.c:321
OnConflictAction action
Definition: primnodes.h:1512
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
OverridingKind override
Definition: parsenodes.h:142
#define Assert(condition)
Definition: c.h:732
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
#define lfirst(lc)
Definition: pg_list.h:190
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1393
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5066
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5139
RTEKind rtekind
Definition: parsenodes.h:974
Node * arbiterWhere
Definition: primnodes.h:1517
Query * subquery
Definition: parsenodes.h:1009
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:226
List * onConflictSet
Definition: primnodes.h:1521
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
Node * onConflictWhere
Definition: primnodes.h:1522
Definition: pg_list.h:50

◆ 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 6926 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_RESULT, 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().

6928 {
6929  RangeTblEntry *rte;
6931  int netlevelsup;
6932  deparse_namespace *dpns;
6933  TupleDesc tupleDesc;
6934  Node *expr;
6935 
6936  /*
6937  * If it's a RowExpr that was expanded from a whole-row Var, use the
6938  * column names attached to it.
6939  */
6940  if (IsA(var, RowExpr))
6941  {
6942  RowExpr *r = (RowExpr *) var;
6943 
6944  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6945  return strVal(list_nth(r->colnames, fieldno - 1));
6946  }
6947 
6948  /*
6949  * If it's a Param of type RECORD, try to find what the Param refers to.
6950  */
6951  if (IsA(var, Param))
6952  {
6953  Param *param = (Param *) var;
6954  ListCell *ancestor_cell;
6955 
6956  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6957  if (expr)
6958  {
6959  /* Found a match, so recurse to decipher the field name */
6960  deparse_namespace save_dpns;
6961  const char *result;
6962 
6963  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
6964  result = get_name_for_var_field((Var *) expr, fieldno,
6965  0, context);
6966  pop_ancestor_plan(dpns, &save_dpns);
6967  return result;
6968  }
6969  }
6970 
6971  /*
6972  * If it's a Var of type RECORD, we have to find what the Var refers to;
6973  * if not, we can use get_expr_result_tupdesc().
6974  */
6975  if (!IsA(var, Var) ||
6976  var->vartype != RECORDOID)
6977  {
6978  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
6979  /* Got the tupdesc, so we can extract the field name */
6980  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
6981  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
6982  }
6983 
6984  /* Find appropriate nesting depth */
6985  netlevelsup = var->varlevelsup + levelsup;
6986  if (netlevelsup >= list_length(context->namespaces))
6987  elog(ERROR, "bogus varlevelsup: %d offset %d",
6988  var->varlevelsup, levelsup);
6989  dpns = (deparse_namespace *) list_nth(context->namespaces,
6990  netlevelsup);
6991 
6992  /*
6993  * Try to find the relevant RTE in this rtable. In a plan tree, it's
6994  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
6995  * down into the subplans, or INDEX_VAR, which is resolved similarly.
6996  */
6997  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
6998  {
6999  rte = rt_fetch(var->varno, dpns->rtable);
7000  attnum = var->varattno;
7001  }
7002  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
7003  {
7004  TargetEntry *tle;
7005  deparse_namespace save_dpns;
7006  const char *result;
7007 
7008  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
7009  if (!tle)
7010  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
7011 
7012  Assert(netlevelsup == 0);
7013  push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
7014 
7015  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7016  levelsup, context);
7017 
7018  pop_child_plan(dpns, &save_dpns);
7019  return result;
7020  }
7021  else if (var->varno == INNER_VAR && dpns->inner_tlist)
7022  {
7023  TargetEntry *tle;
7024  deparse_namespace save_dpns;
7025  const char *result;
7026 
7027  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
7028  if (!tle)
7029  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
7030 
7031  Assert(netlevelsup == 0);
7032  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7033 
7034  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7035  levelsup, context);
7036 
7037  pop_child_plan(dpns, &save_dpns);
7038  return result;
7039  }
7040  else if (var->varno == INDEX_VAR && dpns->index_tlist)
7041  {
7042  TargetEntry *tle;
7043  const char *result;
7044 
7045  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
7046  if (!tle)
7047  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
7048 
7049  Assert(netlevelsup == 0);
7050 
7051  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7052  levelsup, context);
7053 
7054  return result;
7055  }
7056  else
7057  {
7058  elog(ERROR, "bogus varno: %d", var->varno);
7059  return NULL; /* keep compiler quiet */
7060  }
7061 
7062  if (attnum == InvalidAttrNumber)
7063  {
7064  /* Var is whole-row reference to RTE, so select the right field */
7065  return get_rte_attribute_name(rte, fieldno);
7066  }
7067 
7068  /*
7069  * This part has essentially the same logic as the parser's
7070  * expandRecordVariable() function, but we are dealing with a different
7071  * representation of the input context, and we only need one field name
7072  * not a TupleDesc. Also, we need special cases for finding subquery and
7073  * CTE subplans when deparsing Plan trees.
7074  */
7075  expr = (Node *) var; /* default if we can't drill down */
7076 
7077  switch (rte->rtekind)
7078  {
7079  case RTE_RELATION:
7080  case RTE_VALUES:
7081  case RTE_NAMEDTUPLESTORE:
7082  case RTE_RESULT:
7083 
7084  /*
7085  * This case should not occur: a column of a table, values list,
7086  * or ENR shouldn't have type RECORD. Fall through and fail (most
7087  * likely) at the bottom.
7088  */
7089  break;
7090  case RTE_SUBQUERY:
7091  /* Subselect-in-FROM: examine sub-select's output expr */
7092  {
7093  if (rte->subquery)
7094  {
7096  attnum);
7097 
7098  if (ste == NULL || ste->resjunk)
7099  elog(ERROR, "subquery %s does not have attribute %d",
7100  rte->eref->aliasname, attnum);
7101  expr = (Node *) ste->expr;
7102  if (IsA(expr, Var))
7103  {
7104  /*
7105  * Recurse into the sub-select to see what its Var
7106  * refers to. We have to build an additional level of
7107  * namespace to keep in step with varlevelsup in the
7108  * subselect.
7109  */
7110  deparse_namespace mydpns;
7111  const char *result;
7112 
7113  set_deparse_for_query(&mydpns, rte->subquery,
7114  context->namespaces);
7115 
7116  context->namespaces = lcons(&mydpns,
7117  context->namespaces);
7118 
7119  result = get_name_for_var_field((Var *) expr, fieldno,
7120  0, context);
7121 
7122  context->namespaces =
7123  list_delete_first(context->namespaces);
7124 
7125  return result;
7126  }
7127  /* else fall through to inspect the expression */
7128  }
7129  else
7130  {
7131  /*
7132  * We're deparsing a Plan tree so we don't have complete
7133  * RTE entries (in particular, rte->subquery is NULL). But
7134  * the only place we'd see a Var directly referencing a
7135  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7136  * look into the child plan's tlist instead.
7137  */
7138  TargetEntry *tle;
7139  deparse_namespace save_dpns;
7140  const char *result;
7141 
7142  if (!dpns->inner_planstate)
7143  elog(ERROR, "failed to find plan for subquery %s",
7144  rte->eref->aliasname);
7145  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7146  if (!tle)
7147  elog(ERROR, "bogus varattno for subquery var: %d",
7148  attnum);
7149  Assert(netlevelsup == 0);
7150  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7151 
7152  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7153  levelsup, context);
7154 
7155  pop_child_plan(dpns, &save_dpns);
7156  return result;
7157  }
7158  }
7159  break;
7160  case RTE_JOIN:
7161  /* Join RTE --- recursively inspect the alias variable */
7162  if (rte->joinaliasvars == NIL)
7163  elog(ERROR, "cannot decompile join alias var in plan tree");
7164  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7165  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7166  Assert(expr != NULL);
7167  /* we intentionally don't strip implicit coercions here */
7168  if (IsA(expr, Var))
7169  return get_name_for_var_field((Var *) expr, fieldno,
7170  var->varlevelsup + levelsup,
7171  context);
7172  /* else fall through to inspect the expression */
7173  break;
7174  case RTE_FUNCTION:
7175  case RTE_TABLEFUNC:
7176 
7177  /*
7178  * We couldn't get here unless a function is declared with one of
7179  * its result columns as RECORD, which is not allowed.
7180  */
7181  break;
7182  case RTE_CTE:
7183  /* CTE reference: examine subquery's output expr */
7184  {
7185  CommonTableExpr *cte = NULL;
7186  Index ctelevelsup;
7187  ListCell *lc;
7188 
7189  /*
7190  * Try to find the referenced CTE using the namespace stack.
7191  */
7192  ctelevelsup = rte->ctelevelsup + netlevelsup;
7193  if (ctelevelsup >= list_length(context->namespaces))
7194  lc = NULL;
7195  else
7196  {
7197  deparse_namespace *ctedpns;
7198 
7199  ctedpns = (deparse_namespace *)
7200  list_nth(context->namespaces, ctelevelsup);
7201  foreach(lc, ctedpns->ctes)
7202  {
7203  cte = (CommonTableExpr *) lfirst(lc);
7204  if (strcmp(cte->ctename, rte->ctename) == 0)
7205  break;
7206  }
7207  }
7208  if (lc != NULL)
7209  {
7210  Query *ctequery = (Query *) cte->ctequery;
7212  attnum);
7213 
7214  if (ste == NULL || ste->resjunk)
7215  elog(ERROR, "subquery %s does not have attribute %d",
7216  rte->eref->aliasname, attnum);
7217  expr = (Node *) ste->expr;
7218  if (IsA(expr, Var))
7219  {
7220  /*
7221  * Recurse into the CTE to see what its Var refers to.
7222  * We have to build an additional level of namespace
7223  * to keep in step with varlevelsup in the CTE.
7224  * Furthermore it could be an outer CTE, so we may
7225  * have to delete some levels of namespace.
7226  */
7227  List *save_nslist = context->namespaces;
7228  List *new_nslist;
7229  deparse_namespace mydpns;
7230  const char *result;
7231 
7232  set_deparse_for_query(&mydpns, ctequery,
7233  context->namespaces);
7234 
7235  new_nslist = list_copy_tail(context->namespaces,
7236  ctelevelsup);
7237  context->namespaces = lcons(&mydpns, new_nslist);
7238 
7239  result = get_name_for_var_field((Var *) expr, fieldno,
7240  0, context);
7241 
7242  context->namespaces = save_nslist;
7243 
7244  return result;
7245  }
7246  /* else fall through to inspect the expression */
7247  }
7248  else
7249  {
7250  /*
7251  * We're deparsing a Plan tree so we don't have a CTE
7252  * list. But the only place we'd see a Var directly
7253  * referencing a CTE RTE is in a CteScan plan node, and we
7254  * can look into the subplan's tlist instead.
7255  */
7256  TargetEntry *tle;
7257  deparse_namespace save_dpns;
7258  const char *result;
7259 
7260  if (!dpns->inner_planstate)
7261  elog(ERROR, "failed to find plan for CTE %s",
7262  rte->eref->aliasname);
7263  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7264  if (!tle)
7265  elog(ERROR, "bogus varattno for subquery var: %d",
7266  attnum);
7267  Assert(netlevelsup == 0);
7268  push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
7269 
7270  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7271  levelsup, context);
7272 
7273  pop_child_plan(dpns, &save_dpns);
7274  return result;
7275  }
7276  }
7277  break;
7278  }
7279 
7280  /*
7281  * We now have an expression we can't expand any more, so see if
7282  * get_expr_result_tupdesc() can do anything with it.
7283  */
7284  tupleDesc = get_expr_result_tupdesc(expr, false);
7285  /* Got the tupdesc, so we can extract the field name */
7286  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7287  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7288 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
List * joinaliasvars
Definition: parsenodes.h:1030
Index varlevelsup
Definition: primnodes.h:177
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7299
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:524
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:172
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4783
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1419
PlanState * inner_planstate
Definition: ruleutils.c:164
Definition: primnodes.h:167
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1400
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
List * colnames
Definition: primnodes.h:1024
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:397
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
Oid vartype
Definition: primnodes.h:174
static void push_child_plan(deparse_namespace *dpns, PlanState *ps, deparse_namespace *save_dpns)
Definition: ruleutils.c:4715
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:170
List * outer_tlist
Definition: ruleutils.c:165
unsigned int Index
Definition: c.h:475
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6926
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:157
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
List * lcons(void *datum, List *list)
Definition: list.c:453
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4732
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1393
PlanState * outer_planstate
Definition: ruleutils.c:163
static int list_length(const List *l)
Definition: pg_list.h:169
Index ctelevelsup
Definition: parsenodes.h:1057
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3553
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:974
char * ctename
Definition: parsenodes.h:1056
Query * subquery
Definition: parsenodes.h:1009
List * index_tlist
Definition: ruleutils.c:167
List * inner_tlist
Definition: ruleutils.c:166
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4762
#define elog(elevel,...)
Definition: elog.h:226
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:609
Alias * eref
Definition: parsenodes.h:1092
#define INDEX_VAR
Definition: primnodes.h:159
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1444
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:158
List * list_delete_first(List *list)
Definition: list.c:857

◆ get_opclass_name()

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

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

10479 {
10480  HeapTuple ht_opc;
10481  Form_pg_opclass opcrec;
10482  char *opcname;
10483  char *nspname;
10484 
10485  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10486  if (!HeapTupleIsValid(ht_opc))
10487  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10488  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10489 
10490  if (!OidIsValid(actual_datatype) ||
10491  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10492  {
10493  /* Okay, we need the opclass name. Do we need to qualify it? */
10494  opcname = NameStr(opcrec->opcname);
10495  if (OpclassIsVisible(opclass))
10496  appendStringInfo(buf, " %s", quote_identifier(opcname));
10497  else
10498  {
10499  nspname = get_namespace_name(opcrec->opcnamespace);
10500  appendStringInfo(buf, " %s.%s",
10501  quote_identifier(nspname),
10502  quote_identifier(opcname));
10503  }
10504  }
10505  ReleaseSysCache(ht_opc);
10506 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1938
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
#define OidIsValid(objectId)
Definition: c.h:638
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1825
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83

◆ get_oper_expr()

static void get_oper_expr ( OpExpr expr,
deparse_context context 
)
static

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

9098 {
9099  StringInfo buf = context->buf;
9100  Oid opno = expr->opno;
9101  List *args = expr->args;
9102 
9103  if (!PRETTY_PAREN(context))
9104  appendStringInfoChar(buf, '(');
9105  if (list_length(args) == 2)
9106  {
9107  /* binary operator */
9108  Node *arg1 = (Node *) linitial(args);
9109  Node *arg2 = (Node *) lsecond(args);
9110 
9111  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9112  appendStringInfo(buf, " %s ",
9114  exprType(arg1),
9115  exprType(arg2)));
9116  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9117  }
9118  else
9119  {
9120  /* unary operator --- but which side? */
9121  Node *arg = (Node *) linitial(args);
9122  HeapTuple tp;
9123  Form_pg_operator optup;
9124 
9126  if (!HeapTupleIsValid(tp))
9127  elog(ERROR, "cache lookup failed for operator %u", opno);
9128  optup = (Form_pg_operator) GETSTRUCT(tp);
9129  switch (optup->oprkind)
9130  {
9131  case 'l':
9132  appendStringInfo(buf, "%s ",
9134  InvalidOid,
9135  exprType(arg)));
9136  get_rule_expr_paren(arg, context, true, (Node *) expr);
9137  break;
9138  case 'r':
9139  get_rule_expr_paren(arg, context, true, (Node *) expr);
9140  appendStringInfo(buf, " %s",
9142  exprType(arg),
9143  InvalidOid));
9144  break;
9145  default:
9146  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
9147  }
9148  ReleaseSysCache(tp);
9149  }
9150  if (!PRETTY_PAREN(context))
9151  appendStringInfoChar(buf, ')');
9152 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7798
Definition: nodes.h:524
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:200
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:10959
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:99
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#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:169
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:84
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:226
void * arg
Oid opno
Definition: primnodes.h:502
List * args
Definition: primnodes.h:508
Definition: pg_list.h:50

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

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

7420 {
7421  Node *expr;
7422  deparse_namespace *dpns;
7423  ListCell *ancestor_cell;
7424 
7425  /*
7426  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7427  * the parameter was computed. Note that failing to find a referent isn't
7428  * an error, since the Param might well be a subplan output rather than an
7429  * input.
7430  */
7431  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7432  if (expr)
7433  {
7434  /* Found a match, so print it */
7435  deparse_namespace save_dpns;
7436  bool save_varprefix;
7437  bool need_paren;
7438 
7439  /* Switch attention to the ancestor plan node */
7440  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7441 
7442  /*
7443  * Force prefixing of Vars, since they won't belong to the relation
7444  * being scanned in the original plan node.
7445  */
7446  save_varprefix = context->varprefix;
7447  context->varprefix = true;
7448 
7449  /*
7450  * A Param's expansion is typically a Var, Aggref, or upper-level
7451  * Param, which wouldn't need extra parentheses. Otherwise, insert
7452  * parens to ensure the expression looks atomic.
7453  */
7454  need_paren = !(IsA(expr, Var) ||
7455  IsA(expr, Aggref) ||
7456  IsA(expr, Param));
7457  if (need_paren)
7458  appendStringInfoChar(context->buf, '(');
7459 
7460  get_rule_expr(expr, context, false);
7461 
7462  if (need_paren)
7463  appendStringInfoChar(context->buf, ')');
7464 
7465  context->varprefix = save_varprefix;
7466 
7467  pop_ancestor_plan(dpns, &save_dpns);
7468 
7469  return;
7470  }
7471 
7472  /*
7473  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7474  */
7475  appendStringInfo(context->buf, "$%d", param->paramid);
7476 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7299
Definition: nodes.h:524
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4783
Definition: primnodes.h:167
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7830
int paramid
Definition: primnodes.h:249
StringInfo buf
Definition: ruleutils.c:112
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4762

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

5069 {
5070  deparse_context context;
5071  deparse_namespace dpns;
5072 
5073  /* Guard against excessively long or deeply-nested queries */
5076 
5077  /*
5078  * Before we begin to examine the query, acquire locks on referenced
5079  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5080  * consistent results. Note we assume it's OK to scribble on the passed
5081  * querytree!
5082  *
5083  * We are only deparsing the query (we are not about to execute it), so we
5084  * only need AccessShareLock on the relations it mentions.
5085  */
5086  AcquireRewriteLocks(query, false, false);
5087 
5088  context.buf = buf;
5089  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5090  context.windowClause = NIL;
5091  context.windowTList = NIL;
5092  context.varprefix = (parentnamespace != NIL ||
5093  list_length(query->rtable) != 1);
5094  context.prettyFlags = prettyFlags;
5095  context.wrapColumn = wrapColumn;
5096  context.indentLevel = startIndent;
5097  context.special_exprkind = EXPR_KIND_NONE;
5098 
5099  set_deparse_for_query(&dpns, query, parentnamespace);
5100 
5101  switch (query->commandType)
5102  {
5103  case CMD_SELECT:
5104  get_select_query_def(query, &context, resultDesc);
5105  break;
5106 
5107  case CMD_UPDATE:
5108  get_update_query_def(query, &context);
5109  break;
5110 
5111  case CMD_INSERT:
5112  get_insert_query_def(query, &context);
5113  break;
5114 
5115  case CMD_DELETE:
5116  get_delete_query_def(query, &context);
5117  break;
5118 
5119  case CMD_NOTHING:
5120  appendStringInfoString(buf, "NOTHING");
5121  break;
5122 
5123  case CMD_UTILITY:
5124  get_utility_query_def(query, &context);
5125  break;
5126 
5127  default:
5128  elog(ERROR, "unrecognized query command type: %d",
5129  query->commandType);
5130  break;
5131  }
5132 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
List * list_copy(const List *oldlist)
Definition: list.c:1400
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6141
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6354
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:6613
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5262
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
void check_stack_depth(void)
Definition: postgres.c:3262
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:120
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6562
List * windowTList
Definition: ruleutils.c:115
CmdType commandType
Definition: parsenodes.h:112
List * lcons(void *datum, List *list)
Definition: list.c:453
List * windowClause
Definition: ruleutils.c:114
static int list_length(const List *l)
Definition: pg_list.h:169
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3553
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:226
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99

◆ get_range_partbound_string()

char* get_range_partbound_string ( List bound_datums)

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

11270 {
11271  deparse_context context;
11273  ListCell *cell;
11274  char *sep;
11275 
11276  memset(&context, 0, sizeof(deparse_context));
11277  context.buf = buf;
11278 
11279  appendStringInfoString(buf, "(");
11280  sep = "";
11281  foreach(cell, bound_datums)
11282  {
11283  PartitionRangeDatum *datum =
11285 
11286  appendStringInfoString(buf, sep);
11287  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
11288  appendStringInfoString(buf, "MINVALUE");
11289  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
11290  appendStringInfoString(buf, "MAXVALUE");
11291  else
11292  {
11293  Const *val = castNode(Const, datum->value);
11294 
11295  get_const_expr(val, &context, -1);
11296  }
11297  sep = ", ";
11298  }
11299  appendStringInfoChar(buf, ')');
11300 
11301  return buf->data;
11302 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:593
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:9506
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define lfirst(lc)
Definition: pg_list.h:190
StringInfo buf
Definition: ruleutils.c:112
long val
Definition: informix.c:684

◆ get_relation_name()

static char * get_relation_name ( Oid  relid)
static

Definition at line 10732 of file ruleutils.c.

References elog, ERROR, get_rel_name(), and relname.

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

10733 {
10734  char *relname = get_rel_name(relid);
10735 
10736  if (!relname)
10737  elog(ERROR, "cache lookup failed for relation %u", relid);
10738  return relname;
10739 }
NameData relname
Definition: pg_class.h:35
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:226
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 4621 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().

4622 {
4624 
4625  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4626  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4627 }
List * namespaces
Definition: ruleutils.c:113
List * rtable_names
Definition: ruleutils.c:154
#define linitial(l)
Definition: pg_list.h:195
static void * list_nth(const List *list, int n)
Definition: