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/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 "nodes/pathnodes.h"
#include "optimizer/optimizer.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
#include "parser/parse_node.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 ")
 

Typedefs

typedef void(* rsv_callback) (Node *node, deparse_context *context, void *callback_arg)
 

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 columns_only, 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 print_function_sqlbody (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 char * get_rtable_name (int rtindex, deparse_context *context)
 
static void set_deparse_plan (deparse_namespace *dpns, Plan *plan)
 
static Planfind_recursive_union (deparse_namespace *dpns, WorkTableScan *wtscan)
 
static void push_child_plan (deparse_namespace *dpns, Plan *plan, 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 *callback_arg)
 
static void resolve_special_varno (Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
 
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 *callback_arg)
 
static void get_windowfunc_expr (WindowFunc *wfunc, deparse_context *context)
 
static bool get_func_sql_syntax (FuncExpr *expr, 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)
 
static void get_reloptions (StringInfo buf, Datum reloptions)
 
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)
 
char * pg_get_statisticsobjdef_string (Oid statextid)
 
Datum pg_get_statisticsobjdef_columns (PG_FUNCTION_ARGS)
 
Datum pg_get_statisticsobjdef_expressions (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)
 
Datum pg_get_function_sqlbody (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_tree (PlannedStmt *pstmt, List *rtable_names)
 
Listset_deparse_context_plan (List *dpcontext, Plan *plan, List *ancestors)
 
Listselect_rtable_names_for_explain (List *rtable, Bitmapset *rels_used)
 
static RangeTblEntryget_simple_values_rte (Query *query, TupleDesc resultDesc)
 
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)
 
char * generate_opclass_name (Oid opclass)
 
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 492 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 99 of file ruleutils.c.

◆ PRETTYFLAG_INDENT

◆ PRETTYFLAG_PAREN

◆ PRETTYFLAG_SCHEMA

◆ PRETTYINDENT_JOIN

#define PRETTYINDENT_JOIN   4

Definition at line 83 of file ruleutils.c.

Referenced by get_from_clause_item().

◆ PRETTYINDENT_LIMIT

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 86 of file ruleutils.c.

Referenced by appendContextKeyword().

◆ PRETTYINDENT_STD

◆ PRETTYINDENT_VAR

#define PRETTYINDENT_VAR   4

Definition at line 84 of file ruleutils.c.

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

◆ WRAP_COLUMN_DEFAULT

Typedef Documentation

◆ rsv_callback

typedef void(* rsv_callback) (Node *node, deparse_context *context, void *callback_arg)

Definition at line 304 of file ruleutils.c.

Function Documentation

◆ add_cast_to()

static void add_cast_to ( StringInfo  buf,
Oid  typid 
)
static

Definition at line 11822 of file ruleutils.c.

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

Referenced by generate_operator_clause().

11823 {
11824  HeapTuple typetup;
11825  Form_pg_type typform;
11826  char *typname;
11827  char *nspname;
11828 
11829  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11830  if (!HeapTupleIsValid(typetup))
11831  elog(ERROR, "cache lookup failed for type %u", typid);
11832  typform = (Form_pg_type) GETSTRUCT(typetup);
11833 
11834  typname = NameStr(typform->typname);
11835  nspname = get_namespace_name_or_temp(typform->typnamespace);
11836 
11837  appendStringInfo(buf, "::%s.%s",
11838  quote_identifier(nspname), quote_identifier(typname));
11839 
11840  ReleaseSysCache(typetup);
11841 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
NameData typname
Definition: pg_type.h:41
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ appendContextKeyword()

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

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

8217 {
8218  StringInfo buf = context->buf;
8219 
8220  if (PRETTY_INDENT(context))
8221  {
8222  int indentAmount;
8223 
8224  context->indentLevel += indentBefore;
8225 
8226  /* remove any trailing spaces currently in the buffer ... */
8228  /* ... then add a newline and some spaces */
8229  appendStringInfoChar(buf, '\n');
8230 
8231  if (context->indentLevel < PRETTYINDENT_LIMIT)
8232  indentAmount = Max(context->indentLevel, 0) + indentPlus;
8233  else
8234  {
8235  /*
8236  * If we're indented more than PRETTYINDENT_LIMIT characters, try
8237  * to conserve horizontal space by reducing the per-level
8238  * indentation. For best results the scale factor here should
8239  * divide all the indent amounts that get added to indentLevel
8240  * (PRETTYINDENT_STD, etc). It's important that the indentation
8241  * not grow unboundedly, else deeply-nested trees use O(N^2)
8242  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
8243  */
8244  indentAmount = PRETTYINDENT_LIMIT +
8245  (context->indentLevel - PRETTYINDENT_LIMIT) /
8246  (PRETTYINDENT_STD / 2);
8247  indentAmount %= PRETTYINDENT_LIMIT;
8248  /* scale/wrap logic affects indentLevel, but not indentPlus */
8249  indentAmount += indentPlus;
8250  }
8251  appendStringInfoSpaces(buf, indentAmount);
8252 
8254 
8255  context->indentLevel += indentAfter;
8256  if (context->indentLevel < 0)
8257  context->indentLevel = 0;
8258  }
8259  else
8261 }
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:8269
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
#define PRETTYINDENT_LIMIT
Definition: ruleutils.c:86
#define Max(x, y)
Definition: c.h:980
StringInfo buf
Definition: ruleutils.c:110

◆ colname_is_unique()

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

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

4643 {
4644  int i;
4645  ListCell *lc;
4646 
4647  /* Check against already-assigned column aliases within RTE */
4648  for (i = 0; i < colinfo->num_cols; i++)
4649  {
4650  char *oldname = colinfo->colnames[i];
4651 
4652  if (oldname && strcmp(oldname, colname) == 0)
4653  return false;
4654  }
4655 
4656  /*
4657  * If we're building a new_colnames array, check that too (this will be
4658  * partially but not completely redundant with the previous checks)
4659  */
4660  for (i = 0; i < colinfo->num_new_cols; i++)
4661  {
4662  char *oldname = colinfo->new_colnames[i];
4663 
4664  if (oldname && strcmp(oldname, colname) == 0)
4665  return false;
4666  }
4667 
4668  /* Also check against USING-column names that must be globally unique */
4669  foreach(lc, dpns->using_names)
4670  {
4671  char *oldname = (char *) lfirst(lc);
4672 
4673  if (strcmp(oldname, colname) == 0)
4674  return false;
4675  }
4676 
4677  /* Also check against names already assigned for parent-join USING cols */
4678  foreach(lc, colinfo->parentUsing)
4679  {
4680  char *oldname = (char *) lfirst(lc);
4681 
4682  if (strcmp(oldname, colname) == 0)
4683  return false;
4684  }
4685 
4686  return true;
4687 }
List * using_names
Definition: ruleutils.c:166
#define lfirst(lc)
Definition: pg_list.h:169
int i
List * parentUsing
Definition: ruleutils.c:264
char ** new_colnames
Definition: ruleutils.c:257
char ** colnames
Definition: ruleutils.c:240

◆ decompile_column_index_array()

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

Definition at line 2515 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2517 {
2518  Datum *keys;
2519  int nKeys;
2520  int j;
2521 
2522  /* Extract data from array of int16 */
2523  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2524  INT2OID, 2, true, TYPALIGN_SHORT,
2525  &keys, NULL, &nKeys);
2526 
2527  for (j = 0; j < nKeys; j++)
2528  {
2529  char *colName;
2530 
2531  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2532 
2533  if (j == 0)
2535  else
2536  appendStringInfo(buf, ", %s", quote_identifier(colName));
2537  }
2538 
2539  return nKeys;
2540 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
#define DatumGetInt16(X)
Definition: postgres.h:488
uintptr_t Datum
Definition: postgres.h:411
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3491
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ deparse_context_for()

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

Definition at line 3561 of file ruleutils.c.

References AccessShareLock, RangeTblEntry::alias, deparse_namespace::appendrels, 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(), set_simple_column_names(), and deparse_namespace::subplans.

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(), pg_get_statisticsobj_worker(), pg_get_statisticsobjdef_expressions(), transformPartitionBound(), and transformPartitionRangeBounds().

3562 {
3563  deparse_namespace *dpns;
3564  RangeTblEntry *rte;
3565 
3566  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3567 
3568  /* Build a minimal RTE for the rel */
3569  rte = makeNode(RangeTblEntry);
3570  rte->rtekind = RTE_RELATION;
3571  rte->relid = relid;
3572  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3574  rte->alias = makeAlias(aliasname, NIL);
3575  rte->eref = rte->alias;
3576  rte->lateral = false;
3577  rte->inh = false;
3578  rte->inFromCl = true;
3579 
3580  /* Build one-element rtable */
3581  dpns->rtable = list_make1(rte);
3582  dpns->subplans = NIL;
3583  dpns->ctes = NIL;
3584  dpns->appendrels = NULL;
3585  set_rtable_names(dpns, NIL, NULL);
3587 
3588  /* Return a one-deep namespace stack */
3589  return list_make1(dpns);
3590 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1152
#define AccessShareLock
Definition: lockdefs.h:36
AppendRelInfo ** appendrels
Definition: ruleutils.c:163
#define list_make1(x1)
Definition: pg_list.h:206
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:387
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3727
void * palloc0(Size size)
Definition: mcxt.c:1093
#define makeNode(_type_)
Definition: nodes.h:585
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3937
RTEKind rtekind
Definition: parsenodes.h:1007
Alias * eref
Definition: parsenodes.h:1153

◆ deparse_context_for_plan_tree()

List* deparse_context_for_plan_tree ( PlannedStmt pstmt,
List rtable_names 
)

Definition at line 3606 of file ruleutils.c.

References PlannedStmt::appendRelations, deparse_namespace::appendrels, Assert, AppendRelInfo::child_relid, deparse_namespace::ctes, lfirst_node, list_length(), list_make1, NIL, palloc0(), PlannedStmt::rtable, deparse_namespace::rtable, deparse_namespace::rtable_names, set_simple_column_names(), PlannedStmt::subplans, and deparse_namespace::subplans.

Referenced by ExplainPrintPlan().

3607 {
3608  deparse_namespace *dpns;
3609 
3610  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3611 
3612  /* Initialize fields that stay the same across the whole plan tree */
3613  dpns->rtable = pstmt->rtable;
3614  dpns->rtable_names = rtable_names;
3615  dpns->subplans = pstmt->subplans;
3616  dpns->ctes = NIL;
3617  if (pstmt->appendRelations)
3618  {
3619  /* Set up the array, indexed by child relid */
3620  int ntables = list_length(dpns->rtable);
3621  ListCell *lc;
3622 
3623  dpns->appendrels = (AppendRelInfo **)
3624  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3625  foreach(lc, pstmt->appendRelations)
3626  {
3627  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3628  Index crelid = appinfo->child_relid;
3629 
3630  Assert(crelid > 0 && crelid <= ntables);
3631  Assert(dpns->appendrels[crelid] == NULL);
3632  dpns->appendrels[crelid] = appinfo;
3633  }
3634  }
3635  else
3636  dpns->appendrels = NULL; /* don't need it */
3637 
3638  /*
3639  * Set up column name aliases. We will get rather bogus results for join
3640  * RTEs, but that doesn't matter because plan trees don't contain any join
3641  * alias Vars.
3642  */
3644 
3645  /* Return a one-deep namespace stack */
3646  return list_make1(dpns);
3647 }
#define NIL
Definition: pg_list.h:65
List * rtable_names
Definition: ruleutils.c:159
AppendRelInfo ** appendrels
Definition: ruleutils.c:163
#define list_make1(x1)
Definition: pg_list.h:206
#define lfirst_node(type, lc)
Definition: pg_list.h:172
void * palloc0(Size size)
Definition: mcxt.c:1093
unsigned int Index
Definition: c.h:549
List * subplans
Definition: plannodes.h:73
#define Assert(condition)
Definition: c.h:804
static int list_length(const List *l)
Definition: pg_list.h:149
List * rtable
Definition: plannodes.h:66
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3937
Index child_relid
Definition: pathnodes.h:2307
List * appendRelations
Definition: plannodes.h:71

◆ deparse_expression()

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

Definition at line 3501 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_memoize_info(), show_plan_tlist(), show_sort_group_keys(), show_tablesample(), transformPartitionBound(), and transformPartitionRangeBounds().

3503 {
3504  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3505  showimplicit, 0, 0);
3506 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3528

◆ deparse_expression_pretty()

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

Definition at line 3528 of file ruleutils.c.

References deparse_context::appendparents, 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(), pg_get_partkeydef_worker(), pg_get_statisticsobj_worker(), and pg_get_statisticsobjdef_expressions().

3531 {
3533  deparse_context context;
3534 
3535  initStringInfo(&buf);
3536  context.buf = &buf;
3537  context.namespaces = dpcontext;
3538  context.windowClause = NIL;
3539  context.windowTList = NIL;
3540  context.varprefix = forceprefix;
3541  context.prettyFlags = prettyFlags;
3542  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3543  context.indentLevel = startIndent;
3544  context.special_exprkind = EXPR_KIND_NONE;
3545  context.appendparents = NULL;
3546 
3547  get_rule_expr(expr, &context, showimplicit);
3548 
3549  return buf.data;
3550 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:94
static char * buf
Definition: pg_test_fsync.c:68
ParseExprKind special_exprkind
Definition: ruleutils.c:118
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
List * windowTList
Definition: ruleutils.c:113
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
List * windowClause
Definition: ruleutils.c:112
Bitmapset * appendparents
Definition: ruleutils.c:120
StringInfo buf
Definition: ruleutils.c:110

◆ expand_colnames_array_to()

static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

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

4735 {
4736  if (n > colinfo->num_cols)
4737  {
4738  if (colinfo->colnames == NULL)
4739  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4740  else
4741  {
4742  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4743  n * sizeof(char *));
4744  memset(colinfo->colnames + colinfo->num_cols, 0,
4745  (n - colinfo->num_cols) * sizeof(char *));
4746  }
4747  colinfo->num_cols = n;
4748  }
4749 }
void * palloc0(Size size)
Definition: mcxt.c:1093
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
char ** colnames
Definition: ruleutils.c:240

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

References deparse_namespace::ancestors, arg, SubPlan::args, Assert, elog, ERROR, for_each_cell, forboth, innerPlan, IsA, lfirst, lfirst_int, lfirst_node, linitial, list_nth(), lnext(), deparse_context::namespaces, NestLoop::nestParams, NIL, PARAM_EXEC, Param::paramid, Param::paramkind, NestLoopParam::paramno, NestLoopParam::paramval, SubPlan::parParam, deparse_namespace::plan, SubPlan::plan_id, and deparse_namespace::subplans.

Referenced by get_name_for_var_field(), and get_parameter().

7732 {
7733  /* Initialize output parameters to prevent compiler warnings */
7734  *dpns_p = NULL;
7735  *ancestor_cell_p = NULL;
7736 
7737  /*
7738  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7739  * SubPlan argument. This will necessarily be in some ancestor of the
7740  * current expression's Plan node.
7741  */
7742  if (param->paramkind == PARAM_EXEC)
7743  {
7744  deparse_namespace *dpns;
7745  Plan *child_plan;
7746  bool in_same_plan_level;
7747  ListCell *lc;
7748 
7749  dpns = (deparse_namespace *) linitial(context->namespaces);
7750  child_plan = dpns->plan;
7751  in_same_plan_level = true;
7752 
7753  foreach(lc, dpns->ancestors)
7754  {
7755  Node *ancestor = (Node *) lfirst(lc);
7756  ListCell *lc2;
7757 
7758  /*
7759  * NestLoops transmit params to their inner child only; also, once
7760  * we've crawled up out of a subplan, this couldn't possibly be
7761  * the right match.
7762  */
7763  if (IsA(ancestor, NestLoop) &&
7764  child_plan == innerPlan(ancestor) &&
7765  in_same_plan_level)
7766  {
7767  NestLoop *nl = (NestLoop *) ancestor;
7768 
7769  foreach(lc2, nl->nestParams)
7770  {
7771  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7772 
7773  if (nlp->paramno == param->paramid)
7774  {
7775  /* Found a match, so return it */
7776  *dpns_p = dpns;
7777  *ancestor_cell_p = lc;
7778  return (Node *) nlp->paramval;
7779  }
7780  }
7781  }
7782 
7783  /*
7784  * If ancestor is a SubPlan, check the arguments it provides.
7785  */
7786  if (IsA(ancestor, SubPlan))
7787  {
7788  SubPlan *subplan = (SubPlan *) ancestor;
7789  ListCell *lc3;
7790  ListCell *lc4;
7791 
7792  forboth(lc3, subplan->parParam, lc4, subplan->args)
7793  {
7794  int paramid = lfirst_int(lc3);
7795  Node *arg = (Node *) lfirst(lc4);
7796 
7797  if (paramid == param->paramid)
7798  {
7799  /*
7800  * Found a match, so return it. But, since Vars in
7801  * the arg are to be evaluated in the surrounding
7802  * context, we have to point to the next ancestor item
7803  * that is *not* a SubPlan.
7804  */
7805  ListCell *rest;
7806 
7807  for_each_cell(rest, dpns->ancestors,
7808  lnext(dpns->ancestors, lc))
7809  {
7810  Node *ancestor2 = (Node *) lfirst(rest);
7811 
7812  if (!IsA(ancestor2, SubPlan))
7813  {
7814  *dpns_p = dpns;
7815  *ancestor_cell_p = rest;
7816  return arg;
7817  }
7818  }
7819  elog(ERROR, "SubPlan cannot be outermost ancestor");
7820  }
7821  }
7822 
7823  /* We have emerged from a subplan. */
7824  in_same_plan_level = false;
7825 
7826  /* SubPlan isn't a kind of Plan, so skip the rest */
7827  continue;
7828  }
7829 
7830  /*
7831  * Check to see if we're emerging from an initplan of the current
7832  * ancestor plan. Initplans never have any parParams, so no need
7833  * to search that list, but we need to know if we should reset
7834  * in_same_plan_level.
7835  */
7836  foreach(lc2, ((Plan *) ancestor)->initPlan)
7837  {
7838  SubPlan *subplan = lfirst_node(SubPlan, lc2);
7839 
7840  if (child_plan != (Plan *) list_nth(dpns->subplans,
7841  subplan->plan_id - 1))
7842  continue;
7843 
7844  /* No parameters to be had here. */
7845  Assert(subplan->parParam == NIL);
7846 
7847  /* We have emerged from an initplan. */
7848  in_same_plan_level = false;
7849  break;
7850  }
7851 
7852  /* No luck, crawl up to next ancestor */
7853  child_plan = (Plan *) ancestor;
7854  }
7855  }
7856 
7857  /* No referent found */
7858  return NULL;
7859 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
int plan_id
Definition: primnodes.h:752
List * nestParams
Definition: plannodes.h:726
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:417
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:537
Var * paramval
Definition: plannodes.h:733
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
#define lfirst_int(lc)
Definition: pg_list.h:170
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define innerPlan(node)
Definition: plannodes.h:170
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
int paramid
Definition: primnodes.h:268
List * parParam
Definition: primnodes.h:772
#define elog(elevel,...)
Definition: elog.h:232
void * arg
List * args
Definition: primnodes.h:773

◆ find_recursive_union()

static Plan * find_recursive_union ( deparse_namespace dpns,
WorkTableScan wtscan 
)
static

Definition at line 4916 of file ruleutils.c.

References deparse_namespace::ancestors, elog, ERROR, IsA, lfirst, and WorkTableScan::wtParam.

Referenced by set_deparse_plan().

4917 {
4918  ListCell *lc;
4919 
4920  foreach(lc, dpns->ancestors)
4921  {
4922  Plan *ancestor = (Plan *) lfirst(lc);
4923 
4924  if (IsA(ancestor, RecursiveUnion) &&
4925  ((RecursiveUnion *) ancestor)->wtParam == wtscan->wtParam)
4926  return ancestor;
4927  }
4928  elog(ERROR, "could not find RecursiveUnion for WorkTableScan with wtParam %d",
4929  wtscan->wtParam);
4930  return NULL;
4931 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
#define ERROR
Definition: elog.h:46
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:232

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

Definition at line 11987 of file ruleutils.c.

References buf, StringInfoData::data, elog, ERROR, get_reloptions(), HeapTupleIsValid, initStringInfo(), ObjectIdGetDatum, ReleaseSysCache(), RELOID, SearchSysCache1(), and SysCacheGetAttr().

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

11988 {
11989  char *result = NULL;
11990  HeapTuple tuple;
11991  Datum reloptions;
11992  bool isnull;
11993 
11994  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11995  if (!HeapTupleIsValid(tuple))
11996  elog(ERROR, "cache lookup failed for relation %u", relid);
11997 
11998  reloptions = SysCacheGetAttr(RELOID, tuple,
11999  Anum_pg_class_reloptions, &isnull);
12000  if (!isnull)
12001  {
12003 
12004  initStringInfo(&buf);
12005  get_reloptions(&buf, reloptions);
12006 
12007  result = buf.data;
12008  }
12009 
12010  ReleaseSysCache(tuple);
12011 
12012  return result;
12013 }
static void get_reloptions(StringInfo buf, Datum reloptions)
Definition: ruleutils.c:11931
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static char * buf
Definition: pg_test_fsync.c:68
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

Definition at line 11886 of file ruleutils.c.

References CollationIsVisible(), COLLOID, elog, ERROR, get_namespace_name_or_temp(), 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().

11887 {
11888  HeapTuple tp;
11889  Form_pg_collation colltup;
11890  char *collname;
11891  char *nspname;
11892  char *result;
11893 
11894  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11895  if (!HeapTupleIsValid(tp))
11896  elog(ERROR, "cache lookup failed for collation %u", collid);
11897  colltup = (Form_pg_collation) GETSTRUCT(tp);
11898  collname = NameStr(colltup->collname);
11899 
11900  if (!CollationIsVisible(collid))
11901  nspname = get_namespace_name_or_temp(colltup->collnamespace);
11902  else
11903  nspname = NULL;
11904 
11905  result = quote_qualified_identifier(nspname, collname);
11906 
11907  ReleaseSysCache(tp);
11908 
11909  return result;
11910 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2093
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11458
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:56
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ 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 11600 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_or_temp(), 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().

11603 {
11604  char *result;
11605  HeapTuple proctup;
11606  Form_pg_proc procform;
11607  char *proname;
11608  bool use_variadic;
11609  char *nspname;
11610  FuncDetailCode p_result;
11611  Oid p_funcid;
11612  Oid p_rettype;
11613  bool p_retset;
11614  int p_nvargs;
11615  Oid p_vatype;
11616  Oid *p_true_typeids;
11617  bool force_qualify = false;
11618 
11619  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
11620  if (!HeapTupleIsValid(proctup))
11621  elog(ERROR, "cache lookup failed for function %u", funcid);
11622  procform = (Form_pg_proc) GETSTRUCT(proctup);
11623  proname = NameStr(procform->proname);
11624 
11625  /*
11626  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
11627  * qualification in some special cases.
11628  */
11629  if (special_exprkind == EXPR_KIND_GROUP_BY)
11630  {
11631  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
11632  force_qualify = true;
11633  }
11634 
11635  /*
11636  * Determine whether VARIADIC should be printed. We must do this first
11637  * since it affects the lookup rules in func_get_detail().
11638  *
11639  * We always print VARIADIC if the function has a merged variadic-array
11640  * argument. Note that this is always the case for functions taking a
11641  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
11642  * and printed the array elements as separate arguments, the call could
11643  * match a newer non-VARIADIC function.
11644  */
11645  if (use_variadic_p)
11646  {
11647  /* Parser should not have set funcvariadic unless fn is variadic */
11648  Assert(!has_variadic || OidIsValid(procform->provariadic));
11649  use_variadic = has_variadic;
11650  *use_variadic_p = use_variadic;
11651  }
11652  else
11653  {
11654  Assert(!has_variadic);
11655  use_variadic = false;
11656  }
11657 
11658  /*
11659  * The idea here is to schema-qualify only if the parser would fail to
11660  * resolve the correct function given the unqualified func name with the
11661  * specified argtypes and VARIADIC flag. But if we already decided to
11662  * force qualification, then we can skip the lookup and pretend we didn't
11663  * find it.
11664  */
11665  if (!force_qualify)
11666  p_result = func_get_detail(list_make1(makeString(proname)),
11667  NIL, argnames, nargs, argtypes,
11668  !use_variadic, true, false,
11669  &p_funcid, &p_rettype,
11670  &p_retset, &p_nvargs, &p_vatype,
11671  &p_true_typeids, NULL);
11672  else
11673  {
11674  p_result = FUNCDETAIL_NOTFOUND;
11675  p_funcid = InvalidOid;
11676  }
11677 
11678  if ((p_result == FUNCDETAIL_NORMAL ||
11679  p_result == FUNCDETAIL_AGGREGATE ||
11680  p_result == FUNCDETAIL_WINDOWFUNC) &&
11681  p_funcid == funcid)
11682  nspname = NULL;
11683  else
11684  nspname = get_namespace_name_or_temp(procform->pronamespace);
11685 
11686  result = quote_qualified_identifier(nspname, proname);
11687 
11688  ReleaseSysCache(proctup);
11689 
11690  return result;
11691 }
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:35
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
String * makeString(char *str)
Definition: value.c:51
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define list_make1(x1)
Definition: pg_list.h:206
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11458
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, bool include_out_arguments, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1393
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ generate_opclass_name()

char* generate_opclass_name ( Oid  opclass)

Definition at line 11244 of file ruleutils.c.

References buf, StringInfoData::data, get_opclass_name(), initStringInfo(), and InvalidOid.

Referenced by index_opclass_options().

11245 {
11247 
11248  initStringInfo(&buf);
11249  get_opclass_name(opclass, InvalidOid, &buf);
11250 
11251  return &buf.data[1]; /* get_opclass_name() prepends space */
11252 }
static char * buf
Definition: pg_test_fsync.c:68
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:11206
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define InvalidOid
Definition: postgres_ext.h:36

◆ generate_operator_clause()

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

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

11786 {
11787  HeapTuple opertup;
11788  Form_pg_operator operform;
11789  char *oprname;
11790  char *nspname;
11791 
11792  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11793  if (!HeapTupleIsValid(opertup))
11794  elog(ERROR, "cache lookup failed for operator %u", opoid);
11795  operform = (Form_pg_operator) GETSTRUCT(opertup);
11796  Assert(operform->oprkind == 'b');
11797  oprname = NameStr(operform->oprname);
11798 
11799  nspname = get_namespace_name(operform->oprnamespace);
11800 
11801  appendStringInfoString(buf, leftop);
11802  if (leftoptype != operform->oprleft)
11803  add_cast_to(buf, operform->oprleft);
11804  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11805  appendStringInfoString(buf, oprname);
11806  appendStringInfo(buf, ") %s", rightop);
11807  if (rightoptype != operform->oprright)
11808  add_cast_to(buf, operform->oprright);
11809 
11810  ReleaseSysCache(opertup);
11811 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11822
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ generate_operator_name()

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

Definition at line 11705 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, StringInfoData::data, elog, ERROR, get_namespace_name_or_temp(), GETSTRUCT, HeapTupleIsValid, initStringInfo(), left_oper(), list_make1, makeString(), NameStr, ObjectIdGetDatum, oper(), OPEROID, oprid(), quote_identifier(), ReleaseSysCache(), 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().

11706 {
11708  HeapTuple opertup;
11709  Form_pg_operator operform;
11710  char *oprname;
11711  char *nspname;
11712  Operator p_result;
11713 
11714  initStringInfo(&buf);
11715 
11716  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11717  if (!HeapTupleIsValid(opertup))
11718  elog(ERROR, "cache lookup failed for operator %u", operid);
11719  operform = (Form_pg_operator) GETSTRUCT(opertup);
11720  oprname = NameStr(operform->oprname);
11721 
11722  /*
11723  * The idea here is to schema-qualify only if the parser would fail to
11724  * resolve the correct operator given the unqualified op name with the
11725  * specified argtypes.
11726  */
11727  switch (operform->oprkind)
11728  {
11729  case 'b':
11730  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11731  true, -1);
11732  break;
11733  case 'l':
11734  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11735  true, -1);
11736  break;
11737  default:
11738  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11739  p_result = NULL; /* keep compiler quiet */
11740  break;
11741  }
11742 
11743  if (p_result != NULL && oprid(p_result) == operid)
11744  nspname = NULL;
11745  else
11746  {
11747  nspname = get_namespace_name_or_temp(operform->oprnamespace);
11748  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11749  }
11750 
11751  appendStringInfoString(&buf, oprname);
11752 
11753  if (nspname)
11754  appendStringInfoChar(&buf, ')');
11755 
11756  if (p_result != NULL)
11757  ReleaseSysCache(p_result);
11758 
11759  ReleaseSysCache(opertup);
11760 
11761  return buf.data;
11762 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
Oid oprid(Operator op)
Definition: parse_oper.c:250
String * makeString(char *str)
Definition: value.c:51
#define list_make1(x1)
Definition: pg_list.h:206
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:530
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:382

◆ generate_qualified_relation_name()

static char * generate_qualified_relation_name ( Oid  relid)
static

Definition at line 11558 of file ruleutils.c.

References elog, ERROR, get_namespace_name_or_temp(), 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().

11559 {
11560  HeapTuple tp;
11561  Form_pg_class reltup;
11562  char *relname;
11563  char *nspname;
11564  char *result;
11565 
11566  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11567  if (!HeapTupleIsValid(tp))
11568  elog(ERROR, "cache lookup failed for relation %u", relid);
11569  reltup = (Form_pg_class) GETSTRUCT(tp);
11570  relname = NameStr(reltup->relname);
11571 
11572  nspname = get_namespace_name_or_temp(reltup->relnamespace);
11573  if (!nspname)
11574  elog(ERROR, "cache lookup failed for namespace %u",
11575  reltup->relnamespace);
11576 
11577  result = quote_qualified_identifier(nspname, relname);
11578 
11579  ReleaseSysCache(tp);
11580 
11581  return result;
11582 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
NameData relname
Definition: pg_class.h:38
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11458
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

Definition at line 11853 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

11854 {
11855  HeapTuple tp;
11856  Form_pg_type typtup;
11857  char *typname;
11858  char *nspname;
11859  char *result;
11860 
11862  if (!HeapTupleIsValid(tp))
11863  elog(ERROR, "cache lookup failed for type %u", typid);
11864  typtup = (Form_pg_type) GETSTRUCT(tp);
11865  typname = NameStr(typtup->typname);
11866 
11867  nspname = get_namespace_name_or_temp(typtup->typnamespace);
11868  if (!nspname)
11869  elog(ERROR, "cache lookup failed for namespace %u",
11870  typtup->typnamespace);
11871 
11872  result = quote_qualified_identifier(nspname, typname);
11873 
11874  ReleaseSysCache(tp);
11875 
11876  return result;
11877 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
NameData typname
Definition: pg_type.h:41
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11458
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ generate_relation_name()

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

Definition at line 11498 of file ruleutils.c.

References CommonTableExpr::ctename, deparse_namespace::ctes, elog, ERROR, get_namespace_name_or_temp(), 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().

11499 {
11500  HeapTuple tp;
11501  Form_pg_class reltup;
11502  bool need_qual;
11503  ListCell *nslist;
11504  char *relname;
11505  char *nspname;
11506  char *result;
11507 
11508  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11509  if (!HeapTupleIsValid(tp))
11510  elog(ERROR, "cache lookup failed for relation %u", relid);
11511  reltup = (Form_pg_class) GETSTRUCT(tp);
11512  relname = NameStr(reltup->relname);
11513 
11514  /* Check for conflicting CTE name */
11515  need_qual = false;
11516  foreach(nslist, namespaces)
11517  {
11518  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
11519  ListCell *ctlist;
11520 
11521  foreach(ctlist, dpns->ctes)
11522  {
11523  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
11524 
11525  if (strcmp(cte->ctename, relname) == 0)
11526  {
11527  need_qual = true;
11528  break;
11529  }
11530  }
11531  if (need_qual)
11532  break;
11533  }
11534 
11535  /* Otherwise, qualify the name if not visible in search path */
11536  if (!need_qual)
11537  need_qual = !RelationIsVisible(relid);
11538 
11539  if (need_qual)
11540  nspname = get_namespace_name_or_temp(reltup->relnamespace);
11541  else
11542  nspname = NULL;
11543 
11544  result = quote_qualified_identifier(nspname, relname);
11545 
11546  ReleaseSysCache(tp);
11547 
11548  return result;
11549 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
NameData relname
Definition: pg_class.h:38
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11458
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
bool RelationIsVisible(Oid relid)
Definition: namespace.c:709
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681

◆ get_agg_combine_expr()

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

Definition at line 9834 of file ruleutils.c.

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

Referenced by get_agg_expr().

9835 {
9836  Aggref *aggref;
9837  Aggref *original_aggref = callback_arg;
9838 
9839  if (!IsA(node, Aggref))
9840  elog(ERROR, "combining Aggref does not point to an Aggref");
9841 
9842  aggref = (Aggref *) node;
9843  get_agg_expr(aggref, context, original_aggref);
9844 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
#define ERROR
Definition: elog.h:46
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9727
#define elog(elevel,...)
Definition: elog.h:232

◆ get_agg_expr()

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

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

9729 {
9730  StringInfo buf = context->buf;
9731  Oid argtypes[FUNC_MAX_ARGS];
9732  int nargs;
9733  bool use_variadic;
9734 
9735  /*
9736  * For a combining aggregate, we look up and deparse the corresponding
9737  * partial aggregate instead. This is necessary because our input
9738  * argument list has been replaced; the new argument list always has just
9739  * one element, which will point to a partial Aggref that supplies us with
9740  * transition states to combine.
9741  */
9742  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9743  {
9744  TargetEntry *tle;
9745 
9746  Assert(list_length(aggref->args) == 1);
9747  tle = linitial_node(TargetEntry, aggref->args);
9748  resolve_special_varno((Node *) tle->expr, context,
9749  get_agg_combine_expr, original_aggref);
9750  return;
9751  }
9752 
9753  /*
9754  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9755  * to avoid printing this when recursing from the code just above.
9756  */
9757  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9758  appendStringInfoString(buf, "PARTIAL ");
9759 
9760  /* Extract the argument types as seen by the parser */
9761  nargs = get_aggregate_argtypes(aggref, argtypes);
9762 
9763  /* Print the aggregate name, schema-qualified if needed */
9764  appendStringInfo(buf, "%s(%s",
9765  generate_function_name(aggref->aggfnoid, nargs,
9766  NIL, argtypes,
9767  aggref->aggvariadic,
9768  &use_variadic,
9769  context->special_exprkind),
9770  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9771 
9772  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9773  {
9774  /*
9775  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9776  * worry about inserting VARIADIC. So we can just dump the direct
9777  * args as-is.
9778  */
9779  Assert(!aggref->aggvariadic);
9780  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9781  Assert(aggref->aggorder != NIL);
9782  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9783  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9784  }
9785  else
9786  {
9787  /* aggstar can be set only in zero-argument aggregates */
9788  if (aggref->aggstar)
9789  appendStringInfoChar(buf, '*');
9790  else
9791  {
9792  ListCell *l;
9793  int i;
9794 
9795  i = 0;
9796  foreach(l, aggref->args)
9797  {
9798  TargetEntry *tle = (TargetEntry *) lfirst(l);
9799  Node *arg = (Node *) tle->expr;
9800 
9801  Assert(!IsA(arg, NamedArgExpr));
9802  if (tle->resjunk)
9803  continue;
9804  if (i++ > 0)
9805  appendStringInfoString(buf, ", ");
9806  if (use_variadic && i == nargs)
9807  appendStringInfoString(buf, "VARIADIC ");
9808  get_rule_expr(arg, context, true);
9809  }
9810  }
9811 
9812  if (aggref->aggorder != NIL)
9813  {
9814  appendStringInfoString(buf, " ORDER BY ");
9815  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9816  }
9817  }
9818 
9819  if (aggref->aggfilter != NULL)
9820  {
9821  appendStringInfoString(buf, ") FILTER (WHERE ");
9822  get_rule_expr((Node *) aggref->aggfilter, context, false);
9823  }
9824 
9825  appendStringInfoChar(buf, ')');
9826 }
static void resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
Definition: ruleutils.c:7224
List * aggdistinct
Definition: primnodes.h:332
#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:11600
bool aggvariadic
Definition: primnodes.h:335
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6261
Definition: nodes.h:537
List * args
Definition: primnodes.h:330
bool aggstar
Definition: primnodes.h:334
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:177
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:800
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1462
static void get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:9834
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
List * aggorder
Definition: primnodes.h:331
List * aggdirectargs
Definition: primnodes.h:329
ParseExprKind special_exprkind
Definition: ruleutils.c:118
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
Oid aggfnoid
Definition: primnodes.h:323
#define Assert(condition)
Definition: c.h:804
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
AggSplit aggsplit
Definition: primnodes.h:339
static int list_length(const List *l)
Definition: pg_list.h:149
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:801
Expr * aggfilter
Definition: primnodes.h:333
StringInfo buf
Definition: ruleutils.c:110
int i
void * arg
char aggkind
Definition: primnodes.h:337
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1880

◆ get_basic_select_query()

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

Definition at line 5749 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::groupDistinct, Query::groupingSets, Query::hasDistinctOn, Query::havingQual, deparse_context::indentLevel, Query::isReturn, 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().

5751 {
5752  StringInfo buf = context->buf;
5753  RangeTblEntry *values_rte;
5754  char *sep;
5755  ListCell *l;
5756 
5757  if (PRETTY_INDENT(context))
5758  {
5759  context->indentLevel += PRETTYINDENT_STD;
5760  appendStringInfoChar(buf, ' ');
5761  }
5762 
5763  /*
5764  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5765  * VALUES part. This reverses what transformValuesClause() did at parse
5766  * time.
5767  */
5768  values_rte = get_simple_values_rte(query, resultDesc);
5769  if (values_rte)
5770  {
5771  get_values_def(values_rte->values_lists, context);
5772  return;
5773  }
5774 
5775  /*
5776  * Build up the query string - first we say SELECT
5777  */
5778  if (query->isReturn)
5779  appendStringInfoString(buf, "RETURN");
5780  else
5781  appendStringInfoString(buf, "SELECT");
5782 
5783  /* Add the DISTINCT clause if given */
5784  if (query->distinctClause != NIL)
5785  {
5786  if (query->hasDistinctOn)
5787  {
5788  appendStringInfoString(buf, " DISTINCT ON (");
5789  sep = "";
5790  foreach(l, query->distinctClause)
5791  {
5792  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5793 
5794  appendStringInfoString(buf, sep);
5796  false, context);
5797  sep = ", ";
5798  }
5799  appendStringInfoChar(buf, ')');
5800  }
5801  else
5802  appendStringInfoString(buf, " DISTINCT");
5803  }
5804 
5805  /* Then we tell what to select (the targetlist) */
5806  get_target_list(query->targetList, context, resultDesc);
5807 
5808  /* Add the FROM clause if needed */
5809  get_from_clause(query, " FROM ", context);
5810 
5811  /* Add the WHERE clause if given */
5812  if (query->jointree->quals != NULL)
5813  {
5814  appendContextKeyword(context, " WHERE ",
5816  get_rule_expr(query->jointree->quals, context, false);
5817  }
5818 
5819  /* Add the GROUP BY clause if given */
5820  if (query->groupClause != NULL || query->groupingSets != NULL)
5821  {
5822  ParseExprKind save_exprkind;
5823 
5824  appendContextKeyword(context, " GROUP BY ",
5826  if (query->groupDistinct)
5827  appendStringInfoString(buf, "DISTINCT ");
5828 
5829  save_exprkind = context->special_exprkind;
5831 
5832  if (query->groupingSets == NIL)
5833  {
5834  sep = "";
5835  foreach(l, query->groupClause)
5836  {
5837  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5838 
5839  appendStringInfoString(buf, sep);
5841  false, context);
5842  sep = ", ";
5843  }
5844  }
5845  else
5846  {
5847  sep = "";
5848  foreach(l, query->groupingSets)
5849  {
5850  GroupingSet *grp = lfirst(l);
5851 
5852  appendStringInfoString(buf, sep);
5853  get_rule_groupingset(grp, query->targetList, true, context);
5854  sep = ", ";
5855  }
5856  }
5857 
5858  context->special_exprkind = save_exprkind;
5859  }
5860 
5861  /* Add the HAVING clause if given */
5862  if (query->havingQual != NULL)
5863  {
5864  appendContextKeyword(context, " HAVING ",
5866  get_rule_expr(query->havingQual, context, false);
5867  }
5868 
5869  /* Add the WINDOW clause if needed */
5870  if (query->windowClause != NIL)
5871  get_rule_windowclause(query, context);
5872 }
#define NIL
Definition: pg_list.h:65
FromExpr * jointree
Definition: parsenodes.h:148
bool groupDistinct
Definition: parsenodes.h:159
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5881
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6145
Index tleSortGroupRef
Definition: parsenodes.h:1295
List * groupingSets
Definition: parsenodes.h:161
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10638
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:6319
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
ParseExprKind
Definition: parse_node.h:38
List * values_lists
Definition: parsenodes.h:1112
Node * quals
Definition: primnodes.h:1565
bool hasDistinctOn
Definition: parsenodes.h:137
List * windowClause
Definition: parsenodes.h:165
List * targetList
Definition: parsenodes.h:150
List * distinctClause
Definition: parsenodes.h:167
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
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:8215
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5680
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:6201
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
ParseExprKind special_exprkind
Definition: ruleutils.c:118
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
bool isReturn
Definition: parsenodes.h:143
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfirst(lc)
Definition: pg_list.h:169
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5368
List * groupClause
Definition: parsenodes.h:158
StringInfo buf
Definition: ruleutils.c:110
Node * havingQual
Definition: parsenodes.h:163

◆ get_coercion_expr()

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

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

10170 {
10171  StringInfo buf = context->buf;
10172 
10173  /*
10174  * Since parse_coerce.c doesn't immediately collapse application of
10175  * length-coercion functions to constants, what we'll typically see in
10176  * such cases is a Const with typmod -1 and a length-coercion function
10177  * right above it. Avoid generating redundant output. However, beware of
10178  * suppressing casts when the user actually wrote something like
10179  * 'foo'::text::char(3).
10180  *
10181  * Note: it might seem that we are missing the possibility of needing to
10182  * print a COLLATE clause for such a Const. However, a Const could only
10183  * have nondefault collation in a post-constant-folding tree, in which the
10184  * length coercion would have been folded too. See also the special
10185  * handling of CollateExpr in coerce_to_target_type(): any collation
10186  * marking will be above the coercion node, not below it.
10187  */
10188  if (arg && IsA(arg, Const) &&
10189  ((Const *) arg)->consttype == resulttype &&
10190  ((Const *) arg)->consttypmod == -1)
10191  {
10192  /* Show the constant without normal ::typename decoration */
10193  get_const_expr((Const *) arg, context, -1);
10194  }
10195  else
10196  {
10197  if (!PRETTY_PAREN(context))
10198  appendStringInfoChar(buf, '(');
10199  get_rule_expr_paren(arg, context, false, parentNode);
10200  if (!PRETTY_PAREN(context))
10201  appendStringInfoChar(buf, ')');
10202  }
10203 
10204  /*
10205  * Never emit resulttype(arg) functional notation. A pg_proc entry could
10206  * take precedence, and a resulttype in pg_temp would require schema
10207  * qualification that format_type_with_typemod() would usually omit. We've
10208  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
10209  * would work fine.
10210  */
10211  appendStringInfo(buf, "::%s",
10212  format_type_with_typemod(resulttype, resulttypmod));
10213 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8288
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:10231
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:97
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:358
StringInfo buf
Definition: ruleutils.c:110

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

11072 {
11073  StringInfo buf = context->buf;
11074  int i;
11075  bool first = true;
11076 
11077  /* Don't print aliases if not needed */
11078  if (!colinfo->printaliases)
11079  return;
11080 
11081  for (i = 0; i < colinfo->num_new_cols; i++)
11082  {
11083  char *colname = colinfo->new_colnames[i];
11084 
11085  if (first)
11086  {
11087  appendStringInfoChar(buf, '(');
11088  first = false;
11089  }
11090  else
11091  appendStringInfoString(buf, ", ");
11093  }
11094  if (!first)
11095  appendStringInfoChar(buf, ')');
11096 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
StringInfo buf
Definition: ruleutils.c:110
int i
char ** new_colnames
Definition: ruleutils.c:257

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

10362 {
10363  StringInfo buf = context->buf;
10364 
10365  if (OidIsValid(constval->constcollid))
10366  {
10367  Oid typcollation = get_typcollation(constval->consttype);
10368 
10369  if (constval->constcollid != typcollation)
10370  {
10371  appendStringInfo(buf, " COLLATE %s",
10373  }
10374  }
10375 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11886
Oid consttype
Definition: primnodes.h:215
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
Oid constcollid
Definition: primnodes.h:217
static char * buf
Definition: pg_test_fsync.c:68
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:3003
StringInfo buf
Definition: ruleutils.c:110

◆ get_const_expr()

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

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

10232 {
10233  StringInfo buf = context->buf;
10234  Oid typoutput;
10235  bool typIsVarlena;
10236  char *extval;
10237  bool needlabel = false;
10238 
10239  if (constval->constisnull)
10240  {
10241  /*
10242  * Always label the type of a NULL constant to prevent misdecisions
10243  * about type when reparsing.
10244  */
10245  appendStringInfoString(buf, "NULL");
10246  if (showtype >= 0)
10247  {
10248  appendStringInfo(buf, "::%s",
10250  constval->consttypmod));
10251  get_const_collation(constval, context);
10252  }
10253  return;
10254  }
10255 
10256  getTypeOutputInfo(constval->consttype,
10257  &typoutput, &typIsVarlena);
10258 
10259  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
10260 
10261  switch (constval->consttype)
10262  {
10263  case INT4OID:
10264 
10265  /*
10266  * INT4 can be printed without any decoration, unless it is
10267  * negative; in that case print it as '-nnn'::integer to ensure
10268  * that the output will re-parse as a constant, not as a constant
10269  * plus operator. In most cases we could get away with printing
10270  * (-nnn) instead, because of the way that gram.y handles negative
10271  * literals; but that doesn't work for INT_MIN, and it doesn't
10272  * seem that much prettier anyway.
10273  */
10274  if (extval[0] != '-')
10275  appendStringInfoString(buf, extval);
10276  else
10277  {
10278  appendStringInfo(buf, "'%s'", extval);
10279  needlabel = true; /* we must attach a cast */
10280  }
10281  break;
10282 
10283  case NUMERICOID:
10284 
10285  /*
10286  * NUMERIC can be printed without quotes if it looks like a float
10287  * constant (not an integer, and not Infinity or NaN) and doesn't
10288  * have a leading sign (for the same reason as for INT4).
10289  */
10290  if (isdigit((unsigned char) extval[0]) &&
10291  strcspn(extval, "eE.") != strlen(extval))
10292  {
10293  appendStringInfoString(buf, extval);
10294  }
10295  else
10296  {
10297  appendStringInfo(buf, "'%s'", extval);
10298  needlabel = true; /* we must attach a cast */
10299  }
10300  break;
10301 
10302  case BOOLOID:
10303  if (strcmp(extval, "t") == 0)
10304  appendStringInfoString(buf, "true");
10305  else
10306  appendStringInfoString(buf, "false");
10307  break;
10308 
10309  default:
10310  simple_quote_literal(buf, extval);
10311  break;
10312  }
10313 
10314  pfree(extval);
10315 
10316  if (showtype < 0)
10317  return;
10318 
10319  /*
10320  * For showtype == 0, append ::typename unless the constant will be
10321  * implicitly typed as the right type when it is read in.
10322  *
10323  * XXX this code has to be kept in sync with the behavior of the parser,
10324  * especially make_const.
10325  */
10326  switch (constval->consttype)
10327  {
10328  case BOOLOID:
10329  case UNKNOWNOID:
10330  /* These types can be left unlabeled */
10331  needlabel = false;
10332  break;
10333  case INT4OID:
10334  /* We determined above whether a label is needed */
10335  break;
10336  case NUMERICOID:
10337 
10338  /*
10339  * Float-looking constants will be typed as numeric, which we
10340  * checked above; but if there's a nondefault typmod we need to
10341  * show it.
10342  */
10343  needlabel |= (constval->consttypmod >= 0);
10344  break;
10345  default:
10346  needlabel = true;
10347  break;
10348  }
10349  if (needlabel || showtype > 0)
10350  appendStringInfo(buf, "::%s",
10352  constval->consttypmod));
10353 
10354  get_const_collation(constval, context);
10355 }
Datum constvalue
Definition: primnodes.h:219
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2854
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:215
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:10381
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:10361
static char * buf
Definition: pg_test_fsync.c:68
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:358
int32 consttypmod
Definition: primnodes.h:216
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1653
StringInfo buf
Definition: ruleutils.c:110
bool constisnull
Definition: primnodes.h:220

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6881 {
6882  StringInfo buf = context->buf;
6883  RangeTblEntry *rte;
6884 
6885  /* Insert the WITH clause if given */
6886  get_with_clause(query, context);
6887 
6888  /*
6889  * Start the query with DELETE FROM relname
6890  */
6891  rte = rt_fetch(query->resultRelation, query->rtable);
6892  Assert(rte->rtekind == RTE_RELATION);
6893  if (PRETTY_INDENT(context))
6894  {
6895  appendStringInfoChar(buf, ' ');
6896  context->indentLevel += PRETTYINDENT_STD;
6897  }
6898  appendStringInfo(buf, "DELETE FROM %s%s",
6899  only_marker(rte),
6901  if (rte->alias != NULL)
6902  appendStringInfo(buf, " %s",
6904 
6905  /* Add the USING clause if given */
6906  get_from_clause(query, " USING ", context);
6907 
6908  /* Add a WHERE clause if given */
6909  if (query->jointree->quals != NULL)
6910  {
6911  appendContextKeyword(context, " WHERE ",
6913  get_rule_expr(query->jointree->quals, context, false);
6914  }
6915 
6916  /* Add RETURNING if present */
6917  if (query->returningList)
6918  {
6919  appendContextKeyword(context, " RETURNING",
6921  get_target_list(query->returningList, context, NULL);
6922  }
6923 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5411
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
Alias * alias
Definition: parsenodes.h:1152
FromExpr * jointree
Definition: parsenodes.h:148
int resultRelation
Definition: parsenodes.h:130
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5881
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10638
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
Node * quals
Definition: primnodes.h:1565
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11498
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
List * rtable
Definition: parsenodes.h:147
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:8215
List * returningList
Definition: parsenodes.h:156
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define Assert(condition)
Definition: c.h:804
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:492
RTEKind rtekind
Definition: parsenodes.h:1007
StringInfo buf
Definition: ruleutils.c:110

◆ get_from_clause()

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

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

10639 {
10640  StringInfo buf = context->buf;
10641  bool first = true;
10642  ListCell *l;
10643 
10644  /*
10645  * We use the query's jointree as a guide to what to print. However, we
10646  * must ignore auto-added RTEs that are marked not inFromCl. (These can
10647  * only appear at the top level of the jointree, so it's sufficient to
10648  * check here.) This check also ensures we ignore the rule pseudo-RTEs
10649  * for NEW and OLD.
10650  */
10651  foreach(l, query->jointree->fromlist)
10652  {
10653  Node *jtnode = (Node *) lfirst(l);
10654 
10655  if (IsA(jtnode, RangeTblRef))
10656  {
10657  int varno = ((RangeTblRef *) jtnode)->rtindex;
10658  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10659 
10660  if (!rte->inFromCl)
10661  continue;
10662  }
10663 
10664  if (first)
10665  {
10666  appendContextKeyword(context, prefix,
10668  first = false;
10669 
10670  get_from_clause_item(jtnode, query, context);
10671  }
10672  else
10673  {
10674  StringInfoData itembuf;
10675 
10676  appendStringInfoString(buf, ", ");
10677 
10678  /*
10679  * Put the new FROM item's text into itembuf so we can decide
10680  * after we've got it whether or not it needs to go on a new line.
10681  */
10682  initStringInfo(&itembuf);
10683  context->buf = &itembuf;
10684 
10685  get_from_clause_item(jtnode, query, context);
10686 
10687  /* Restore context's output buffer */
10688  context->buf = buf;
10689 
10690  /* Consider line-wrapping if enabled */
10691  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10692  {
10693  /* Does the new item start with a new line? */
10694  if (itembuf.len > 0 && itembuf.data[0] == '\n')
10695  {
10696  /* If so, we shouldn't add anything */
10697  /* instead, remove any trailing spaces currently in buf */
10699  }
10700  else
10701  {
10702  char *trailing_nl;
10703 
10704  /* Locate the start of the current line in the buffer */
10705  trailing_nl = strrchr(buf->data, '\n');
10706  if (trailing_nl == NULL)
10707  trailing_nl = buf->data;
10708  else
10709  trailing_nl++;
10710 
10711  /*
10712  * Add a newline, plus some indentation, if the new item
10713  * would cause an overflow.
10714  */
10715  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10716  appendContextKeyword(context, "", -PRETTYINDENT_STD,
10719  }
10720  }
10721 
10722  /* Add the new item */
10723  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10724 
10725  /* clean up */
10726  pfree(itembuf.data);
10727  }
10728  }
10729 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
FromExpr * jointree
Definition: parsenodes.h:148
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
Definition: nodes.h:537
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
List * fromlist
Definition: primnodes.h:1564
void pfree(void *pointer)
Definition: mcxt.c:1169
List * rtable
Definition: parsenodes.h:147
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
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:8215
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:8269
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define lfirst(lc)
Definition: pg_list.h:169
StringInfo buf
Definition: ruleutils.c:110
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10732

◆ get_from_clause_coldeflist()

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

Definition at line 11111 of file ruleutils.c.

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

11114 {
11115  StringInfo buf = context->buf;
11116  ListCell *l1;
11117  ListCell *l2;
11118  ListCell *l3;
11119  ListCell *l4;
11120  int i;
11121 
11122  appendStringInfoChar(buf, '(');
11123 
11124  i = 0;
11125  forfour(l1, rtfunc->funccoltypes,
11126  l2, rtfunc->funccoltypmods,
11127  l3, rtfunc->funccolcollations,
11128  l4, rtfunc->funccolnames)
11129  {
11130  Oid atttypid = lfirst_oid(l1);
11131  int32 atttypmod = lfirst_int(l2);
11132  Oid attcollation = lfirst_oid(l3);
11133  char *attname;
11134 
11135  if (colinfo)
11136  attname = colinfo->colnames[i];
11137  else
11138  attname = strVal(lfirst(l4));
11139 
11140  Assert(attname); /* shouldn't be any dropped columns here */
11141 
11142  if (i > 0)
11143  appendStringInfoString(buf, ", ");
11144  appendStringInfo(buf, "%s %s",
11145  quote_identifier(attname),
11146  format_type_with_typemod(atttypid, atttypmod));
11147  if (OidIsValid(attcollation) &&
11148  attcollation != get_typcollation(atttypid))
11149  appendStringInfo(buf, " COLLATE %s",
11150  generate_collation_name(attcollation));
11151 
11152  i++;
11153  }
11154 
11155  appendStringInfoChar(buf, ')');
11156 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
#define strVal(v)
Definition: value.h:65
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11886
signed int int32
Definition: c.h:429
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
NameData attname
Definition: pg_attribute.h:41
#define lfirst_int(lc)
Definition: pg_list.h:170
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:358
List * funccoltypmods
Definition: parsenodes.h:1191
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:3003
List * funccolcollations
Definition: parsenodes.h:1192
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:503
StringInfo buf
Definition: ruleutils.c:110
int i
#define lfirst_oid(lc)
Definition: pg_list.h:171
char ** colnames
Definition: ruleutils.c:240

◆ get_from_clause_item()

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

Definition at line 10732 of file ruleutils.c.

References RangeTblEntry::alias, JoinExpr::alias, Alias::aliasname, appendContextKeyword(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), generate_unaccent_rules::args, buf, deparse_context::buf, RangeTblEntry::ctename, deparse_columns_fetch, elog, ERROR, RangeTblFunction::funccolnames, RangeTblFunction::funcexpr, RangeTblEntry::funcordinality, RangeTblEntry::functions, generate_relation_name(), get_column_alias_list(), get_from_clause_coldeflist(), get_query_def(), get_relation_name(), get_rtable_name(), get_rule_expr(), get_rule_expr_funccall(), get_tablefunc(), get_tablesample_def(), get_values_def(), deparse_context::indentLevel, IsA, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JoinExpr::join_using_alias, 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().

10733 {
10734  StringInfo buf = context->buf;
10736 
10737  if (IsA(jtnode, RangeTblRef))
10738  {
10739  int varno = ((RangeTblRef *) jtnode)->rtindex;
10740  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10741  char *refname = get_rtable_name(varno, context);
10742  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10743  RangeTblFunction *rtfunc1 = NULL;
10744  bool printalias;
10745 
10746  if (rte->lateral)
10747  appendStringInfoString(buf, "LATERAL ");
10748 
10749  /* Print the FROM item proper */
10750  switch (rte->rtekind)
10751  {
10752  case RTE_RELATION:
10753  /* Normal relation RTE */
10754  appendStringInfo(buf, "%s%s",
10755  only_marker(rte),
10757  context->namespaces));
10758  break;
10759  case RTE_SUBQUERY:
10760  /* Subquery RTE */
10761  appendStringInfoChar(buf, '(');
10762  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10763  context->prettyFlags, context->wrapColumn,
10764  context->indentLevel);
10765  appendStringInfoChar(buf, ')');
10766  break;
10767  case RTE_FUNCTION:
10768  /* Function RTE */
10769  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10770 
10771  /*
10772  * Omit ROWS FROM() syntax for just one function, unless it
10773  * has both a coldeflist and WITH ORDINALITY. If it has both,
10774  * we must use ROWS FROM() syntax to avoid ambiguity about
10775  * whether the coldeflist includes the ordinality column.
10776  */
10777  if (list_length(rte->functions) == 1 &&
10778  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10779  {
10780  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10781  /* we'll print the coldeflist below, if it has one */
10782  }
10783  else
10784  {
10785  bool all_unnest;
10786  ListCell *lc;
10787 
10788  /*
10789  * If all the function calls in the list are to unnest,
10790  * and none need a coldeflist, then collapse the list back
10791  * down to UNNEST(args). (If we had more than one
10792  * built-in unnest function, this would get more
10793  * difficult.)
10794  *
10795  * XXX This is pretty ugly, since it makes not-terribly-
10796  * future-proof assumptions about what the parser would do
10797  * with the output; but the alternative is to emit our
10798  * nonstandard ROWS FROM() notation for what might have
10799  * been a perfectly spec-compliant multi-argument
10800  * UNNEST().
10801  */
10802  all_unnest = true;
10803  foreach(lc, rte->functions)
10804  {
10805  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10806 
10807  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10808  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
10809  rtfunc->funccolnames != NIL)
10810  {
10811  all_unnest = false;
10812  break;
10813  }
10814  }
10815 
10816  if (all_unnest)
10817  {
10818  List *allargs = NIL;
10819 
10820  foreach(lc, rte->functions)
10821  {
10822  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10823  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10824 
10825  allargs = list_concat(allargs, args);
10826  }
10827 
10828  appendStringInfoString(buf, "UNNEST(");
10829  get_rule_expr((Node *) allargs, context, true);
10830  appendStringInfoChar(buf, ')');
10831  }
10832  else
10833  {
10834  int funcno = 0;
10835 
10836  appendStringInfoString(buf, "ROWS FROM(");
10837  foreach(lc, rte->functions)
10838  {
10839  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10840 
10841  if (funcno > 0)
10842  appendStringInfoString(buf, ", ");
10843  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10844  if (rtfunc->funccolnames != NIL)
10845  {
10846  /* Reconstruct the column definition list */
10847  appendStringInfoString(buf, " AS ");
10849  NULL,
10850  context);
10851  }
10852  funcno++;
10853  }
10854  appendStringInfoChar(buf, ')');
10855  }
10856  /* prevent printing duplicate coldeflist below */
10857  rtfunc1 = NULL;
10858  }
10859  if (rte->funcordinality)
10860  appendStringInfoString(buf, " WITH ORDINALITY");
10861  break;
10862  case RTE_TABLEFUNC:
10863  get_tablefunc(rte->tablefunc, context, true);
10864  break;
10865  case RTE_VALUES:
10866  /* Values list RTE */
10867  appendStringInfoChar(buf, '(');
10868  get_values_def(rte->values_lists, context);
10869  appendStringInfoChar(buf, ')');
10870  break;
10871  case RTE_CTE:
10873  break;
10874  default:
10875  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10876  break;
10877  }
10878 
10879  /* Print the relation alias, if needed */
10880  printalias = false;
10881  if (rte->alias != NULL)
10882  {
10883  /* Always print alias if user provided one */
10884  printalias = true;
10885  }
10886  else if (colinfo->printaliases)
10887  {
10888  /* Always print alias if we need to print column aliases */
10889  printalias = true;
10890  }
10891  else if (rte->rtekind == RTE_RELATION)
10892  {
10893  /*
10894  * No need to print alias if it's same as relation name (this
10895  * would normally be the case, but not if set_rtable_names had to
10896  * resolve a conflict).
10897  */
10898  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10899  printalias = true;
10900  }
10901  else if (rte->rtekind == RTE_FUNCTION)
10902  {
10903  /*
10904  * For a function RTE, always print alias. This covers possible
10905  * renaming of the function and/or instability of the
10906  * FigureColname rules for things that aren't simple functions.
10907  * Note we'd need to force it anyway for the columndef list case.
10908  */
10909  printalias = true;
10910  }
10911  else if (rte->rtekind == RTE_VALUES)
10912  {
10913  /* Alias is syntactically required for VALUES */
10914  printalias = true;
10915  }
10916  else if (rte->rtekind == RTE_CTE)
10917  {
10918  /*
10919  * No need to print alias if it's same as CTE name (this would
10920  * normally be the case, but not if set_rtable_names had to
10921  * resolve a conflict).
10922  */
10923  if (strcmp(refname, rte->ctename) != 0)
10924  printalias = true;
10925  }
10926  if (printalias)
10927  appendStringInfo(buf, " %s", quote_identifier(refname));
10928 
10929  /* Print the column definitions or aliases, if needed */
10930  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10931  {
10932  /* Reconstruct the columndef list, which is also the aliases */
10933  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10934  }
10935  else
10936  {
10937  /* Else print column aliases as needed */
10938  get_column_alias_list(colinfo, context);
10939  }
10940 
10941  /* Tablesample clause must go after any alias */
10942  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10943  get_tablesample_def(rte->tablesample, context);
10944  }
10945  else if (IsA(jtnode, JoinExpr))
10946  {
10947  JoinExpr *j = (JoinExpr *) jtnode;
10948  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10949  bool need_paren_on_right;
10950 
10951  need_paren_on_right = PRETTY_PAREN(context) &&
10952  !IsA(j->rarg, RangeTblRef) &&
10953  !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
10954 
10955  if (!PRETTY_PAREN(context) || j->alias != NULL)
10956  appendStringInfoChar(buf, '(');
10957 
10958  get_from_clause_item(j->larg, query, context);
10959 
10960  switch (j->jointype)
10961  {
10962  case JOIN_INNER:
10963  if (j->quals)
10964  appendContextKeyword(context, " JOIN ",
10968  else
10969  appendContextKeyword(context, " CROSS JOIN ",
10973  break;
10974  case JOIN_LEFT:
10975  appendContextKeyword(context, " LEFT JOIN ",
10979  break;
10980  case JOIN_FULL:
10981  appendContextKeyword(context, " FULL JOIN ",
10985  break;
10986  case JOIN_RIGHT:
10987  appendContextKeyword(context, " RIGHT JOIN ",
10991  break;
10992  default:
10993  elog(ERROR, "unrecognized join type: %d",
10994  (int) j->jointype);
10995  }
10996 
10997  if (need_paren_on_right)
10998  appendStringInfoChar(buf, '(');
10999  get_from_clause_item(j->rarg, query, context);
11000  if (need_paren_on_right)
11001  appendStringInfoChar(buf, ')');
11002 
11003  if (j->usingClause)
11004  {
11005  ListCell *lc;
11006  bool first = true;
11007 
11008  appendStringInfoString(buf, " USING (");
11009  /* Use the assigned names, not what's in usingClause */
11010  foreach(lc, colinfo->usingNames)
11011  {
11012  char *colname = (char *) lfirst(lc);
11013 
11014  if (first)
11015  first = false;
11016  else
11017  appendStringInfoString(buf, ", ");
11019  }
11020  appendStringInfoChar(buf, ')');
11021 
11022  if (j->join_using_alias)
11023  appendStringInfo(buf, " AS %s",
11025  }
11026  else if (j->quals)
11027  {
11028  appendStringInfoString(buf, " ON ");
11029  if (!PRETTY_PAREN(context))
11030  appendStringInfoChar(buf, '(');
11031  get_rule_expr(j->quals, context, false);
11032  if (!PRETTY_PAREN(context))
11033  appendStringInfoChar(buf, ')');
11034  }
11035  else if (j->jointype != JOIN_INNER)
11036  {
11037  /* If we didn't say CROSS JOIN above, we must provide an ON */
11038  appendStringInfoString(buf, " ON TRUE");
11039  }
11040 
11041  if (!PRETTY_PAREN(context) || j->alias != NULL)
11042  appendStringInfoChar(buf, ')');
11043 
11044  /* Yes, it's correct to put alias after the right paren ... */
11045  if (j->alias != NULL)
11046  {
11047  /*
11048  * Note that it's correct to emit an alias clause if and only if
11049  * there was one originally. Otherwise we'd be converting a named
11050  * join to unnamed or vice versa, which creates semantic
11051  * subtleties we don't want. However, we might print a different
11052  * alias name than was there originally.
11053  */
11054  appendStringInfo(buf, " %s",
11056  context)));
11057  get_column_alias_list(colinfo, context);
11058  }
11059  }
11060  else
11061  elog(ERROR, "unrecognized node type: %d",
11062  (int) nodeTag(jtnode));
11063 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:11478
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
Alias * alias
Definition: parsenodes.h:1152
Definition: nodes.h:537
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
bool funcordinality
Definition: parsenodes.h:1102
List * values_lists
Definition: parsenodes.h:1112
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11498
Node * larg
Definition: primnodes.h:1543
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:11162
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
List * rtable
Definition: parsenodes.h:147
#define ERROR
Definition: elog.h:46
List * usingNames
Definition: ruleutils.c:287
TableFunc * tablefunc
Definition: parsenodes.h:1107
Alias * join_using_alias
Definition: primnodes.h:1546
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:97
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:8215
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:291
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
List * usingClause
Definition: primnodes.h:1545
Node * quals
Definition: primnodes.h:1547
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:10533
Node * rarg
Definition: primnodes.h:1544
Alias * alias
Definition: primnodes.h:1548
JoinType jointype
Definition: primnodes.h:1541
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:1101
#define only_marker(rte)
Definition: ruleutils.c:492
static int list_length(const List *l)
Definition: pg_list.h:149
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5294
#define nodeTag(nodeptr)
Definition: nodes.h:542
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5368
RTEKind rtekind
Definition: parsenodes.h:1007
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:11071
char * ctename
Definition: parsenodes.h:1117
Query * subquery
Definition: parsenodes.h:1042
StringInfo buf
Definition: ruleutils.c:110
#define elog(elevel,...)
Definition: elog.h:232
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:11111
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9540
int rtindex
Definition: primnodes.h:1549
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1037
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4826
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10732

◆ get_func_expr()

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

Definition at line 9631 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, FuncExpr::args, buf, deparse_context::buf, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, COERCE_SQL_SYNTAX, ereport, errcode(), errmsg(), ERROR, exprIsLengthCoercion(), exprType(), FUNC_MAX_ARGS, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcvariadic, generate_function_name(), get_coercion_expr(), get_func_sql_syntax(), 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().

9633 {
9634  StringInfo buf = context->buf;
9635  Oid funcoid = expr->funcid;
9636  Oid argtypes[FUNC_MAX_ARGS];
9637  int nargs;
9638  List *argnames;
9639  bool use_variadic;
9640  ListCell *l;
9641 
9642  /*
9643  * If the function call came from an implicit coercion, then just show the
9644  * first argument --- unless caller wants to see implicit coercions.
9645  */
9646  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9647  {
9648  get_rule_expr_paren((Node *) linitial(expr->args), context,
9649  false, (Node *) expr);
9650  return;
9651  }
9652 
9653  /*
9654  * If the function call came from a cast, then show the first argument
9655  * plus an explicit cast operation.
9656  */
9657  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9659  {
9660  Node *arg = linitial(expr->args);
9661  Oid rettype = expr->funcresulttype;
9662  int32 coercedTypmod;
9663 
9664  /* Get the typmod if this is a length-coercion function */
9665  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9666 
9667  get_coercion_expr(arg, context,
9668  rettype, coercedTypmod,
9669  (Node *) expr);
9670 
9671  return;
9672  }
9673 
9674  /*
9675  * If the function was called using one of the SQL spec's random special
9676  * syntaxes, try to reproduce that. If we don't recognize the function,
9677  * fall through.
9678  */
9679  if (expr->funcformat == COERCE_SQL_SYNTAX)
9680  {
9681  if (get_func_sql_syntax(expr, context))
9682  return;
9683  }
9684 
9685  /*
9686  * Normal function: display as proname(args). First we need to extract
9687  * the argument datatypes.
9688  */
9689  if (list_length(expr->args) > FUNC_MAX_ARGS)
9690  ereport(ERROR,
9691  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9692  errmsg("too many arguments")));
9693  nargs = 0;
9694  argnames = NIL;
9695  foreach(l, expr->args)
9696  {
9697  Node *arg = (Node *) lfirst(l);
9698 
9699  if (IsA(arg, NamedArgExpr))
9700  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9701  argtypes[nargs] = exprType(arg);
9702  nargs++;
9703  }
9704 
9705  appendStringInfo(buf, "%s(",
9706  generate_function_name(funcoid, nargs,
9707  argnames, argtypes,
9708  expr->funcvariadic,
9709  &use_variadic,
9710  context->special_exprkind));
9711  nargs = 0;
9712  foreach(l, expr->args)
9713  {
9714  if (nargs++ > 0)
9715  appendStringInfoString(buf, ", ");
9716  if (use_variadic && lnext(expr->args, l) == NULL)
9717  appendStringInfoString(buf, "VARIADIC ");
9718  get_rule_expr((Node *) lfirst(l), context, true);
9719  }
9720  appendStringInfoChar(buf, ')');
9721 }
Oid funcresulttype
Definition: primnodes.h:496
#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:11600
static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Definition: ruleutils.c:9927
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8288
List * args
Definition: primnodes.h:503
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
Definition: nodes.h:537
int errcode(int sqlerrcode)
Definition: elog.c:698
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:503
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:429
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:500
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:495
#define ERROR
Definition: elog.h:46
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:10167
ParseExprKind special_exprkind
Definition: ruleutils.c:118
List * lappend(List *list, void *datum)
Definition: list.c:336
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ereport(elevel,...)
Definition: elog.h:157
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfirst(lc)
Definition: pg_list.h:169
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
StringInfo buf
Definition: ruleutils.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:909
void * arg
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:498

◆ get_func_sql_syntax()

static bool get_func_sql_syntax ( FuncExpr expr,
deparse_context context 
)
static

Definition at line 9927 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), FuncExpr::args, Assert, buf, deparse_context::buf, Const::constisnull, Const::consttype, Const::constvalue, FuncExpr::funcid, get_rule_expr(), IsA, lfourth, linitial, list_length(), lsecond, lthird, and TextDatumGetCString.

Referenced by get_func_expr().

9928 {
9929  StringInfo buf = context->buf;
9930  Oid funcoid = expr->funcid;
9931 
9932  switch (funcoid)
9933  {
9934  case F_TIMEZONE_INTERVAL_TIMESTAMP:
9935  case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
9936  case F_TIMEZONE_INTERVAL_TIMETZ:
9937  case F_TIMEZONE_TEXT_TIMESTAMP:
9938  case F_TIMEZONE_TEXT_TIMESTAMPTZ:
9939  case F_TIMEZONE_TEXT_TIMETZ:
9940  /* AT TIME ZONE ... note reversed argument order */
9941  appendStringInfoChar(buf, '(');
9942  get_rule_expr((Node *) lsecond(expr->args), context, false);
9943  appendStringInfoString(buf, " AT TIME ZONE ");
9944  get_rule_expr((Node *) linitial(expr->args), context, false);
9945  appendStringInfoChar(buf, ')');
9946  return true;
9947 
9948  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
9949  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
9950  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
9951  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
9952  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
9953  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
9954  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
9955  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
9956  case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
9957  case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
9958  case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
9959  case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
9960  case F_OVERLAPS_TIME_TIME_TIME_TIME:
9961  /* (x1, x2) OVERLAPS (y1, y2) */
9962  appendStringInfoString(buf, "((");
9963  get_rule_expr((Node *) linitial(expr->args), context, false);
9964  appendStringInfoString(buf, ", ");
9965  get_rule_expr((Node *) lsecond(expr->args), context, false);
9966  appendStringInfoString(buf, ") OVERLAPS (");
9967  get_rule_expr((Node *) lthird(expr->args), context, false);
9968  appendStringInfoString(buf, ", ");
9969  get_rule_expr((Node *) lfourth(expr->args), context, false);
9970  appendStringInfoString(buf, "))");
9971  return true;
9972 
9973  case F_EXTRACT_TEXT_DATE:
9974  case F_EXTRACT_TEXT_TIME:
9975  case F_EXTRACT_TEXT_TIMETZ:
9976  case F_EXTRACT_TEXT_TIMESTAMP:
9977  case F_EXTRACT_TEXT_TIMESTAMPTZ:
9978  case F_EXTRACT_TEXT_INTERVAL:
9979  /* EXTRACT (x FROM y) */
9980  appendStringInfoString(buf, "EXTRACT(");
9981  {
9982  Const *con = (Const *) linitial(expr->args);
9983 
9984  Assert(IsA(con, Const) &&
9985  con->consttype == TEXTOID &&
9986  !con->constisnull);
9988  }
9989  appendStringInfoString(buf, " FROM ");
9990  get_rule_expr((Node *) lsecond(expr->args), context, false);
9991  appendStringInfoChar(buf, ')');
9992  return true;
9993 
9994  case F_IS_NORMALIZED:
9995  /* IS xxx NORMALIZED */
9996  appendStringInfoString(buf, "((");
9997  get_rule_expr((Node *) linitial(expr->args), context, false);
9998  appendStringInfoString(buf, ") IS");
9999  if (list_length(expr->args) == 2)
10000  {
10001  Const *con = (Const *) lsecond(expr->args);
10002 
10003  Assert(IsA(con, Const) &&
10004  con->consttype == TEXTOID &&
10005  !con->constisnull);
10006  appendStringInfo(buf, " %s",
10008  }
10009  appendStringInfoString(buf, " NORMALIZED)");
10010  return true;
10011 
10012  case F_PG_COLLATION_FOR:
10013  /* COLLATION FOR */
10014  appendStringInfoString(buf, "COLLATION FOR (");
10015  get_rule_expr((Node *) linitial(expr->args), context, false);
10016  appendStringInfoChar(buf, ')');
10017  return true;
10018 
10019  /*
10020  * XXX EXTRACT, a/k/a date_part(), is intentionally not covered
10021  * yet. Add it after we change the return type to numeric.
10022  */
10023 
10024  case F_NORMALIZE:
10025  /* NORMALIZE() */
10026  appendStringInfoString(buf, "NORMALIZE(");
10027  get_rule_expr((Node *) linitial(expr->args), context, false);
10028  if (list_length(expr->args) == 2)
10029  {
10030  Const *con = (Const *) lsecond(expr->args);
10031 
10032  Assert(IsA(con, Const) &&
10033  con->consttype == TEXTOID &&
10034  !con->constisnull);
10035  appendStringInfo(buf, ", %s",
10037  }
10038  appendStringInfoChar(buf, ')');
10039  return true;
10040 
10041  case F_OVERLAY_BIT_BIT_INT4:
10042  case F_OVERLAY_BIT_BIT_INT4_INT4:
10043  case F_OVERLAY_BYTEA_BYTEA_INT4:
10044  case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
10045  case F_OVERLAY_TEXT_TEXT_INT4:
10046  case F_OVERLAY_TEXT_TEXT_INT4_INT4:
10047  /* OVERLAY() */
10048  appendStringInfoString(buf, "OVERLAY(");
10049  get_rule_expr((Node *) linitial(expr->args), context, false);
10050  appendStringInfoString(buf, " PLACING ");
10051  get_rule_expr((Node *) lsecond(expr->args), context, false);
10052  appendStringInfoString(buf, " FROM ");
10053  get_rule_expr((Node *) lthird(expr->args), context, false);
10054  if (list_length(expr->args) == 4)
10055  {
10056  appendStringInfoString(buf, " FOR ");
10057  get_rule_expr((Node *) lfourth(expr->args), context, false);
10058  }
10059  appendStringInfoChar(buf, ')');
10060  return true;
10061 
10062  case F_POSITION_BIT_BIT:
10063  case F_POSITION_BYTEA_BYTEA:
10064  case F_POSITION_TEXT_TEXT:
10065  /* POSITION() ... extra parens since args are b_expr not a_expr */
10066  appendStringInfoString(buf, "POSITION((");
10067  get_rule_expr((Node *) lsecond(expr->args), context, false);
10068  appendStringInfoString(buf, ") IN (");
10069  get_rule_expr((Node *) linitial(expr->args), context, false);
10070  appendStringInfoString(buf, "))");
10071  return true;
10072 
10073  case F_SUBSTRING_BIT_INT4:
10074  case F_SUBSTRING_BIT_INT4_INT4:
10075  case F_SUBSTRING_BYTEA_INT4:
10076  case F_SUBSTRING_BYTEA_INT4_INT4:
10077  case F_SUBSTRING_TEXT_INT4:
10078  case F_SUBSTRING_TEXT_INT4_INT4:
10079  /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
10080  appendStringInfoString(buf, "SUBSTRING(");
10081  get_rule_expr((Node *) linitial(expr->args), context, false);
10082  appendStringInfoString(buf, " FROM ");
10083  get_rule_expr((Node *) lsecond(expr->args), context, false);
10084  if (list_length(expr->args) == 3)
10085  {
10086  appendStringInfoString(buf, " FOR ");
10087  get_rule_expr((Node *) lthird(expr->args), context, false);
10088  }
10089  appendStringInfoChar(buf, ')');
10090  return true;
10091 
10092  case F_SUBSTRING_TEXT_TEXT_TEXT:
10093  /* SUBSTRING SIMILAR/ESCAPE */
10094  appendStringInfoString(buf, "SUBSTRING(");
10095  get_rule_expr((Node *) linitial(expr->args), context, false);
10096  appendStringInfoString(buf, " SIMILAR ");
10097  get_rule_expr((Node *) lsecond(expr->args), context, false);
10098  appendStringInfoString(buf, " ESCAPE ");
10099  get_rule_expr((Node *) lthird(expr->args), context, false);
10100  appendStringInfoChar(buf, ')');
10101  return true;
10102 
10103  case F_BTRIM_BYTEA_BYTEA:
10104  case F_BTRIM_TEXT:
10105  case F_BTRIM_TEXT_TEXT:
10106  /* TRIM() */
10107  appendStringInfoString(buf, "TRIM(BOTH");
10108  if (list_length(expr->args) == 2)
10109  {
10110  appendStringInfoChar(buf, ' ');
10111  get_rule_expr((Node *) lsecond(expr->args), context, false);
10112  }
10113  appendStringInfoString(buf, " FROM ");
10114  get_rule_expr((Node *) linitial(expr->args), context, false);
10115  appendStringInfoChar(buf, ')');
10116  return true;
10117 
10118  case F_LTRIM_BYTEA_BYTEA:
10119  case F_LTRIM_TEXT:
10120  case F_LTRIM_TEXT_TEXT:
10121  /* TRIM() */
10122  appendStringInfoString(buf, "TRIM(LEADING");
10123  if (list_length(expr->args) == 2)
10124  {
10125  appendStringInfoChar(buf, ' ');
10126  get_rule_expr((Node *) lsecond(expr->args), context, false);
10127  }
10128  appendStringInfoString(buf, " FROM ");
10129  get_rule_expr((Node *) linitial(expr->args), context, false);
10130  appendStringInfoChar(buf, ')');
10131  return true;
10132 
10133  case F_RTRIM_BYTEA_BYTEA:
10134  case F_RTRIM_TEXT:
10135  case F_RTRIM_TEXT_TEXT:
10136  /* TRIM() */
10137  appendStringInfoString(buf, "TRIM(TRAILING");
10138  if (list_length(expr->args) == 2)
10139  {
10140  appendStringInfoChar(buf, ' ');
10141  get_rule_expr((Node *) lsecond(expr->args), context, false);
10142  }
10143  appendStringInfoString(buf, " FROM ");
10144  get_rule_expr((Node *) linitial(expr->args), context, false);
10145  appendStringInfoChar(buf, ')');
10146  return true;
10147 
10148  case F_XMLEXISTS:
10149  /* XMLEXISTS ... extra parens because args are c_expr */
10150  appendStringInfoString(buf, "XMLEXISTS((");
10151  get_rule_expr((Node *) linitial(expr->args), context, false);
10152  appendStringInfoString(buf, ") PASSING (");
10153  get_rule_expr((Node *) lsecond(expr->args), context, false);
10154  appendStringInfoString(buf, "))");
10155  return true;
10156  }
10157  return false;
10158 }
Datum constvalue
Definition: primnodes.h:219
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
List * args
Definition: primnodes.h:503
Definition: nodes.h:537
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:179
Oid consttype
Definition: primnodes.h:215
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:495
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define TextDatumGetCString(d)
Definition: builtins.h:87
#define Assert(condition)
Definition: c.h:804
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfourth(l)
Definition: pg_list.h:189
static int list_length(const List *l)
Definition: pg_list.h:149
StringInfo buf
Definition: ruleutils.c:110
#define lthird(l)
Definition: pg_list.h:184
bool constisnull
Definition: primnodes.h:220

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

6461 {
6462  StringInfo buf = context->buf;
6463  RangeTblEntry *select_rte = NULL;
6464  RangeTblEntry *values_rte = NULL;
6465  RangeTblEntry *rte;
6466  char *sep;
6467  ListCell *l;
6468  List *strippedexprs;
6469 
6470  /* Insert the WITH clause if given */
6471  get_with_clause(query, context);
6472 
6473  /*
6474  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6475  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6476  */
6477  foreach(l, query->rtable)
6478  {
6479  rte = (RangeTblEntry *) lfirst(l);
6480 
6481  if (rte->rtekind == RTE_SUBQUERY)
6482  {
6483  if (select_rte)
6484  elog(ERROR, "too many subquery RTEs in INSERT");
6485  select_rte = rte;
6486  }
6487 
6488  if (rte->rtekind == RTE_VALUES)
6489  {
6490  if (values_rte)
6491  elog(ERROR, "too many values RTEs in INSERT");
6492  values_rte = rte;
6493  }
6494  }
6495  if (select_rte && values_rte)
6496  elog(ERROR, "both subquery and values RTEs in INSERT");
6497 
6498  /*
6499  * Start the query with INSERT INTO relname
6500  */
6501  rte = rt_fetch(query->resultRelation, query->rtable);
6502  Assert(rte->rtekind == RTE_RELATION);
6503 
6504  if (PRETTY_INDENT(context))
6505  {
6506  context->indentLevel += PRETTYINDENT_STD;
6507  appendStringInfoChar(buf, ' ');
6508  }
6509  appendStringInfo(buf, "INSERT INTO %s ",
6511  /* INSERT requires AS keyword for target alias */
6512  if (rte->alias != NULL)
6513  appendStringInfo(buf, "AS %s ",
6515 
6516  /*
6517  * Add the insert-column-names list. Any indirection decoration needed on
6518  * the column names can be inferred from the top targetlist.
6519  */
6520  strippedexprs = NIL;
6521  sep = "";
6522  if (query->targetList)
6523  appendStringInfoChar(buf, '(');
6524  foreach(l, query->targetList)
6525  {
6526  TargetEntry *tle = (TargetEntry *) lfirst(l);
6527 
6528  if (tle->resjunk)
6529  continue; /* ignore junk entries */
6530 
6531  appendStringInfoString(buf, sep);
6532  sep = ", ";
6533 
6534  /*
6535  * Put out name of target column; look in the catalogs, not at
6536  * tle->resname, since resname will fail to track RENAME.
6537  */
6540  tle->resno,
6541  false)));
6542 
6543  /*
6544  * Print any indirection needed (subfields or subscripts), and strip
6545  * off the top-level nodes representing the indirection assignments.
6546  * Add the stripped expressions to strippedexprs. (If it's a
6547  * single-VALUES statement, the stripped expressions are the VALUES to
6548  * print below. Otherwise they're just Vars and not really
6549  * interesting.)
6550  */
6551  strippedexprs = lappend(strippedexprs,
6552  processIndirection((Node *) tle->expr,
6553  context));
6554  }
6555  if (query->targetList)
6556  appendStringInfoString(buf, ") ");
6557 
6558  if (query->override)
6559  {
6560  if (query->override == OVERRIDING_SYSTEM_VALUE)
6561  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6562  else if (query->override == OVERRIDING_USER_VALUE)
6563  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6564  }
6565 
6566  if (select_rte)
6567  {
6568  /* Add the SELECT */
6569  get_query_def(select_rte->subquery, buf, NIL, NULL,
6570  context->prettyFlags, context->wrapColumn,
6571  context->indentLevel);
6572  }
6573  else if (values_rte)
6574  {
6575  /* Add the multi-VALUES expression lists */
6576  get_values_def(values_rte->values_lists, context);
6577  }
6578  else if (strippedexprs)
6579  {
6580  /* Add the single-VALUES expression list */
6581  appendContextKeyword(context, "VALUES (",
6583  get_rule_expr((Node *) strippedexprs, context, false);
6584  appendStringInfoChar(buf, ')');
6585  }
6586  else
6587  {
6588  /* No expressions, so it must be DEFAULT VALUES */
6589  appendStringInfoString(buf, "DEFAULT VALUES");
6590  }
6591 
6592  /* Add ON CONFLICT if present */
6593  if (query->onConflict)
6594  {
6595  OnConflictExpr *confl = query->onConflict;
6596 
6597  appendStringInfoString(buf, " ON CONFLICT");
6598 
6599  if (confl->arbiterElems)
6600  {
6601  /* Add the single-VALUES expression list */
6602  appendStringInfoChar(buf, '(');
6603  get_rule_expr((Node *) confl->arbiterElems, context, false);
6604  appendStringInfoChar(buf, ')');
6605 
6606  /* Add a WHERE clause (for partial indexes) if given */
6607  if (confl->arbiterWhere != NULL)
6608  {
6609  bool save_varprefix;
6610 
6611  /*
6612  * Force non-prefixing of Vars, since parser assumes that they
6613  * belong to target relation. WHERE clause does not use
6614  * InferenceElem, so this is separately required.
6615  */
6616  save_varprefix = context->varprefix;
6617  context->varprefix = false;
6618 
6619  appendContextKeyword(context, " WHERE ",
6621  get_rule_expr(confl->arbiterWhere, context, false);
6622 
6623  context->varprefix = save_varprefix;
6624  }
6625  }
6626  else if (OidIsValid(confl->constraint))
6627  {
6628  char *constraint = get_constraint_name(confl->constraint);
6629 
6630  if (!constraint)
6631  elog(ERROR, "cache lookup failed for constraint %u",
6632  confl->constraint);
6633  appendStringInfo(buf, " ON CONSTRAINT %s",
6634  quote_identifier(constraint));
6635  }
6636 
6637  if (confl->action == ONCONFLICT_NOTHING)
6638  {
6639  appendStringInfoString(buf, " DO NOTHING");
6640  }
6641  else
6642  {
6643  appendStringInfoString(buf, " DO UPDATE SET ");
6644  /* Deparse targetlist */
6646  context, rte);
6647 
6648  /* Add a WHERE clause if given */
6649  if (confl->onConflictWhere != NULL)
6650  {
6651  appendContextKeyword(context, " WHERE ",
6653  get_rule_expr(confl->onConflictWhere, context, false);
6654  }
6655  }
6656  }
6657 
6658  /* Add RETURNING if present */
6659  if (query->returningList)
6660  {
6661  appendContextKeyword(context, " RETURNING",
6663  get_target_list(query->returningList, context, NULL);
6664  }
6665 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5411
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
Alias * alias
Definition: parsenodes.h:1152
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:1106
OnConflictExpr * onConflict
Definition: parsenodes.h:154
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:11266
int resultRelation
Definition: parsenodes.h:130
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5881
Definition: nodes.h:537
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte)
Definition: ruleutils.c:6728
#define OidIsValid(objectId)
Definition: c.h:710
List * values_lists
Definition: parsenodes.h:1112
List * targetList
Definition: parsenodes.h:150
List * arbiterElems
Definition: primnodes.h:1583
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11498
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1462
List * rtable
Definition: parsenodes.h:147
#define ERROR
Definition: elog.h:46
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
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:8215
AttrNumber resno
Definition: primnodes.h:1456
List * returningList
Definition: parsenodes.h:156
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
List * lappend(List *list, void *datum)
Definition: list.c:336
OnConflictAction action
Definition: primnodes.h:1580
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
OverridingKind override
Definition: parsenodes.h:152
#define Assert(condition)
Definition: c.h:804
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8320
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1455
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5294
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5368
RTEKind rtekind
Definition: parsenodes.h:1007
Node * arbiterWhere
Definition: primnodes.h:1585
Query * subquery
Definition: parsenodes.h:1042
StringInfo buf
Definition: ruleutils.c:110
#define elog(elevel,...)
Definition: elog.h:232
List * onConflictSet
Definition: primnodes.h:1589
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
Node * onConflictWhere
Definition: primnodes.h:1590
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 7332 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_plan, 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_plan, deparse_namespace::outer_tlist, OUTER_VAR, deparse_namespace::plan, 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::varattnosyn, Var::varlevelsup, Var::varno, Var::varnosyn, and Var::vartype.

Referenced by get_rule_expr().

7334 {
7335  RangeTblEntry *rte;
7337  int netlevelsup;
7338  deparse_namespace *dpns;
7339  int varno;
7340  AttrNumber varattno;
7341  TupleDesc tupleDesc;
7342  Node *expr;
7343 
7344  /*
7345  * If it's a RowExpr that was expanded from a whole-row Var, use the
7346  * column names attached to it.
7347  */
7348  if (IsA(var, RowExpr))
7349  {
7350  RowExpr *r = (RowExpr *) var;
7351 
7352  if (fieldno > 0 && fieldno <= list_length(r->colnames))
7353  return strVal(list_nth(r->colnames, fieldno - 1));
7354  }
7355 
7356  /*
7357  * If it's a Param of type RECORD, try to find what the Param refers to.
7358  */
7359  if (IsA(var, Param))
7360  {
7361  Param *param = (Param *) var;
7362  ListCell *ancestor_cell;
7363 
7364  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7365  if (expr)
7366  {
7367  /* Found a match, so recurse to decipher the field name */
7368  deparse_namespace save_dpns;
7369  const char *result;
7370 
7371  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7372  result = get_name_for_var_field((Var *) expr, fieldno,
7373  0, context);
7374  pop_ancestor_plan(dpns, &save_dpns);
7375  return result;
7376  }
7377  }
7378 
7379  /*
7380  * If it's a Var of type RECORD, we have to find what the Var refers to;
7381  * if not, we can use get_expr_result_tupdesc().
7382  */
7383  if (!IsA(var, Var) ||
7384  var->vartype != RECORDOID)
7385  {
7386  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7387  /* Got the tupdesc, so we can extract the field name */
7388  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7389  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7390  }
7391 
7392  /* Find appropriate nesting depth */
7393  netlevelsup = var->varlevelsup + levelsup;
7394  if (netlevelsup >= list_length(context->namespaces))
7395  elog(ERROR, "bogus varlevelsup: %d offset %d",
7396  var->varlevelsup, levelsup);
7397  dpns = (deparse_namespace *) list_nth(context->namespaces,
7398  netlevelsup);
7399 
7400  /*
7401  * If we have a syntactic referent for the Var, and we're working from a
7402  * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7403  * on the semantic referent. (See comments in get_variable().)
7404  */
7405  if (var->varnosyn > 0 && dpns->plan == NULL)
7406  {
7407  varno = var->varnosyn;
7408  varattno = var->varattnosyn;
7409  }
7410  else
7411  {
7412  varno = var->varno;
7413  varattno = var->varattno;
7414  }
7415 
7416  /*
7417  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7418  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7419  * down into the subplans, or INDEX_VAR, which is resolved similarly.
7420  *
7421  * Note: unlike get_variable and resolve_special_varno, we need not worry
7422  * about inheritance mapping: a child Var should have the same datatype as
7423  * its parent, and here we're really only interested in the Var's type.
7424  */
7425  if (varno >= 1 && varno <= list_length(dpns->rtable))
7426  {
7427  rte = rt_fetch(varno, dpns->rtable);
7428  attnum = varattno;
7429  }
7430  else if (varno == OUTER_VAR && dpns->outer_tlist)
7431  {
7432  TargetEntry *tle;
7433  deparse_namespace save_dpns;
7434  const char *result;
7435 
7436  tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7437  if (!tle)
7438  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7439 
7440  Assert(netlevelsup == 0);
7441  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7442 
7443  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7444  levelsup, context);
7445 
7446  pop_child_plan(dpns, &save_dpns);
7447  return result;
7448  }
7449  else if (varno == INNER_VAR && dpns->inner_tlist)
7450  {
7451  TargetEntry *tle;
7452  deparse_namespace save_dpns;
7453  const char *result;
7454 
7455  tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7456  if (!tle)
7457  elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7458 
7459  Assert(netlevelsup == 0);
7460  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7461 
7462  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7463  levelsup, context);
7464 
7465  pop_child_plan(dpns, &save_dpns);
7466  return result;
7467  }
7468  else if (varno == INDEX_VAR && dpns->index_tlist)
7469  {
7470  TargetEntry *tle;
7471  const char *result;
7472 
7473  tle = get_tle_by_resno(dpns->index_tlist, varattno);
7474  if (!tle)
7475  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7476 
7477  Assert(netlevelsup == 0);
7478 
7479  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7480  levelsup, context);
7481 
7482  return result;
7483  }
7484  else
7485  {
7486  elog(ERROR, "bogus varno: %d", varno);
7487  return NULL; /* keep compiler quiet */
7488  }
7489 
7490  if (attnum == InvalidAttrNumber)
7491  {
7492  /* Var is whole-row reference to RTE, so select the right field */
7493  return get_rte_attribute_name(rte, fieldno);
7494  }
7495 
7496  /*
7497  * This part has essentially the same logic as the parser's
7498  * expandRecordVariable() function, but we are dealing with a different
7499  * representation of the input context, and we only need one field name
7500  * not a TupleDesc. Also, we need special cases for finding subquery and
7501  * CTE subplans when deparsing Plan trees.
7502  */
7503  expr = (Node *) var; /* default if we can't drill down */
7504 
7505  switch (rte->rtekind)
7506  {
7507  case RTE_RELATION:
7508  case RTE_VALUES:
7509  case RTE_NAMEDTUPLESTORE:
7510  case RTE_RESULT:
7511 
7512  /*
7513  * This case should not occur: a column of a table, values list,
7514  * or ENR shouldn't have type RECORD. Fall through and fail (most
7515  * likely) at the bottom.
7516  */
7517  break;
7518  case RTE_SUBQUERY:
7519  /* Subselect-in-FROM: examine sub-select's output expr */
7520  {
7521  if (rte->subquery)
7522  {
7524  attnum);
7525 
7526  if (ste == NULL || ste->resjunk)
7527  elog(ERROR, "subquery %s does not have attribute %d",
7528  rte->eref->aliasname, attnum);
7529  expr = (Node *) ste->expr;
7530  if (IsA(expr, Var))
7531  {
7532  /*
7533  * Recurse into the sub-select to see what its Var
7534  * refers to. We have to build an additional level of
7535  * namespace to keep in step with varlevelsup in the
7536  * subselect.
7537  */
7538  deparse_namespace mydpns;
7539  const char *result;
7540 
7541  set_deparse_for_query(&mydpns, rte->subquery,
7542  context->namespaces);
7543 
7544  context->namespaces = lcons(&mydpns,
7545  context->namespaces);
7546 
7547  result = get_name_for_var_field((Var *) expr, fieldno,
7548  0, context);
7549 
7550  context->namespaces =
7551  list_delete_first(context->namespaces);
7552 
7553  return result;
7554  }
7555  /* else fall through to inspect the expression */
7556  }
7557  else
7558  {
7559  /*
7560  * We're deparsing a Plan tree so we don't have complete
7561  * RTE entries (in particular, rte->subquery is NULL). But
7562  * the only place we'd see a Var directly referencing a
7563  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7564  * look into the child plan's tlist instead.
7565  */
7566  TargetEntry *tle;
7567  deparse_namespace save_dpns;
7568  const char *result;
7569 
7570  if (!dpns->inner_plan)
7571  elog(ERROR, "failed to find plan for subquery %s",
7572  rte->eref->aliasname);
7573  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7574  if (!tle)
7575  elog(ERROR, "bogus varattno for subquery var: %d",
7576  attnum);
7577  Assert(netlevelsup == 0);
7578  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7579 
7580  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7581  levelsup, context);
7582 
7583  pop_child_plan(dpns, &save_dpns);
7584  return result;
7585  }
7586  }
7587  break;
7588  case RTE_JOIN:
7589  /* Join RTE --- recursively inspect the alias variable */
7590  if (rte->joinaliasvars == NIL)
7591  elog(ERROR, "cannot decompile join alias var in plan tree");
7592  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7593  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7594  Assert(expr != NULL);
7595  /* we intentionally don't strip implicit coercions here */
7596  if (IsA(expr, Var))
7597  return get_name_for_var_field((Var *) expr, fieldno,
7598  var->varlevelsup + levelsup,
7599  context);
7600  /* else fall through to inspect the expression */
7601  break;
7602  case RTE_FUNCTION:
7603  case RTE_TABLEFUNC:
7604 
7605  /*
7606  * We couldn't get here unless a function is declared with one of
7607  * its result columns as RECORD, which is not allowed.
7608  */
7609  break;
7610  case RTE_CTE:
7611  /* CTE reference: examine subquery's output expr */
7612  {
7613  CommonTableExpr *cte = NULL;
7614  Index ctelevelsup;
7615  ListCell *lc;
7616 
7617  /*
7618  * Try to find the referenced CTE using the namespace stack.
7619  */
7620  ctelevelsup = rte->ctelevelsup + netlevelsup;
7621  if (ctelevelsup >= list_length(context->namespaces))
7622  lc = NULL;
7623  else
7624  {
7625  deparse_namespace *ctedpns;
7626 
7627  ctedpns = (deparse_namespace *)
7628  list_nth(context->namespaces, ctelevelsup);
7629  foreach(lc, ctedpns->ctes)
7630  {
7631  cte = (CommonTableExpr *) lfirst(lc);
7632  if (strcmp(cte->ctename, rte->ctename) == 0)
7633  break;
7634  }
7635  }
7636  if (lc != NULL)
7637  {
7638  Query *ctequery = (Query *) cte->ctequery;
7640  attnum);
7641 
7642  if (ste == NULL || ste->resjunk)
7643  elog(ERROR, "subquery %s does not have attribute %d",
7644  rte->eref->aliasname, attnum);
7645  expr = (Node *) ste->expr;
7646  if (IsA(expr, Var))
7647  {
7648  /*
7649  * Recurse into the CTE to see what its Var refers to.
7650  * We have to build an additional level of namespace
7651  * to keep in step with varlevelsup in the CTE.
7652  * Furthermore it could be an outer CTE, so we may
7653  * have to delete some levels of namespace.
7654  */
7655  List *save_nslist = context->namespaces;
7656  List *new_nslist;
7657  deparse_namespace mydpns;
7658  const char *result;
7659 
7660  set_deparse_for_query(&mydpns, ctequery,
7661  context->namespaces);
7662 
7663  new_nslist = list_copy_tail(context->namespaces,
7664  ctelevelsup);
7665  context->namespaces = lcons(&mydpns, new_nslist);
7666 
7667  result = get_name_for_var_field((Var *) expr, fieldno,
7668  0, context);
7669 
7670  context->namespaces = save_nslist;
7671 
7672  return result;
7673  }
7674  /* else fall through to inspect the expression */
7675  }
7676  else
7677  {
7678  /*
7679  * We're deparsing a Plan tree so we don't have a CTE
7680  * list. But the only places we'd see a Var directly
7681  * referencing a CTE RTE are in CteScan or WorkTableScan
7682  * plan nodes. For those cases, set_deparse_plan arranged
7683  * for dpns->inner_plan to be the plan node that emits the
7684  * CTE or RecursiveUnion result, and we can look at its
7685  * tlist instead.
7686  */
7687  TargetEntry *tle;
7688  deparse_namespace save_dpns;
7689  const char *result;
7690 
7691  if (!dpns->inner_plan)
7692  elog(ERROR, "failed to find plan for CTE %s",
7693  rte->eref->aliasname);
7694  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7695  if (!tle)
7696  elog(ERROR, "bogus varattno for subquery var: %d",
7697  attnum);
7698  Assert(netlevelsup == 0);
7699  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7700 
7701  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7702  levelsup, context);
7703 
7704  pop_child_plan(dpns, &save_dpns);
7705  return result;
7706  }
7707  }
7708  break;
7709  }
7710 
7711  /*
7712  * We now have an expression we can't expand any more, so see if
7713  * get_expr_result_tupdesc() can do anything with it.
7714  */
7715  tupleDesc = get_expr_result_tupdesc(expr, false);
7716  /* Got the tupdesc, so we can extract the field name */
7717  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7718  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7719 }
List * namespaces
Definition: ruleutils.c:111
int varno
Definition: primnodes.h:189
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:588
List * joinaliasvars
Definition: parsenodes.h:1082
Index varlevelsup
Definition: primnodes.h:196
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7730
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:537
#define strVal(v)
Definition: value.h:65
AttrNumber varattno
Definition: primnodes.h:191
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:5014
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1437
Definition: primnodes.h:186
List * targetList
Definition: parsenodes.h:150
bool resjunk
Definition: primnodes.h:1462
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
List * colnames
Definition: primnodes.h:1084
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:440
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
Oid vartype
Definition: primnodes.h:193
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varnosyn
Definition: primnodes.h:199
AttrNumber varattnosyn
Definition: primnodes.h:200
List * outer_tlist
Definition: ruleutils.c:172
unsigned int Index
Definition: c.h:549
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:7332
int16 attnum
Definition: pg_attribute.h:83
#define INNER_VAR
Definition: primnodes.h:175
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
List * lcons(void *datum, List *list)
Definition: list.c:468
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4963
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
static void push_child_plan(deparse_namespace *dpns, Plan *plan, deparse_namespace *save_dpns)
Definition: ruleutils.c:4946
Expr * expr
Definition: primnodes.h:1455
static int list_length(const List *l)
Definition: pg_list.h:149
Index ctelevelsup
Definition: parsenodes.h:1118
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3872
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:1007
char * ctename
Definition: parsenodes.h:1117
Query * subquery
Definition: parsenodes.h:1042
List * index_tlist
Definition: ruleutils.c:174
List * inner_tlist
Definition: ruleutils.c:173
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4993
#define elog(elevel,...)
Definition: elog.h:232
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:681
Alias * eref
Definition: parsenodes.h:1153
#define INDEX_VAR
Definition: primnodes.h:177
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1531
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:176
List * list_delete_first(List *list)
Definition: list.c:875

◆ get_opclass_name()

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

Definition at line 11206 of file ruleutils.c.

References appendStringInfo(), CLAOID, elog, ERROR, get_namespace_name_or_temp(), GetDefaultOpClass(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, OidIsValid, OpclassIsVisible(), quote_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by generate_opclass_name(), get_rule_expr(), pg_get_indexdef_worker(), and pg_get_partkeydef_worker().

11208 {
11209  HeapTuple ht_opc;
11210  Form_pg_opclass opcrec;
11211  char *opcname;
11212  char *nspname;
11213 
11214  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
11215  if (!HeapTupleIsValid(ht_opc))
11216  elog(ERROR, "cache lookup failed for opclass %u", opclass);
11217  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
11218 
11219  if (!OidIsValid(actual_datatype) ||
11220  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
11221  {
11222  /* Okay, we need the opclass name. Do we need to qualify it? */
11223  opcname = NameStr(opcrec->opcname);
11224  if (OpclassIsVisible(opclass))
11225  appendStringInfo(buf, " %s", quote_identifier(opcname));
11226  else
11227  {
11228  nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
11229  appendStringInfo(buf, " %s.%s",
11230  quote_identifier(nspname),
11231  quote_identifier(opcname));
11232  }
11233  }
11234  ReleaseSysCache(ht_opc);
11235 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2089
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
#define OidIsValid(objectId)
Definition: c.h:710
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1878
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3340
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
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 9591 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), arg, generate_unaccent_rules::args, OpExpr::args, buf, deparse_context::buf, exprType(), generate_operator_name(), get_rule_expr_paren(), InvalidOid, linitial, list_length(), lsecond, OpExpr::opno, and PRETTY_PAREN.

Referenced by get_rule_expr().

9592 {
9593  StringInfo buf = context->buf;
9594  Oid opno = expr->opno;
9595  List *args = expr->args;
9596 
9597  if (!PRETTY_PAREN(context))
9598  appendStringInfoChar(buf, '(');
9599  if (list_length(args) == 2)
9600  {
9601  /* binary operator */
9602  Node *arg1 = (Node *) linitial(args);
9603  Node *arg2 = (Node *) lsecond(args);
9604 
9605  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9606  appendStringInfo(buf, " %s ",
9608  exprType(arg1),
9609  exprType(arg2)));
9610  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9611  }
9612  else
9613  {
9614  /* prefix operator */
9615  Node *arg = (Node *) linitial(args);
9616 
9617  appendStringInfo(buf, "%s ",
9619  InvalidOid,
9620  exprType(arg)));
9621  get_rule_expr_paren(arg, context, true, (Node *) expr);
9622  }
9623  if (!PRETTY_PAREN(context))
9624  appendStringInfoChar(buf, ')');
9625 }
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8288
Definition: nodes.h:537
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:179
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:11705
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
static char * buf
Definition: pg_test_fsync.c:68
#define PRETTY_PAREN(context)
Definition: ruleutils.c:97
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define InvalidOid
Definition: postgres_ext.h:36
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
StringInfo buf
Definition: ruleutils.c:110
void * arg
Oid opno
Definition: primnodes.h:542
List * args
Definition: primnodes.h:548
Definition: pg_list.h:50

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

Definition at line 7865 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), deparse_namespace::argnames, deparse_context::buf, find_param_referent(), deparse_namespace::funcname, get_rule_expr(), IsA, lfirst, list_length(), list_tail(), deparse_context::namespaces, PARAM_EXTERN, Param::paramid, Param::paramkind, pop_ancestor_plan(), push_ancestor_plan(), quote_identifier(), deparse_namespace::rtable_names, and deparse_context::varprefix.

Referenced by get_rule_expr().

7866 {
7867  Node *expr;
7868  deparse_namespace *dpns;
7869  ListCell *ancestor_cell;
7870 
7871  /*
7872  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7873  * the parameter was computed. Note that failing to find a referent isn't
7874  * an error, since the Param might well be a subplan output rather than an
7875  * input.
7876  */
7877  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7878  if (expr)
7879  {
7880  /* Found a match, so print it */
7881  deparse_namespace save_dpns;
7882  bool save_varprefix;
7883  bool need_paren;
7884 
7885  /* Switch attention to the ancestor plan node */
7886  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7887 
7888  /*
7889  * Force prefixing of Vars, since they won't belong to the relation
7890  * being scanned