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

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

Referenced by generate_operator_clause().

11772 {
11773  HeapTuple typetup;
11774  Form_pg_type typform;
11775  char *typname;
11776  char *nspname;
11777 
11778  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11779  if (!HeapTupleIsValid(typetup))
11780  elog(ERROR, "cache lookup failed for type %u", typid);
11781  typform = (Form_pg_type) GETSTRUCT(typetup);
11782 
11783  typname = NameStr(typform->typname);
11784  nspname = get_namespace_name(typform->typnamespace);
11785 
11786  appendStringInfo(buf, "::%s.%s",
11787  quote_identifier(nspname), quote_identifier(typname));
11788 
11789  ReleaseSysCache(typetup);
11790 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
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
#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 8164 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().

8166 {
8167  StringInfo buf = context->buf;
8168 
8169  if (PRETTY_INDENT(context))
8170  {
8171  int indentAmount;
8172 
8173  context->indentLevel += indentBefore;
8174 
8175  /* remove any trailing spaces currently in the buffer ... */
8177  /* ... then add a newline and some spaces */
8178  appendStringInfoChar(buf, '\n');
8179 
8180  if (context->indentLevel < PRETTYINDENT_LIMIT)
8181  indentAmount = Max(context->indentLevel, 0) + indentPlus;
8182  else
8183  {
8184  /*
8185  * If we're indented more than PRETTYINDENT_LIMIT characters, try
8186  * to conserve horizontal space by reducing the per-level
8187  * indentation. For best results the scale factor here should
8188  * divide all the indent amounts that get added to indentLevel
8189  * (PRETTYINDENT_STD, etc). It's important that the indentation
8190  * not grow unboundedly, else deeply-nested trees use O(N^2)
8191  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
8192  */
8193  indentAmount = PRETTYINDENT_LIMIT +
8194  (context->indentLevel - PRETTYINDENT_LIMIT) /
8195  (PRETTYINDENT_STD / 2);
8196  indentAmount %= PRETTYINDENT_LIMIT;
8197  /* scale/wrap logic affects indentLevel, but not indentPlus */
8198  indentAmount += indentPlus;
8199  }
8200  appendStringInfoSpaces(buf, indentAmount);
8201 
8203 
8204  context->indentLevel += indentAfter;
8205  if (context->indentLevel < 0)
8206  context->indentLevel = 0;
8207  }
8208  else
8210 }
#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:8218
#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 4622 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().

4624 {
4625  int i;
4626  ListCell *lc;
4627 
4628  /* Check against already-assigned column aliases within RTE */
4629  for (i = 0; i < colinfo->num_cols; i++)
4630  {
4631  char *oldname = colinfo->colnames[i];
4632 
4633  if (oldname && strcmp(oldname, colname) == 0)
4634  return false;
4635  }
4636 
4637  /*
4638  * If we're building a new_colnames array, check that too (this will be
4639  * partially but not completely redundant with the previous checks)
4640  */
4641  for (i = 0; i < colinfo->num_new_cols; i++)
4642  {
4643  char *oldname = colinfo->new_colnames[i];
4644 
4645  if (oldname && strcmp(oldname, colname) == 0)
4646  return false;
4647  }
4648 
4649  /* Also check against USING-column names that must be globally unique */
4650  foreach(lc, dpns->using_names)
4651  {
4652  char *oldname = (char *) lfirst(lc);
4653 
4654  if (strcmp(oldname, colname) == 0)
4655  return false;
4656  }
4657 
4658  /* Also check against names already assigned for parent-join USING cols */
4659  foreach(lc, colinfo->parentUsing)
4660  {
4661  char *oldname = (char *) lfirst(lc);
4662 
4663  if (strcmp(oldname, colname) == 0)
4664  return false;
4665  }
4666 
4667  return true;
4668 }
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 2513 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2515 {
2516  Datum *keys;
2517  int nKeys;
2518  int j;
2519 
2520  /* Extract data from array of int16 */
2521  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2522  INT2OID, 2, true, TYPALIGN_SHORT,
2523  &keys, NULL, &nKeys);
2524 
2525  for (j = 0; j < nKeys; j++)
2526  {
2527  char *colName;
2528 
2529  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2530 
2531  if (j == 0)
2533  else
2534  appendStringInfo(buf, ", %s", quote_identifier(colName));
2535  }
2536 
2537  return nKeys;
2538 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
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:3488
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 3542 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().

3543 {
3544  deparse_namespace *dpns;
3545  RangeTblEntry *rte;
3546 
3547  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3548 
3549  /* Build a minimal RTE for the rel */
3550  rte = makeNode(RangeTblEntry);
3551  rte->rtekind = RTE_RELATION;
3552  rte->relid = relid;
3553  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3555  rte->alias = makeAlias(aliasname, NIL);
3556  rte->eref = rte->alias;
3557  rte->lateral = false;
3558  rte->inh = false;
3559  rte->inFromCl = true;
3560 
3561  /* Build one-element rtable */
3562  dpns->rtable = list_make1(rte);
3563  dpns->subplans = NIL;
3564  dpns->ctes = NIL;
3565  dpns->appendrels = NULL;
3566  set_rtable_names(dpns, NIL, NULL);
3568 
3569  /* Return a one-deep namespace stack */
3570  return list_make1(dpns);
3571 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1140
#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:3708
void * palloc0(Size size)
Definition: mcxt.c:1093
#define makeNode(_type_)
Definition: nodes.h:587
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3918
RTEKind rtekind
Definition: parsenodes.h:995
Alias * eref
Definition: parsenodes.h:1141

◆ deparse_context_for_plan_tree()

List* deparse_context_for_plan_tree ( PlannedStmt pstmt,
List rtable_names 
)

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

3588 {
3589  deparse_namespace *dpns;
3590 
3591  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3592 
3593  /* Initialize fields that stay the same across the whole plan tree */
3594  dpns->rtable = pstmt->rtable;
3595  dpns->rtable_names = rtable_names;
3596  dpns->subplans = pstmt->subplans;
3597  dpns->ctes = NIL;
3598  if (pstmt->appendRelations)
3599  {
3600  /* Set up the array, indexed by child relid */
3601  int ntables = list_length(dpns->rtable);
3602  ListCell *lc;
3603 
3604  dpns->appendrels = (AppendRelInfo **)
3605  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3606  foreach(lc, pstmt->appendRelations)
3607  {
3608  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3609  Index crelid = appinfo->child_relid;
3610 
3611  Assert(crelid > 0 && crelid <= ntables);
3612  Assert(dpns->appendrels[crelid] == NULL);
3613  dpns->appendrels[crelid] = appinfo;
3614  }
3615  }
3616  else
3617  dpns->appendrels = NULL; /* don't need it */
3618 
3619  /*
3620  * Set up column name aliases. We will get rather bogus results for join
3621  * RTEs, but that doesn't matter because plan trees don't contain any join
3622  * alias Vars.
3623  */
3625 
3626  /* Return a one-deep namespace stack */
3627  return list_make1(dpns);
3628 }
#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:3918
Index child_relid
Definition: pathnodes.h:2296
List * appendRelations
Definition: plannodes.h:71

◆ deparse_expression()

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

Definition at line 3482 of file ruleutils.c.

References deparse_expression_pretty().

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

3484 {
3485  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3486  showimplicit, 0, 0);
3487 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3509

◆ deparse_expression_pretty()

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

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

3512 {
3514  deparse_context context;
3515 
3516  initStringInfo(&buf);
3517  context.buf = &buf;
3518  context.namespaces = dpcontext;
3519  context.windowClause = NIL;
3520  context.windowTList = NIL;
3521  context.varprefix = forceprefix;
3522  context.prettyFlags = prettyFlags;
3523  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3524  context.indentLevel = startIndent;
3525  context.special_exprkind = EXPR_KIND_NONE;
3526  context.appendparents = NULL;
3527 
3528  get_rule_expr(expr, &context, showimplicit);
3529 
3530  return buf.data;
3531 }
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:8269
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 4715 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().

4716 {
4717  if (n > colinfo->num_cols)
4718  {
4719  if (colinfo->colnames == NULL)
4720  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4721  else
4722  {
4723  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4724  n * sizeof(char *));
4725  memset(colinfo->colnames + colinfo->num_cols, 0,
4726  (n - colinfo->num_cols) * sizeof(char *));
4727  }
4728  colinfo->num_cols = n;
4729  }
4730 }
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 7679 of file ruleutils.c.

References deparse_namespace::ancestors, arg, SubPlan::args, Assert, castNode, elog, ERROR, for_each_cell, forboth, innerPlan, IsA, lfirst, lfirst_int, 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().

7681 {
7682  /* Initialize output parameters to prevent compiler warnings */
7683  *dpns_p = NULL;
7684  *ancestor_cell_p = NULL;
7685 
7686  /*
7687  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7688  * SubPlan argument. This will necessarily be in some ancestor of the
7689  * current expression's Plan node.
7690  */
7691  if (param->paramkind == PARAM_EXEC)
7692  {
7693  deparse_namespace *dpns;
7694  Plan *child_plan;
7695  bool in_same_plan_level;
7696  ListCell *lc;
7697 
7698  dpns = (deparse_namespace *) linitial(context->namespaces);
7699  child_plan = dpns->plan;
7700  in_same_plan_level = true;
7701 
7702  foreach(lc, dpns->ancestors)
7703  {
7704  Node *ancestor = (Node *) lfirst(lc);
7705  ListCell *lc2;
7706 
7707  /*
7708  * NestLoops transmit params to their inner child only; also, once
7709  * we've crawled up out of a subplan, this couldn't possibly be
7710  * the right match.
7711  */
7712  if (IsA(ancestor, NestLoop) &&
7713  child_plan == innerPlan(ancestor) &&
7714  in_same_plan_level)
7715  {
7716  NestLoop *nl = (NestLoop *) ancestor;
7717 
7718  foreach(lc2, nl->nestParams)
7719  {
7720  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7721 
7722  if (nlp->paramno == param->paramid)
7723  {
7724  /* Found a match, so return it */
7725  *dpns_p = dpns;
7726  *ancestor_cell_p = lc;
7727  return (Node *) nlp->paramval;
7728  }
7729  }
7730  }
7731 
7732  /*
7733  * If ancestor is a SubPlan, check the arguments it provides.
7734  */
7735  if (IsA(ancestor, SubPlan))
7736  {
7737  SubPlan *subplan = (SubPlan *) ancestor;
7738  ListCell *lc3;
7739  ListCell *lc4;
7740 
7741  forboth(lc3, subplan->parParam, lc4, subplan->args)
7742  {
7743  int paramid = lfirst_int(lc3);
7744  Node *arg = (Node *) lfirst(lc4);
7745 
7746  if (paramid == param->paramid)
7747  {
7748  /*
7749  * Found a match, so return it. But, since Vars in
7750  * the arg are to be evaluated in the surrounding
7751  * context, we have to point to the next ancestor item
7752  * that is *not* a SubPlan.
7753  */
7754  ListCell *rest;
7755 
7756  for_each_cell(rest, dpns->ancestors,
7757  lnext(dpns->ancestors, lc))
7758  {
7759  Node *ancestor2 = (Node *) lfirst(rest);
7760 
7761  if (!IsA(ancestor2, SubPlan))
7762  {
7763  *dpns_p = dpns;
7764  *ancestor_cell_p = rest;
7765  return arg;
7766  }
7767  }
7768  elog(ERROR, "SubPlan cannot be outermost ancestor");
7769  }
7770  }
7771 
7772  /* We have emerged from a subplan. */
7773  in_same_plan_level = false;
7774 
7775  /* SubPlan isn't a kind of Plan, so skip the rest */
7776  continue;
7777  }
7778 
7779  /*
7780  * Check to see if we're emerging from an initplan of the current
7781  * ancestor plan. Initplans never have any parParams, so no need
7782  * to search that list, but we need to know if we should reset
7783  * in_same_plan_level.
7784  */
7785  foreach(lc2, ((Plan *) ancestor)->initPlan)
7786  {
7787  SubPlan *subplan = castNode(SubPlan, lfirst(lc2));
7788 
7789  if (child_plan != (Plan *) list_nth(dpns->subplans,
7790  subplan->plan_id - 1))
7791  continue;
7792 
7793  /* No parameters to be had here. */
7794  Assert(subplan->parParam == NIL);
7795 
7796  /* We have emerged from an initplan. */
7797  in_same_plan_level = false;
7798  break;
7799  }
7800 
7801  /* No luck, crawl up to next ancestor */
7802  child_plan = (Plan *) ancestor;
7803  }
7804  }
7805 
7806  /* No referent found */
7807  return NULL;
7808 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
int plan_id
Definition: primnodes.h:742
List * nestParams
Definition: plannodes.h:722
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:417
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:539
Var * paramval
Definition: plannodes.h:729
#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 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:762
#define elog(elevel,...)
Definition: elog.h:232
void * arg
List * args
Definition: primnodes.h:763

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

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

11937 {
11938  char *result = NULL;
11939  HeapTuple tuple;
11940  Datum reloptions;
11941  bool isnull;
11942 
11943  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11944  if (!HeapTupleIsValid(tuple))
11945  elog(ERROR, "cache lookup failed for relation %u", relid);
11946 
11947  reloptions = SysCacheGetAttr(RELOID, tuple,
11948  Anum_pg_class_reloptions, &isnull);
11949  if (!isnull)
11950  {
11952 
11953  initStringInfo(&buf);
11954  get_reloptions(&buf, reloptions);
11955 
11956  result = buf.data;
11957  }
11958 
11959  ReleaseSysCache(tuple);
11960 
11961  return result;
11962 }
static void get_reloptions(StringInfo buf, Datum reloptions)
Definition: ruleutils.c:11880
#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 11835 of file ruleutils.c.

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

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

11836 {
11837  HeapTuple tp;
11838  Form_pg_collation colltup;
11839  char *collname;
11840  char *nspname;
11841  char *result;
11842 
11843  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11844  if (!HeapTupleIsValid(tp))
11845  elog(ERROR, "cache lookup failed for collation %u", collid);
11846  colltup = (Form_pg_collation) GETSTRUCT(tp);
11847  collname = NameStr(colltup->collname);
11848 
11849  if (!CollationIsVisible(collid))
11850  nspname = get_namespace_name(colltup->collnamespace);
11851  else
11852  nspname = NULL;
11853 
11854  result = quote_qualified_identifier(nspname, collname);
11855 
11856  ReleaseSysCache(tp);
11857 
11858  return result;
11859 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2047
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11407
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:51
#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 11549 of file ruleutils.c.

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

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

11552 {
11553  char *result;
11554  HeapTuple proctup;
11555  Form_pg_proc procform;
11556  char *proname;
11557  bool use_variadic;
11558  char *nspname;
11559  FuncDetailCode p_result;
11560  Oid p_funcid;
11561  Oid p_rettype;
11562  bool p_retset;
11563  int p_nvargs;
11564  Oid p_vatype;
11565  Oid *p_true_typeids;
11566  bool force_qualify = false;
11567 
11568  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
11569  if (!HeapTupleIsValid(proctup))
11570  elog(ERROR, "cache lookup failed for function %u", funcid);
11571  procform = (Form_pg_proc) GETSTRUCT(proctup);
11572  proname = NameStr(procform->proname);
11573 
11574  /*
11575  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
11576  * qualification in some special cases.
11577  */
11578  if (special_exprkind == EXPR_KIND_GROUP_BY)
11579  {
11580  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
11581  force_qualify = true;
11582  }
11583 
11584  /*
11585  * Determine whether VARIADIC should be printed. We must do this first
11586  * since it affects the lookup rules in func_get_detail().
11587  *
11588  * We always print VARIADIC if the function has a merged variadic-array
11589  * argument. Note that this is always the case for functions taking a
11590  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
11591  * and printed the array elements as separate arguments, the call could
11592  * match a newer non-VARIADIC function.
11593  */
11594  if (use_variadic_p)
11595  {
11596  /* Parser should not have set funcvariadic unless fn is variadic */
11597  Assert(!has_variadic || OidIsValid(procform->provariadic));
11598  use_variadic = has_variadic;
11599  *use_variadic_p = use_variadic;
11600  }
11601  else
11602  {
11603  Assert(!has_variadic);
11604  use_variadic = false;
11605  }
11606 
11607  /*
11608  * The idea here is to schema-qualify only if the parser would fail to
11609  * resolve the correct function given the unqualified func name with the
11610  * specified argtypes and VARIADIC flag. But if we already decided to
11611  * force qualification, then we can skip the lookup and pretend we didn't
11612  * find it.
11613  */
11614  if (!force_qualify)
11615  p_result = func_get_detail(list_make1(makeString(proname)),
11616  NIL, argnames, nargs, argtypes,
11617  !use_variadic, true,
11618  &p_funcid, &p_rettype,
11619  &p_retset, &p_nvargs, &p_vatype,
11620  &p_true_typeids, NULL);
11621  else
11622  {
11623  p_result = FUNCDETAIL_NOTFOUND;
11624  p_funcid = InvalidOid;
11625  }
11626 
11627  if ((p_result == FUNCDETAIL_NORMAL ||
11628  p_result == FUNCDETAIL_AGGREGATE ||
11629  p_result == FUNCDETAIL_WINDOWFUNC) &&
11630  p_funcid == funcid)
11631  nspname = NULL;
11632  else
11633  nspname = get_namespace_name(procform->pronamespace);
11634 
11635  result = quote_qualified_identifier(nspname, proname);
11636 
11637  ReleaseSysCache(proctup);
11638 
11639  return result;
11640 }
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:65
NameData proname
Definition: pg_proc.h:35
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11407
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, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1392
#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 11193 of file ruleutils.c.

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

Referenced by index_opclass_options().

11194 {
11196 
11197  initStringInfo(&buf);
11198  get_opclass_name(opclass, InvalidOid, &buf);
11199 
11200  return &buf.data[1]; /* get_opclass_name() prepends space */
11201 }
static char * buf
Definition: pg_test_fsync.c:68
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:11155
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 11731 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().

11735 {
11736  HeapTuple opertup;
11737  Form_pg_operator operform;
11738  char *oprname;
11739  char *nspname;
11740 
11741  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11742  if (!HeapTupleIsValid(opertup))
11743  elog(ERROR, "cache lookup failed for operator %u", opoid);
11744  operform = (Form_pg_operator) GETSTRUCT(opertup);
11745  Assert(operform->oprkind == 'b');
11746  oprname = NameStr(operform->oprname);
11747 
11748  nspname = get_namespace_name(operform->oprnamespace);
11749 
11750  appendStringInfoString(buf, leftop);
11751  if (leftoptype != operform->oprleft)
11752  add_cast_to(buf, operform->oprleft);
11753  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11754  appendStringInfoString(buf, oprname);
11755  appendStringInfo(buf, ") %s", rightop);
11756  if (rightoptype != operform->oprright)
11757  add_cast_to(buf, operform->oprright);
11758 
11759  ReleaseSysCache(opertup);
11760 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11771
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
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 11654 of file ruleutils.c.

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

11655 {
11657  HeapTuple opertup;
11658  Form_pg_operator operform;
11659  char *oprname;
11660  char *nspname;
11661  Operator p_result;
11662 
11663  initStringInfo(&buf);
11664 
11665  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11666  if (!HeapTupleIsValid(opertup))
11667  elog(ERROR, "cache lookup failed for operator %u", operid);
11668  operform = (Form_pg_operator) GETSTRUCT(opertup);
11669  oprname = NameStr(operform->oprname);
11670 
11671  /*
11672  * The idea here is to schema-qualify only if the parser would fail to
11673  * resolve the correct operator given the unqualified op name with the
11674  * specified argtypes.
11675  */
11676  switch (operform->oprkind)
11677  {
11678  case 'b':
11679  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11680  true, -1);
11681  break;
11682  case 'l':
11683  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11684  true, -1);
11685  break;
11686  default:
11687  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11688  p_result = NULL; /* keep compiler quiet */
11689  break;
11690  }
11691 
11692  if (p_result != NULL && oprid(p_result) == operid)
11693  nspname = NULL;
11694  else
11695  {
11696  nspname = get_namespace_name(operform->oprnamespace);
11697  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11698  }
11699 
11700  appendStringInfoString(&buf, oprname);
11701 
11702  if (nspname)
11703  appendStringInfoChar(&buf, ')');
11704 
11705  if (p_result != NULL)
11706  ReleaseSysCache(p_result);
11707 
11708  ReleaseSysCache(opertup);
11709 
11710  return buf.data;
11711 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
Oid oprid(Operator op)
Definition: parse_oper.c:250
#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
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
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
#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 11507 of file ruleutils.c.

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

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

11508 {
11509  HeapTuple tp;
11510  Form_pg_class reltup;
11511  char *relname;
11512  char *nspname;
11513  char *result;
11514 
11515  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11516  if (!HeapTupleIsValid(tp))
11517  elog(ERROR, "cache lookup failed for relation %u", relid);
11518  reltup = (Form_pg_class) GETSTRUCT(tp);
11519  relname = NameStr(reltup->relname);
11520 
11521  nspname = get_namespace_name(reltup->relnamespace);
11522  if (!nspname)
11523  elog(ERROR, "cache lookup failed for namespace %u",
11524  reltup->relnamespace);
11525 
11526  result = quote_qualified_identifier(nspname, relname);
11527 
11528  ReleaseSysCache(tp);
11529 
11530  return result;
11531 }
#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 * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11407
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
#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 11802 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

11803 {
11804  HeapTuple tp;
11805  Form_pg_type typtup;
11806  char *typname;
11807  char *nspname;
11808  char *result;
11809 
11811  if (!HeapTupleIsValid(tp))
11812  elog(ERROR, "cache lookup failed for type %u", typid);
11813  typtup = (Form_pg_type) GETSTRUCT(tp);
11814  typname = NameStr(typtup->typname);
11815 
11816  nspname = get_namespace_name(typtup->typnamespace);
11817  if (!nspname)
11818  elog(ERROR, "cache lookup failed for namespace %u",
11819  typtup->typnamespace);
11820 
11821  result = quote_qualified_identifier(nspname, typname);
11822 
11823  ReleaseSysCache(tp);
11824 
11825  return result;
11826 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
NameData typname
Definition: pg_type.h:41
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11407
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
#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 11447 of file ruleutils.c.

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

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

11448 {
11449  HeapTuple tp;
11450  Form_pg_class reltup;
11451  bool need_qual;
11452  ListCell *nslist;
11453  char *relname;
11454  char *nspname;
11455  char *result;
11456 
11457  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11458  if (!HeapTupleIsValid(tp))
11459  elog(ERROR, "cache lookup failed for relation %u", relid);
11460  reltup = (Form_pg_class) GETSTRUCT(tp);
11461  relname = NameStr(reltup->relname);
11462 
11463  /* Check for conflicting CTE name */
11464  need_qual = false;
11465  foreach(nslist, namespaces)
11466  {
11467  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
11468  ListCell *ctlist;
11469 
11470  foreach(ctlist, dpns->ctes)
11471  {
11472  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
11473 
11474  if (strcmp(cte->ctename, relname) == 0)
11475  {
11476  need_qual = true;
11477  break;
11478  }
11479  }
11480  if (need_qual)
11481  break;
11482  }
11483 
11484  /* Otherwise, qualify the name if not visible in search path */
11485  if (!need_qual)
11486  need_qual = !RelationIsVisible(relid);
11487 
11488  if (need_qual)
11489  nspname = get_namespace_name(reltup->relnamespace);
11490  else
11491  nspname = NULL;
11492 
11493  result = quote_qualified_identifier(nspname, relname);
11494 
11495  ReleaseSysCache(tp);
11496 
11497  return result;
11498 }
#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 * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11407
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:708
#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 9783 of file ruleutils.c.

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

Referenced by get_agg_expr().

9784 {
9785  Aggref *aggref;
9786  Aggref *original_aggref = callback_arg;
9787 
9788  if (!IsA(node, Aggref))
9789  elog(ERROR, "combining Aggref does not point to an Aggref");
9790 
9791  aggref = (Aggref *) node;
9792  get_agg_expr(aggref, context, original_aggref);
9793 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
#define ERROR
Definition: elog.h:46
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9676
#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 9676 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().

9678 {
9679  StringInfo buf = context->buf;
9680  Oid argtypes[FUNC_MAX_ARGS];
9681  int nargs;
9682  bool use_variadic;
9683 
9684  /*
9685  * For a combining aggregate, we look up and deparse the corresponding
9686  * partial aggregate instead. This is necessary because our input
9687  * argument list has been replaced; the new argument list always has just
9688  * one element, which will point to a partial Aggref that supplies us with
9689  * transition states to combine.
9690  */
9691  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9692  {
9693  TargetEntry *tle;
9694 
9695  Assert(list_length(aggref->args) == 1);
9696  tle = linitial_node(TargetEntry, aggref->args);
9697  resolve_special_varno((Node *) tle->expr, context,
9698  get_agg_combine_expr, original_aggref);
9699  return;
9700  }
9701 
9702  /*
9703  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9704  * to avoid printing this when recursing from the code just above.
9705  */
9706  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9707  appendStringInfoString(buf, "PARTIAL ");
9708 
9709  /* Extract the argument types as seen by the parser */
9710  nargs = get_aggregate_argtypes(aggref, argtypes);
9711 
9712  /* Print the aggregate name, schema-qualified if needed */
9713  appendStringInfo(buf, "%s(%s",
9714  generate_function_name(aggref->aggfnoid, nargs,
9715  NIL, argtypes,
9716  aggref->aggvariadic,
9717  &use_variadic,
9718  context->special_exprkind),
9719  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9720 
9721  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9722  {
9723  /*
9724  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9725  * worry about inserting VARIADIC. So we can just dump the direct
9726  * args as-is.
9727  */
9728  Assert(!aggref->aggvariadic);
9729  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9730  Assert(aggref->aggorder != NIL);
9731  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9732  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9733  }
9734  else
9735  {
9736  /* aggstar can be set only in zero-argument aggregates */
9737  if (aggref->aggstar)
9738  appendStringInfoChar(buf, '*');
9739  else
9740  {
9741  ListCell *l;
9742  int i;
9743 
9744  i = 0;
9745  foreach(l, aggref->args)
9746  {
9747  TargetEntry *tle = (TargetEntry *) lfirst(l);
9748  Node *arg = (Node *) tle->expr;
9749 
9750  Assert(!IsA(arg, NamedArgExpr));
9751  if (tle->resjunk)
9752  continue;
9753  if (i++ > 0)
9754  appendStringInfoString(buf, ", ");
9755  if (use_variadic && i == nargs)
9756  appendStringInfoString(buf, "VARIADIC ");
9757  get_rule_expr(arg, context, true);
9758  }
9759  }
9760 
9761  if (aggref->aggorder != NIL)
9762  {
9763  appendStringInfoString(buf, " ORDER BY ");
9764  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9765  }
9766  }
9767 
9768  if (aggref->aggfilter != NULL)
9769  {
9770  appendStringInfoString(buf, ") FILTER (WHERE ");
9771  get_rule_expr((Node *) aggref->aggfilter, context, false);
9772  }
9773 
9774  appendStringInfoChar(buf, ')');
9775 }
static void resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
Definition: ruleutils.c:7176
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:11549
bool aggvariadic
Definition: primnodes.h:335
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6213
Definition: nodes.h:539
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:801
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1451
static void get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:9783
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:8269
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
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:802
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:1886

◆ get_basic_select_query()

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

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

5703 {
5704  StringInfo buf = context->buf;
5705  RangeTblEntry *values_rte;
5706  char *sep;
5707  ListCell *l;
5708 
5709  if (PRETTY_INDENT(context))
5710  {
5711  context->indentLevel += PRETTYINDENT_STD;
5712  appendStringInfoChar(buf, ' ');
5713  }
5714 
5715  /*
5716  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5717  * VALUES part. This reverses what transformValuesClause() did at parse
5718  * time.
5719  */
5720  values_rte = get_simple_values_rte(query, resultDesc);
5721  if (values_rte)
5722  {
5723  get_values_def(values_rte->values_lists, context);
5724  return;
5725  }
5726 
5727  /*
5728  * Build up the query string - first we say SELECT
5729  */
5730  if (query->isReturn)
5731  appendStringInfoString(buf, "RETURN");
5732  else
5733  appendStringInfoString(buf, "SELECT");
5734 
5735  /* Add the DISTINCT clause if given */
5736  if (query->distinctClause != NIL)
5737  {
5738  if (query->hasDistinctOn)
5739  {
5740  appendStringInfoString(buf, " DISTINCT ON (");
5741  sep = "";
5742  foreach(l, query->distinctClause)
5743  {
5744  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5745 
5746  appendStringInfoString(buf, sep);
5748  false, context);
5749  sep = ", ";
5750  }
5751  appendStringInfoChar(buf, ')');
5752  }
5753  else
5754  appendStringInfoString(buf, " DISTINCT");
5755  }
5756 
5757  /* Then we tell what to select (the targetlist) */
5758  get_target_list(query->targetList, context, resultDesc);
5759 
5760  /* Add the FROM clause if needed */
5761  get_from_clause(query, " FROM ", context);
5762 
5763  /* Add the WHERE clause if given */
5764  if (query->jointree->quals != NULL)
5765  {
5766  appendContextKeyword(context, " WHERE ",
5768  get_rule_expr(query->jointree->quals, context, false);
5769  }
5770 
5771  /* Add the GROUP BY clause if given */
5772  if (query->groupClause != NULL || query->groupingSets != NULL)
5773  {
5774  ParseExprKind save_exprkind;
5775 
5776  appendContextKeyword(context, " GROUP BY ",
5778  if (query->groupDistinct)
5779  appendStringInfoString(buf, "DISTINCT ");
5780 
5781  save_exprkind = context->special_exprkind;
5783 
5784  if (query->groupingSets == NIL)
5785  {
5786  sep = "";
5787  foreach(l, query->groupClause)
5788  {
5789  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5790 
5791  appendStringInfoString(buf, sep);
5793  false, context);
5794  sep = ", ";
5795  }
5796  }
5797  else
5798  {
5799  sep = "";
5800  foreach(l, query->groupingSets)
5801  {
5802  GroupingSet *grp = lfirst(l);
5803 
5804  appendStringInfoString(buf, sep);
5805  get_rule_groupingset(grp, query->targetList, true, context);
5806  sep = ", ";
5807  }
5808  }
5809 
5810  context->special_exprkind = save_exprkind;
5811  }
5812 
5813  /* Add the HAVING clause if given */
5814  if (query->havingQual != NULL)
5815  {
5816  appendContextKeyword(context, " HAVING ",
5818  get_rule_expr(query->havingQual, context, false);
5819  }
5820 
5821  /* Add the WINDOW clause if needed */
5822  if (query->windowClause != NIL)
5823  get_rule_windowclause(query, context);
5824 }
#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:5833
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:6097
Index tleSortGroupRef
Definition: parsenodes.h:1283
List * groupingSets
Definition: parsenodes.h:161
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10587
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:6271
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
ParseExprKind
Definition: parse_node.h:38
List * values_lists
Definition: parsenodes.h:1100
Node * quals
Definition: primnodes.h:1554
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:8164
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5632
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:6153
#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:8269
#define lfirst(lc)
Definition: pg_list.h:169
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5320
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 10116 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().

10119 {
10120  StringInfo buf = context->buf;
10121 
10122  /*
10123  * Since parse_coerce.c doesn't immediately collapse application of
10124  * length-coercion functions to constants, what we'll typically see in
10125  * such cases is a Const with typmod -1 and a length-coercion function
10126  * right above it. Avoid generating redundant output. However, beware of
10127  * suppressing casts when the user actually wrote something like
10128  * 'foo'::text::char(3).
10129  *
10130  * Note: it might seem that we are missing the possibility of needing to
10131  * print a COLLATE clause for such a Const. However, a Const could only
10132  * have nondefault collation in a post-constant-folding tree, in which the
10133  * length coercion would have been folded too. See also the special
10134  * handling of CollateExpr in coerce_to_target_type(): any collation
10135  * marking will be above the coercion node, not below it.
10136  */
10137  if (arg && IsA(arg, Const) &&
10138  ((Const *) arg)->consttype == resulttype &&
10139  ((Const *) arg)->consttypmod == -1)
10140  {
10141  /* Show the constant without normal ::typename decoration */
10142  get_const_expr((Const *) arg, context, -1);
10143  }
10144  else
10145  {
10146  if (!PRETTY_PAREN(context))
10147  appendStringInfoChar(buf, '(');
10148  get_rule_expr_paren(arg, context, false, parentNode);
10149  if (!PRETTY_PAREN(context))
10150  appendStringInfoChar(buf, ')');
10151  }
10152 
10153  /*
10154  * Never emit resulttype(arg) functional notation. A pg_proc entry could
10155  * take precedence, and a resulttype in pg_temp would require schema
10156  * qualification that format_type_with_typemod() would usually omit. We've
10157  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
10158  * would work fine.
10159  */
10160  appendStringInfo(buf, "::%s",
10161  format_type_with_typemod(resulttype, resulttypmod));
10162 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8237
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:10180
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 11020 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().

11021 {
11022  StringInfo buf = context->buf;
11023  int i;
11024  bool first = true;
11025 
11026  /* Don't print aliases if not needed */
11027  if (!colinfo->printaliases)
11028  return;
11029 
11030  for (i = 0; i < colinfo->num_new_cols; i++)
11031  {
11032  char *colname = colinfo->new_colnames[i];
11033 
11034  if (first)
11035  {
11036  appendStringInfoChar(buf, '(');
11037  first = false;
11038  }
11039  else
11040  appendStringInfoString(buf, ", ");
11042  }
11043  if (!first)
11044  appendStringInfoChar(buf, ')');
11045 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
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 10310 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().

10311 {
10312  StringInfo buf = context->buf;
10313 
10314  if (OidIsValid(constval->constcollid))
10315  {
10316  Oid typcollation = get_typcollation(constval->consttype);
10317 
10318  if (constval->constcollid != typcollation)
10319  {
10320  appendStringInfo(buf, " COLLATE %s",
10322  }
10323  }
10324 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11835
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 10180 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().

10181 {
10182  StringInfo buf = context->buf;
10183  Oid typoutput;
10184  bool typIsVarlena;
10185  char *extval;
10186  bool needlabel = false;
10187 
10188  if (constval->constisnull)
10189  {
10190  /*
10191  * Always label the type of a NULL constant to prevent misdecisions
10192  * about type when reparsing.
10193  */
10194  appendStringInfoString(buf, "NULL");
10195  if (showtype >= 0)
10196  {
10197  appendStringInfo(buf, "::%s",
10199  constval->consttypmod));
10200  get_const_collation(constval, context);
10201  }
10202  return;
10203  }
10204 
10205  getTypeOutputInfo(constval->consttype,
10206  &typoutput, &typIsVarlena);
10207 
10208  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
10209 
10210  switch (constval->consttype)
10211  {
10212  case INT4OID:
10213 
10214  /*
10215  * INT4 can be printed without any decoration, unless it is
10216  * negative; in that case print it as '-nnn'::integer to ensure
10217  * that the output will re-parse as a constant, not as a constant
10218  * plus operator. In most cases we could get away with printing
10219  * (-nnn) instead, because of the way that gram.y handles negative
10220  * literals; but that doesn't work for INT_MIN, and it doesn't
10221  * seem that much prettier anyway.
10222  */
10223  if (extval[0] != '-')
10224  appendStringInfoString(buf, extval);
10225  else
10226  {
10227  appendStringInfo(buf, "'%s'", extval);
10228  needlabel = true; /* we must attach a cast */
10229  }
10230  break;
10231 
10232  case NUMERICOID:
10233 
10234  /*
10235  * NUMERIC can be printed without quotes if it looks like a float
10236  * constant (not an integer, and not Infinity or NaN) and doesn't
10237  * have a leading sign (for the same reason as for INT4).
10238  */
10239  if (isdigit((unsigned char) extval[0]) &&
10240  strcspn(extval, "eE.") != strlen(extval))
10241  {
10242  appendStringInfoString(buf, extval);
10243  }
10244  else
10245  {
10246  appendStringInfo(buf, "'%s'", extval);
10247  needlabel = true; /* we must attach a cast */
10248  }
10249  break;
10250 
10251  case BOOLOID:
10252  if (strcmp(extval, "t") == 0)
10253  appendStringInfoString(buf, "true");
10254  else
10255  appendStringInfoString(buf, "false");
10256  break;
10257 
10258  default:
10259  simple_quote_literal(buf, extval);
10260  break;
10261  }
10262 
10263  pfree(extval);
10264 
10265  if (showtype < 0)
10266  return;
10267 
10268  /*
10269  * For showtype == 0, append ::typename unless the constant will be
10270  * implicitly typed as the right type when it is read in.
10271  *
10272  * XXX this code has to be kept in sync with the behavior of the parser,
10273  * especially make_const.
10274  */
10275  switch (constval->consttype)
10276  {
10277  case BOOLOID:
10278  case UNKNOWNOID:
10279  /* These types can be left unlabeled */
10280  needlabel = false;
10281  break;
10282  case INT4OID:
10283  /* We determined above whether a label is needed */
10284  break;
10285  case NUMERICOID:
10286 
10287  /*
10288  * Float-looking constants will be typed as numeric, which we
10289  * checked above; but if there's a nondefault typmod we need to
10290  * show it.
10291  */
10292  needlabel |= (constval->consttypmod >= 0);
10293  break;
10294  default:
10295  needlabel = true;
10296  break;
10297  }
10298  if (needlabel || showtype > 0)
10299  appendStringInfo(buf, "::%s",
10301  constval->consttypmod));
10302 
10303  get_const_collation(constval, context);
10304 }
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:10330
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:10310
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:1656
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 6832 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().

6833 {
6834  StringInfo buf = context->buf;
6835  RangeTblEntry *rte;
6836 
6837  /* Insert the WITH clause if given */
6838  get_with_clause(query, context);
6839 
6840  /*
6841  * Start the query with DELETE FROM relname
6842  */
6843  rte = rt_fetch(query->resultRelation, query->rtable);
6844  Assert(rte->rtekind == RTE_RELATION);
6845  if (PRETTY_INDENT(context))
6846  {
6847  appendStringInfoChar(buf, ' ');
6848  context->indentLevel += PRETTYINDENT_STD;
6849  }
6850  appendStringInfo(buf, "DELETE FROM %s%s",
6851  only_marker(rte),
6853  if (rte->alias != NULL)
6854  appendStringInfo(buf, " %s",
6856 
6857  /* Add the USING clause if given */
6858  get_from_clause(query, " USING ", context);
6859 
6860  /* Add a WHERE clause if given */
6861  if (query->jointree->quals != NULL)
6862  {
6863  appendContextKeyword(context, " WHERE ",
6865  get_rule_expr(query->jointree->quals, context, false);
6866  }
6867 
6868  /* Add RETURNING if present */
6869  if (query->returningList)
6870  {
6871  appendContextKeyword(context, " RETURNING",
6873  get_target_list(query->returningList, context, NULL);
6874  }
6875 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5363
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
Alias * alias
Definition: parsenodes.h:1140
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:5833
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10587
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
Node * quals
Definition: primnodes.h:1554
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11447
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:8164
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:8269
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:490
RTEKind rtekind
Definition: parsenodes.h:995
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 10587 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().

10588 {
10589  StringInfo buf = context->buf;
10590  bool first = true;
10591  ListCell *l;
10592 
10593  /*
10594  * We use the query's jointree as a guide to what to print. However, we
10595  * must ignore auto-added RTEs that are marked not inFromCl. (These can
10596  * only appear at the top level of the jointree, so it's sufficient to
10597  * check here.) This check also ensures we ignore the rule pseudo-RTEs
10598  * for NEW and OLD.
10599  */
10600  foreach(l, query->jointree->fromlist)
10601  {
10602  Node *jtnode = (Node *) lfirst(l);
10603 
10604  if (IsA(jtnode, RangeTblRef))
10605  {
10606  int varno = ((RangeTblRef *) jtnode)->rtindex;
10607  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10608 
10609  if (!rte->inFromCl)
10610  continue;
10611  }
10612 
10613  if (first)
10614  {
10615  appendContextKeyword(context, prefix,
10617  first = false;
10618 
10619  get_from_clause_item(jtnode, query, context);
10620  }
10621  else
10622  {
10623  StringInfoData itembuf;
10624 
10625  appendStringInfoString(buf, ", ");
10626 
10627  /*
10628  * Put the new FROM item's text into itembuf so we can decide
10629  * after we've got it whether or not it needs to go on a new line.
10630  */
10631  initStringInfo(&itembuf);
10632  context->buf = &itembuf;
10633 
10634  get_from_clause_item(jtnode, query, context);
10635 
10636  /* Restore context's output buffer */
10637  context->buf = buf;
10638 
10639  /* Consider line-wrapping if enabled */
10640  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10641  {
10642  /* Does the new item start with a new line? */
10643  if (itembuf.len > 0 && itembuf.data[0] == '\n')
10644  {
10645  /* If so, we shouldn't add anything */
10646  /* instead, remove any trailing spaces currently in buf */
10648  }
10649  else
10650  {
10651  char *trailing_nl;
10652 
10653  /* Locate the start of the current line in the buffer */
10654  trailing_nl = strrchr(buf->data, '\n');
10655  if (trailing_nl == NULL)
10656  trailing_nl = buf->data;
10657  else
10658  trailing_nl++;
10659 
10660  /*
10661  * Add a newline, plus some indentation, if the new item
10662  * would cause an overflow.
10663  */
10664  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10665  appendContextKeyword(context, "", -PRETTYINDENT_STD,
10668  }
10669  }
10670 
10671  /* Add the new item */
10672  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10673 
10674  /* clean up */
10675  pfree(itembuf.data);
10676  }
10677  }
10678 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
FromExpr * jointree
Definition: parsenodes.h:148
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
Definition: nodes.h:539
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
List * fromlist
Definition: primnodes.h:1553
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:8164
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:8218
#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:10681

◆ get_from_clause_coldeflist()

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

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

11063 {
11064  StringInfo buf = context->buf;
11065  ListCell *l1;
11066  ListCell *l2;
11067  ListCell *l3;
11068  ListCell *l4;
11069  int i;
11070 
11071  appendStringInfoChar(buf, '(');
11072 
11073  i = 0;
11074  forfour(l1, rtfunc->funccoltypes,
11075  l2, rtfunc->funccoltypmods,
11076  l3, rtfunc->funccolcollations,
11077  l4, rtfunc->funccolnames)
11078  {
11079  Oid atttypid = lfirst_oid(l1);
11080  int32 atttypmod = lfirst_int(l2);
11081  Oid attcollation = lfirst_oid(l3);
11082  char *attname;
11083 
11084  if (colinfo)
11085  attname = colinfo->colnames[i];
11086  else
11087  attname = strVal(lfirst(l4));
11088 
11089  Assert(attname); /* shouldn't be any dropped columns here */
11090 
11091  if (i > 0)
11092  appendStringInfoString(buf, ", ");
11093  appendStringInfo(buf, "%s %s",
11094  quote_identifier(attname),
11095  format_type_with_typemod(atttypid, atttypmod));
11096  if (OidIsValid(attcollation) &&
11097  attcollation != get_typcollation(atttypid))
11098  appendStringInfo(buf, " COLLATE %s",
11099  generate_collation_name(attcollation));
11100 
11101  i++;
11102  }
11103 
11104  appendStringInfoChar(buf, ')');
11105 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11835
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:1179
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:3003
List * funccolcollations
Definition: parsenodes.h:1180
#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 10681 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().

10682 {
10683  StringInfo buf = context->buf;
10685 
10686  if (IsA(jtnode, RangeTblRef))
10687  {
10688  int varno = ((RangeTblRef *) jtnode)->rtindex;
10689  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10690  char *refname = get_rtable_name(varno, context);
10691  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10692  RangeTblFunction *rtfunc1 = NULL;
10693  bool printalias;
10694 
10695  if (rte->lateral)
10696  appendStringInfoString(buf, "LATERAL ");
10697 
10698  /* Print the FROM item proper */
10699  switch (rte->rtekind)
10700  {
10701  case RTE_RELATION:
10702  /* Normal relation RTE */
10703  appendStringInfo(buf, "%s%s",
10704  only_marker(rte),
10706  context->namespaces));
10707  break;
10708  case RTE_SUBQUERY:
10709  /* Subquery RTE */
10710  appendStringInfoChar(buf, '(');
10711  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10712  context->prettyFlags, context->wrapColumn,
10713  context->indentLevel);
10714  appendStringInfoChar(buf, ')');
10715  break;
10716  case RTE_FUNCTION:
10717  /* Function RTE */
10718  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10719 
10720  /*
10721  * Omit ROWS FROM() syntax for just one function, unless it
10722  * has both a coldeflist and WITH ORDINALITY. If it has both,
10723  * we must use ROWS FROM() syntax to avoid ambiguity about
10724  * whether the coldeflist includes the ordinality column.
10725  */
10726  if (list_length(rte->functions) == 1 &&
10727  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10728  {
10729  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10730  /* we'll print the coldeflist below, if it has one */
10731  }
10732  else
10733  {
10734  bool all_unnest;
10735  ListCell *lc;
10736 
10737  /*
10738  * If all the function calls in the list are to unnest,
10739  * and none need a coldeflist, then collapse the list back
10740  * down to UNNEST(args). (If we had more than one
10741  * built-in unnest function, this would get more
10742  * difficult.)
10743  *
10744  * XXX This is pretty ugly, since it makes not-terribly-
10745  * future-proof assumptions about what the parser would do
10746  * with the output; but the alternative is to emit our
10747  * nonstandard ROWS FROM() notation for what might have
10748  * been a perfectly spec-compliant multi-argument
10749  * UNNEST().
10750  */
10751  all_unnest = true;
10752  foreach(lc, rte->functions)
10753  {
10754  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10755 
10756  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10757  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
10758  rtfunc->funccolnames != NIL)
10759  {
10760  all_unnest = false;
10761  break;
10762  }
10763  }
10764 
10765  if (all_unnest)
10766  {
10767  List *allargs = NIL;
10768 
10769  foreach(lc, rte->functions)
10770  {
10771  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10772  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10773 
10774  allargs = list_concat(allargs, args);
10775  }
10776 
10777  appendStringInfoString(buf, "UNNEST(");
10778  get_rule_expr((Node *) allargs, context, true);
10779  appendStringInfoChar(buf, ')');
10780  }
10781  else
10782  {
10783  int funcno = 0;
10784 
10785  appendStringInfoString(buf, "ROWS FROM(");
10786  foreach(lc, rte->functions)
10787  {
10788  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10789 
10790  if (funcno > 0)
10791  appendStringInfoString(buf, ", ");
10792  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10793  if (rtfunc->funccolnames != NIL)
10794  {
10795  /* Reconstruct the column definition list */
10796  appendStringInfoString(buf, " AS ");
10798  NULL,
10799  context);
10800  }
10801  funcno++;
10802  }
10803  appendStringInfoChar(buf, ')');
10804  }
10805  /* prevent printing duplicate coldeflist below */
10806  rtfunc1 = NULL;
10807  }
10808  if (rte->funcordinality)
10809  appendStringInfoString(buf, " WITH ORDINALITY");
10810  break;
10811  case RTE_TABLEFUNC:
10812  get_tablefunc(rte->tablefunc, context, true);
10813  break;
10814  case RTE_VALUES:
10815  /* Values list RTE */
10816  appendStringInfoChar(buf, '(');
10817  get_values_def(rte->values_lists, context);
10818  appendStringInfoChar(buf, ')');
10819  break;
10820  case RTE_CTE:
10822  break;
10823  default:
10824  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10825  break;
10826  }
10827 
10828  /* Print the relation alias, if needed */
10829  printalias = false;
10830  if (rte->alias != NULL)
10831  {
10832  /* Always print alias if user provided one */
10833  printalias = true;
10834  }
10835  else if (colinfo->printaliases)
10836  {
10837  /* Always print alias if we need to print column aliases */
10838  printalias = true;
10839  }
10840  else if (rte->rtekind == RTE_RELATION)
10841  {
10842  /*
10843  * No need to print alias if it's same as relation name (this
10844  * would normally be the case, but not if set_rtable_names had to
10845  * resolve a conflict).
10846  */
10847  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10848  printalias = true;
10849  }
10850  else if (rte->rtekind == RTE_FUNCTION)
10851  {
10852  /*
10853  * For a function RTE, always print alias. This covers possible
10854  * renaming of the function and/or instability of the
10855  * FigureColname rules for things that aren't simple functions.
10856  * Note we'd need to force it anyway for the columndef list case.
10857  */
10858  printalias = true;
10859  }
10860  else if (rte->rtekind == RTE_VALUES)
10861  {
10862  /* Alias is syntactically required for VALUES */
10863  printalias = true;
10864  }
10865  else if (rte->rtekind == RTE_CTE)
10866  {
10867  /*
10868  * No need to print alias if it's same as CTE name (this would
10869  * normally be the case, but not if set_rtable_names had to
10870  * resolve a conflict).
10871  */
10872  if (strcmp(refname, rte->ctename) != 0)
10873  printalias = true;
10874  }
10875  if (printalias)
10876  appendStringInfo(buf, " %s", quote_identifier(refname));
10877 
10878  /* Print the column definitions or aliases, if needed */
10879  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10880  {
10881  /* Reconstruct the columndef list, which is also the aliases */
10882  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10883  }
10884  else
10885  {
10886  /* Else print column aliases as needed */
10887  get_column_alias_list(colinfo, context);
10888  }
10889 
10890  /* Tablesample clause must go after any alias */
10891  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10892  get_tablesample_def(rte->tablesample, context);
10893  }
10894  else if (IsA(jtnode, JoinExpr))
10895  {
10896  JoinExpr *j = (JoinExpr *) jtnode;
10897  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10898  bool need_paren_on_right;
10899 
10900  need_paren_on_right = PRETTY_PAREN(context) &&
10901  !IsA(j->rarg, RangeTblRef) &&
10902  !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
10903 
10904  if (!PRETTY_PAREN(context) || j->alias != NULL)
10905  appendStringInfoChar(buf, '(');
10906 
10907  get_from_clause_item(j->larg, query, context);
10908 
10909  switch (j->jointype)
10910  {
10911  case JOIN_INNER:
10912  if (j->quals)
10913  appendContextKeyword(context, " JOIN ",
10917  else
10918  appendContextKeyword(context, " CROSS JOIN ",
10922  break;
10923  case JOIN_LEFT:
10924  appendContextKeyword(context, " LEFT JOIN ",
10928  break;
10929  case JOIN_FULL:
10930  appendContextKeyword(context, " FULL JOIN ",
10934  break;
10935  case JOIN_RIGHT:
10936  appendContextKeyword(context, " RIGHT JOIN ",
10940  break;
10941  default:
10942  elog(ERROR, "unrecognized join type: %d",
10943  (int) j->jointype);
10944  }
10945 
10946  if (need_paren_on_right)
10947  appendStringInfoChar(buf, '(');
10948  get_from_clause_item(j->rarg, query, context);
10949  if (need_paren_on_right)
10950  appendStringInfoChar(buf, ')');
10951 
10952  if (j->usingClause)
10953  {
10954  ListCell *lc;
10955  bool first = true;
10956 
10957  appendStringInfoString(buf, " USING (");
10958  /* Use the assigned names, not what's in usingClause */
10959  foreach(lc, colinfo->usingNames)
10960  {
10961  char *colname = (char *) lfirst(lc);
10962 
10963  if (first)
10964  first = false;
10965  else
10966  appendStringInfoString(buf, ", ");
10968  }
10969  appendStringInfoChar(buf, ')');
10970 
10971  if (j->join_using_alias)
10972  appendStringInfo(buf, " AS %s",
10974  }
10975  else if (j->quals)
10976  {
10977  appendStringInfoString(buf, " ON ");
10978  if (!PRETTY_PAREN(context))
10979  appendStringInfoChar(buf, '(');
10980  get_rule_expr(j->quals, context, false);
10981  if (!PRETTY_PAREN(context))
10982  appendStringInfoChar(buf, ')');
10983  }
10984  else if (j->jointype != JOIN_INNER)
10985  {
10986  /* If we didn't say CROSS JOIN above, we must provide an ON */
10987  appendStringInfoString(buf, " ON TRUE");
10988  }
10989 
10990  if (!PRETTY_PAREN(context) || j->alias != NULL)
10991  appendStringInfoChar(buf, ')');
10992 
10993  /* Yes, it's correct to put alias after the right paren ... */
10994  if (j->alias != NULL)
10995  {
10996  /*
10997  * Note that it's correct to emit an alias clause if and only if
10998  * there was one originally. Otherwise we'd be converting a named
10999  * join to unnamed or vice versa, which creates semantic
11000  * subtleties we don't want. However, we might print a different
11001  * alias name than was there originally.
11002  */
11003  appendStringInfo(buf, " %s",
11005  context)));
11006  get_column_alias_list(colinfo, context);
11007  }
11008  }
11009  else
11010  elog(ERROR, "unrecognized node type: %d",
11011  (int) nodeTag(jtnode));
11012 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:11427
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
Alias * alias
Definition: parsenodes.h:1140
Definition: nodes.h:539
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
bool funcordinality
Definition: parsenodes.h:1090
List * values_lists
Definition: parsenodes.h:1100
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11447
Node * larg
Definition: primnodes.h:1532
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:11111
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:1095
Alias * join_using_alias
Definition: primnodes.h:1535
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:8164
#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:1534
Node * quals
Definition: primnodes.h:1536
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:10482
Node * rarg
Definition: primnodes.h:1533
Alias * alias
Definition: primnodes.h:1537
JoinType jointype
Definition: primnodes.h:1530
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8269
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
List * functions
Definition: parsenodes.h:1089
#define only_marker(rte)
Definition: ruleutils.c:490
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:5246
#define nodeTag(nodeptr)
Definition: nodes.h:544
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5320
RTEKind rtekind
Definition: parsenodes.h:995
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:11020
char * ctename
Definition: parsenodes.h:1105
Query * subquery
Definition: parsenodes.h:1030
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:11060
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9489
int rtindex
Definition: primnodes.h:1538
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1025
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4807
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10681

◆ get_func_expr()

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

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

9582 {
9583  StringInfo buf = context->buf;
9584  Oid funcoid = expr->funcid;
9585  Oid argtypes[FUNC_MAX_ARGS];
9586  int nargs;
9587  List *argnames;
9588  bool use_variadic;
9589  ListCell *l;
9590 
9591  /*
9592  * If the function call came from an implicit coercion, then just show the
9593  * first argument --- unless caller wants to see implicit coercions.
9594  */
9595  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9596  {
9597  get_rule_expr_paren((Node *) linitial(expr->args), context,
9598  false, (Node *) expr);
9599  return;
9600  }
9601 
9602  /*
9603  * If the function call came from a cast, then show the first argument
9604  * plus an explicit cast operation.
9605  */
9606  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9608  {
9609  Node *arg = linitial(expr->args);
9610  Oid rettype = expr->funcresulttype;
9611  int32 coercedTypmod;
9612 
9613  /* Get the typmod if this is a length-coercion function */
9614  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9615 
9616  get_coercion_expr(arg, context,
9617  rettype, coercedTypmod,
9618  (Node *) expr);
9619 
9620  return;
9621  }
9622 
9623  /*
9624  * If the function was called using one of the SQL spec's random special
9625  * syntaxes, try to reproduce that. If we don't recognize the function,
9626  * fall through.
9627  */
9628  if (expr->funcformat == COERCE_SQL_SYNTAX)
9629  {
9630  if (get_func_sql_syntax(expr, context))
9631  return;
9632  }
9633 
9634  /*
9635  * Normal function: display as proname(args). First we need to extract
9636  * the argument datatypes.
9637  */
9638  if (list_length(expr->args) > FUNC_MAX_ARGS)
9639  ereport(ERROR,
9640  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9641  errmsg("too many arguments")));
9642  nargs = 0;
9643  argnames = NIL;
9644  foreach(l, expr->args)
9645  {
9646  Node *arg = (Node *) lfirst(l);
9647 
9648  if (IsA(arg, NamedArgExpr))
9649  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9650  argtypes[nargs] = exprType(arg);
9651  nargs++;
9652  }
9653 
9654  appendStringInfo(buf, "%s(",
9655  generate_function_name(funcoid, nargs,
9656  argnames, argtypes,
9657  expr->funcvariadic,
9658  &use_variadic,
9659  context->special_exprkind));
9660  nargs = 0;
9661  foreach(l, expr->args)
9662  {
9663  if (nargs++ > 0)
9664  appendStringInfoString(buf, ", ");
9665  if (use_variadic && lnext(expr->args, l) == NULL)
9666  appendStringInfoString(buf, "VARIADIC ");
9667  get_rule_expr((Node *) lfirst(l), context, true);
9668  }
9669  appendStringInfoChar(buf, ')');
9670 }
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:11549
static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Definition: ruleutils.c:9876
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8237
List * args
Definition: primnodes.h:503
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
Definition: nodes.h:539
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:10116
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:8269
#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 9876 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().

9877 {
9878  StringInfo buf = context->buf;
9879  Oid funcoid = expr->funcid;
9880 
9881  switch (funcoid)
9882  {
9883  case F_TIMEZONE_INTERVAL_TIMESTAMP:
9884  case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
9885  case F_TIMEZONE_INTERVAL_TIMETZ:
9886  case F_TIMEZONE_TEXT_TIMESTAMP:
9887  case F_TIMEZONE_TEXT_TIMESTAMPTZ:
9888  case F_TIMEZONE_TEXT_TIMETZ:
9889  /* AT TIME ZONE ... note reversed argument order */
9890  appendStringInfoChar(buf, '(');
9891  get_rule_expr((Node *) lsecond(expr->args), context, false);
9892  appendStringInfoString(buf, " AT TIME ZONE ");
9893  get_rule_expr((Node *) linitial(expr->args), context, false);
9894  appendStringInfoChar(buf, ')');
9895  return true;
9896 
9897  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
9898  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
9899  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
9900  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
9901  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
9902  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
9903  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
9904  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
9905  case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
9906  case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
9907  case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
9908  case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
9909  case F_OVERLAPS_TIME_TIME_TIME_TIME:
9910  /* (x1, x2) OVERLAPS (y1, y2) */
9911  appendStringInfoString(buf, "((");
9912  get_rule_expr((Node *) linitial(expr->args), context, false);
9913  appendStringInfoString(buf, ", ");
9914  get_rule_expr((Node *) lsecond(expr->args), context, false);
9915  appendStringInfoString(buf, ") OVERLAPS (");
9916  get_rule_expr((Node *) lthird(expr->args), context, false);
9917  appendStringInfoString(buf, ", ");
9918  get_rule_expr((Node *) lfourth(expr->args), context, false);
9919  appendStringInfoString(buf, "))");
9920  return true;
9921 
9922  case F_EXTRACT_TEXT_DATE:
9923  case F_EXTRACT_TEXT_TIME:
9924  case F_EXTRACT_TEXT_TIMETZ:
9925  case F_EXTRACT_TEXT_TIMESTAMP:
9926  case F_EXTRACT_TEXT_TIMESTAMPTZ:
9927  case F_EXTRACT_TEXT_INTERVAL:
9928  /* EXTRACT (x FROM y) */
9929  appendStringInfoString(buf, "EXTRACT(");
9930  {
9931  Const *con = (Const *) linitial(expr->args);
9932 
9933  Assert(IsA(con, Const) &&
9934  con->consttype == TEXTOID &&
9935  !con->constisnull);
9937  }
9938  appendStringInfoString(buf, " FROM ");
9939  get_rule_expr((Node *) lsecond(expr->args), context, false);
9940  appendStringInfoChar(buf, ')');
9941  return true;
9942 
9943  case F_IS_NORMALIZED:
9944  /* IS xxx NORMALIZED */
9945  appendStringInfoString(buf, "((");
9946  get_rule_expr((Node *) linitial(expr->args), context, false);
9947  appendStringInfoString(buf, ") IS");
9948  if (list_length(expr->args) == 2)
9949  {
9950  Const *con = (Const *) lsecond(expr->args);
9951 
9952  Assert(IsA(con, Const) &&
9953  con->consttype == TEXTOID &&
9954  !con->constisnull);
9955  appendStringInfo(buf, " %s",
9957  }
9958  appendStringInfoString(buf, " NORMALIZED)");
9959  return true;
9960 
9961  case F_PG_COLLATION_FOR:
9962  /* COLLATION FOR */
9963  appendStringInfoString(buf, "COLLATION FOR (");
9964  get_rule_expr((Node *) linitial(expr->args), context, false);
9965  appendStringInfoChar(buf, ')');
9966  return true;
9967 
9968  /*
9969  * XXX EXTRACT, a/k/a date_part(), is intentionally not covered
9970  * yet. Add it after we change the return type to numeric.
9971  */
9972 
9973  case F_NORMALIZE:
9974  /* NORMALIZE() */
9975  appendStringInfoString(buf, "NORMALIZE(");
9976  get_rule_expr((Node *) linitial(expr->args), context, false);
9977  if (list_length(expr->args) == 2)
9978  {
9979  Const *con = (Const *) lsecond(expr->args);
9980 
9981  Assert(IsA(con, Const) &&
9982  con->consttype == TEXTOID &&
9983  !con->constisnull);
9984  appendStringInfo(buf, ", %s",
9986  }
9987  appendStringInfoChar(buf, ')');
9988  return true;
9989 
9990  case F_OVERLAY_BIT_BIT_INT4:
9991  case F_OVERLAY_BIT_BIT_INT4_INT4:
9992  case F_OVERLAY_BYTEA_BYTEA_INT4:
9993  case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
9994  case F_OVERLAY_TEXT_TEXT_INT4:
9995  case F_OVERLAY_TEXT_TEXT_INT4_INT4:
9996  /* OVERLAY() */
9997  appendStringInfoString(buf, "OVERLAY(");
9998  get_rule_expr((Node *) linitial(expr->args), context, false);
9999  appendStringInfoString(buf, " PLACING ");
10000  get_rule_expr((Node *) lsecond(expr->args), context, false);
10001  appendStringInfoString(buf, " FROM ");
10002  get_rule_expr((Node *) lthird(expr->args), context, false);
10003  if (list_length(expr->args) == 4)
10004  {
10005  appendStringInfoString(buf, " FOR ");
10006  get_rule_expr((Node *) lfourth(expr->args), context, false);
10007  }
10008  appendStringInfoChar(buf, ')');
10009  return true;
10010 
10011  case F_POSITION_BIT_BIT:
10012  case F_POSITION_BYTEA_BYTEA:
10013  case F_POSITION_TEXT_TEXT:
10014  /* POSITION() ... extra parens since args are b_expr not a_expr */
10015  appendStringInfoString(buf, "POSITION((");
10016  get_rule_expr((Node *) lsecond(expr->args), context, false);
10017  appendStringInfoString(buf, ") IN (");
10018  get_rule_expr((Node *) linitial(expr->args), context, false);
10019  appendStringInfoString(buf, "))");
10020  return true;
10021 
10022  case F_SUBSTRING_BIT_INT4:
10023  case F_SUBSTRING_BIT_INT4_INT4:
10024  case F_SUBSTRING_BYTEA_INT4:
10025  case F_SUBSTRING_BYTEA_INT4_INT4:
10026  case F_SUBSTRING_TEXT_INT4:
10027  case F_SUBSTRING_TEXT_INT4_INT4:
10028  /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
10029  appendStringInfoString(buf, "SUBSTRING(");
10030  get_rule_expr((Node *) linitial(expr->args), context, false);
10031  appendStringInfoString(buf, " FROM ");
10032  get_rule_expr((Node *) lsecond(expr->args), context, false);
10033  if (list_length(expr->args) == 3)
10034  {
10035  appendStringInfoString(buf, " FOR ");
10036  get_rule_expr((Node *) lthird(expr->args), context, false);
10037  }
10038  appendStringInfoChar(buf, ')');
10039  return true;
10040 
10041  case F_SUBSTRING_TEXT_TEXT_TEXT:
10042  /* SUBSTRING SIMILAR/ESCAPE */
10043  appendStringInfoString(buf, "SUBSTRING(");
10044  get_rule_expr((Node *) linitial(expr->args), context, false);
10045  appendStringInfoString(buf, " SIMILAR ");
10046  get_rule_expr((Node *) lsecond(expr->args), context, false);
10047  appendStringInfoString(buf, " ESCAPE ");
10048  get_rule_expr((Node *) lthird(expr->args), context, false);
10049  appendStringInfoChar(buf, ')');
10050  return true;
10051 
10052  case F_BTRIM_BYTEA_BYTEA:
10053  case F_BTRIM_TEXT:
10054  case F_BTRIM_TEXT_TEXT:
10055  /* TRIM() */
10056  appendStringInfoString(buf, "TRIM(BOTH");
10057  if (list_length(expr->args) == 2)
10058  {
10059  appendStringInfoChar(buf, ' ');
10060  get_rule_expr((Node *) lsecond(expr->args), context, false);
10061  }
10062  appendStringInfoString(buf, " FROM ");
10063  get_rule_expr((Node *) linitial(expr->args), context, false);
10064  appendStringInfoChar(buf, ')');
10065  return true;
10066 
10067  case F_LTRIM_BYTEA_BYTEA:
10068  case F_LTRIM_TEXT:
10069  case F_LTRIM_TEXT_TEXT:
10070  /* TRIM() */
10071  appendStringInfoString(buf, "TRIM(LEADING");
10072  if (list_length(expr->args) == 2)
10073  {
10074  appendStringInfoChar(buf, ' ');
10075  get_rule_expr((Node *) lsecond(expr->args), context, false);
10076  }
10077  appendStringInfoString(buf, " FROM ");
10078  get_rule_expr((Node *) linitial(expr->args), context, false);
10079  appendStringInfoChar(buf, ')');
10080  return true;
10081 
10082  case F_RTRIM_BYTEA_BYTEA:
10083  case F_RTRIM_TEXT:
10084  case F_RTRIM_TEXT_TEXT:
10085  /* TRIM() */
10086  appendStringInfoString(buf, "TRIM(TRAILING");
10087  if (list_length(expr->args) == 2)
10088  {
10089  appendStringInfoChar(buf, ' ');
10090  get_rule_expr((Node *) lsecond(expr->args), context, false);
10091  }
10092  appendStringInfoString(buf, " FROM ");
10093  get_rule_expr((Node *) linitial(expr->args), context, false);
10094  appendStringInfoChar(buf, ')');
10095  return true;
10096 
10097  case F_XMLEXISTS:
10098  /* XMLEXISTS ... extra parens because args are c_expr */
10099  appendStringInfoString(buf, "XMLEXISTS((");
10100  get_rule_expr((Node *) linitial(expr->args), context, false);
10101  appendStringInfoString(buf, ") PASSING (");
10102  get_rule_expr((Node *) lsecond(expr->args), context, false);
10103  appendStringInfoString(buf, "))");
10104  return true;
10105  }
10106  return false;
10107 }
Datum constvalue
Definition: primnodes.h:219
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
List * args
Definition: primnodes.h:503
Definition: nodes.h:539
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:83
#define Assert(condition)
Definition: c.h:804
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:8269
#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 6412 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().

6413 {
6414  StringInfo buf = context->buf;
6415  RangeTblEntry *select_rte = NULL;
6416  RangeTblEntry *values_rte = NULL;
6417  RangeTblEntry *rte;
6418  char *sep;
6419  ListCell *l;
6420  List *strippedexprs;
6421 
6422  /* Insert the WITH clause if given */
6423  get_with_clause(query, context);
6424 
6425  /*
6426  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6427  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6428  */
6429  foreach(l, query->rtable)
6430  {
6431  rte = (RangeTblEntry *) lfirst(l);
6432 
6433  if (rte->rtekind == RTE_SUBQUERY)
6434  {
6435  if (select_rte)
6436  elog(ERROR, "too many subquery RTEs in INSERT");
6437  select_rte = rte;
6438  }
6439 
6440  if (rte->rtekind == RTE_VALUES)
6441  {
6442  if (values_rte)
6443  elog(ERROR, "too many values RTEs in INSERT");
6444  values_rte = rte;
6445  }
6446  }
6447  if (select_rte && values_rte)
6448  elog(ERROR, "both subquery and values RTEs in INSERT");
6449 
6450  /*
6451  * Start the query with INSERT INTO relname
6452  */
6453  rte = rt_fetch(query->resultRelation, query->rtable);
6454  Assert(rte->rtekind == RTE_RELATION);
6455 
6456  if (PRETTY_INDENT(context))
6457  {
6458  context->indentLevel += PRETTYINDENT_STD;
6459  appendStringInfoChar(buf, ' ');
6460  }
6461  appendStringInfo(buf, "INSERT INTO %s ",
6463  /* INSERT requires AS keyword for target alias */
6464  if (rte->alias != NULL)
6465  appendStringInfo(buf, "AS %s ",
6467 
6468  /*
6469  * Add the insert-column-names list. Any indirection decoration needed on
6470  * the column names can be inferred from the top targetlist.
6471  */
6472  strippedexprs = NIL;
6473  sep = "";
6474  if (query->targetList)
6475  appendStringInfoChar(buf, '(');
6476  foreach(l, query->targetList)
6477  {
6478  TargetEntry *tle = (TargetEntry *) lfirst(l);
6479 
6480  if (tle->resjunk)
6481  continue; /* ignore junk entries */
6482 
6483  appendStringInfoString(buf, sep);
6484  sep = ", ";
6485 
6486  /*
6487  * Put out name of target column; look in the catalogs, not at
6488  * tle->resname, since resname will fail to track RENAME.
6489  */
6492  tle->resno,
6493  false)));
6494 
6495  /*
6496  * Print any indirection needed (subfields or subscripts), and strip
6497  * off the top-level nodes representing the indirection assignments.
6498  * Add the stripped expressions to strippedexprs. (If it's a
6499  * single-VALUES statement, the stripped expressions are the VALUES to
6500  * print below. Otherwise they're just Vars and not really
6501  * interesting.)
6502  */
6503  strippedexprs = lappend(strippedexprs,
6504  processIndirection((Node *) tle->expr,
6505  context));
6506  }
6507  if (query->targetList)
6508  appendStringInfoString(buf, ") ");
6509 
6510  if (query->override)
6511  {
6512  if (query->override == OVERRIDING_SYSTEM_VALUE)
6513  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6514  else if (query->override == OVERRIDING_USER_VALUE)
6515  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6516  }
6517 
6518  if (select_rte)
6519  {
6520  /* Add the SELECT */
6521  get_query_def(select_rte->subquery, buf, NIL, NULL,
6522  context->prettyFlags, context->wrapColumn,
6523  context->indentLevel);
6524  }
6525  else if (values_rte)
6526  {
6527  /* Add the multi-VALUES expression lists */
6528  get_values_def(values_rte->values_lists, context);
6529  }
6530  else if (strippedexprs)
6531  {
6532  /* Add the single-VALUES expression list */
6533  appendContextKeyword(context, "VALUES (",
6535  get_rule_expr((Node *) strippedexprs, context, false);
6536  appendStringInfoChar(buf, ')');
6537  }
6538  else
6539  {
6540  /* No expressions, so it must be DEFAULT VALUES */
6541  appendStringInfoString(buf, "DEFAULT VALUES");
6542  }
6543 
6544  /* Add ON CONFLICT if present */
6545  if (query->onConflict)
6546  {
6547  OnConflictExpr *confl = query->onConflict;
6548 
6549  appendStringInfoString(buf, " ON CONFLICT");
6550 
6551  if (confl->arbiterElems)
6552  {
6553  /* Add the single-VALUES expression list */
6554  appendStringInfoChar(buf, '(');
6555  get_rule_expr((Node *) confl->arbiterElems, context, false);
6556  appendStringInfoChar(buf, ')');
6557 
6558  /* Add a WHERE clause (for partial indexes) if given */
6559  if (confl->arbiterWhere != NULL)
6560  {
6561  bool save_varprefix;
6562 
6563  /*
6564  * Force non-prefixing of Vars, since parser assumes that they
6565  * belong to target relation. WHERE clause does not use
6566  * InferenceElem, so this is separately required.
6567  */
6568  save_varprefix = context->varprefix;
6569  context->varprefix = false;
6570 
6571  appendContextKeyword(context, " WHERE ",
6573  get_rule_expr(confl->arbiterWhere, context, false);
6574 
6575  context->varprefix = save_varprefix;
6576  }
6577  }
6578  else if (OidIsValid(confl->constraint))
6579  {
6580  char *constraint = get_constraint_name(confl->constraint);
6581 
6582  if (!constraint)
6583  elog(ERROR, "cache lookup failed for constraint %u",
6584  confl->constraint);
6585  appendStringInfo(buf, " ON CONSTRAINT %s",
6586  quote_identifier(constraint));
6587  }
6588 
6589  if (confl->action == ONCONFLICT_NOTHING)
6590  {
6591  appendStringInfoString(buf, " DO NOTHING");
6592  }
6593  else
6594  {
6595  appendStringInfoString(buf, " DO UPDATE SET ");
6596  /* Deparse targetlist */
6598  context, rte);
6599 
6600  /* Add a WHERE clause if given */
6601  if (confl->onConflictWhere != NULL)
6602  {
6603  appendContextKeyword(context, " WHERE ",
6605  get_rule_expr(confl->onConflictWhere, context, false);
6606  }
6607  }
6608  }
6609 
6610  /* Add RETURNING if present */
6611  if (query->returningList)
6612  {
6613  appendContextKeyword(context, " RETURNING",
6615  get_target_list(query->returningList, context, NULL);
6616  }
6617 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5363
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
Alias * alias
Definition: parsenodes.h:1140
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:11215
int resultRelation
Definition: parsenodes.h:130
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5833
Definition: nodes.h:539
#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:6680
#define OidIsValid(objectId)
Definition: c.h:710
List * values_lists
Definition: parsenodes.h:1100
List * targetList
Definition: parsenodes.h:150
List * arbiterElems
Definition: primnodes.h:1572
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11447
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1451
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:8164
AttrNumber resno
Definition: primnodes.h:1445
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:1569
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:8269
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1444
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5246
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5320
RTEKind rtekind
Definition: parsenodes.h:995
Node * arbiterWhere
Definition: primnodes.h:1574
Query * subquery
Definition: parsenodes.h:1030
StringInfo buf
Definition: ruleutils.c:110
#define elog(elevel,...)
Definition: elog.h:232
List * onConflictSet
Definition: primnodes.h:1578
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
Node * onConflictWhere
Definition: primnodes.h:1579
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 7284 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().

7286 {
7287  RangeTblEntry *rte;
7289  int netlevelsup;
7290  deparse_namespace *dpns;
7291  Index varno;
7292  AttrNumber varattno;
7293  TupleDesc tupleDesc;
7294  Node *expr;
7295 
7296  /*
7297  * If it's a RowExpr that was expanded from a whole-row Var, use the
7298  * column names attached to it.
7299  */
7300  if (IsA(var, RowExpr))
7301  {
7302  RowExpr *r = (RowExpr *) var;
7303 
7304  if (fieldno > 0 && fieldno <= list_length(r->colnames))
7305  return strVal(list_nth(r->colnames, fieldno - 1));
7306  }
7307 
7308  /*
7309  * If it's a Param of type RECORD, try to find what the Param refers to.
7310  */
7311  if (IsA(var, Param))
7312  {
7313  Param *param = (Param *) var;
7314  ListCell *ancestor_cell;
7315 
7316  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7317  if (expr)
7318  {
7319  /* Found a match, so recurse to decipher the field name */
7320  deparse_namespace save_dpns;
7321  const char *result;
7322 
7323  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7324  result = get_name_for_var_field((Var *) expr, fieldno,
7325  0, context);
7326  pop_ancestor_plan(dpns, &save_dpns);
7327  return result;
7328  }
7329  }
7330 
7331  /*
7332  * If it's a Var of type RECORD, we have to find what the Var refers to;
7333  * if not, we can use get_expr_result_tupdesc().
7334  */
7335  if (!IsA(var, Var) ||
7336  var->vartype != RECORDOID)
7337  {
7338  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7339  /* Got the tupdesc, so we can extract the field name */
7340  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7341  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7342  }
7343 
7344  /* Find appropriate nesting depth */
7345  netlevelsup = var->varlevelsup + levelsup;
7346  if (netlevelsup >= list_length(context->namespaces))
7347  elog(ERROR, "bogus varlevelsup: %d offset %d",
7348  var->varlevelsup, levelsup);
7349  dpns = (deparse_namespace *) list_nth(context->namespaces,
7350  netlevelsup);
7351 
7352  /*
7353  * If we have a syntactic referent for the Var, and we're working from a
7354  * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7355  * on the semantic referent. (See comments in get_variable().)
7356  */
7357  if (var->varnosyn > 0 && dpns->plan == NULL)
7358  {
7359  varno = var->varnosyn;
7360  varattno = var->varattnosyn;
7361  }
7362  else
7363  {
7364  varno = var->varno;
7365  varattno = var->varattno;
7366  }
7367 
7368  /*
7369  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7370  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7371  * down into the subplans, or INDEX_VAR, which is resolved similarly.
7372  *
7373  * Note: unlike get_variable and resolve_special_varno, we need not worry
7374  * about inheritance mapping: a child Var should have the same datatype as
7375  * its parent, and here we're really only interested in the Var's type.
7376  */
7377  if (varno >= 1 && varno <= list_length(dpns->rtable))
7378  {
7379  rte = rt_fetch(varno, dpns->rtable);
7380  attnum = varattno;
7381  }
7382  else if (varno == OUTER_VAR && dpns->outer_tlist)
7383  {
7384  TargetEntry *tle;
7385  deparse_namespace save_dpns;
7386  const char *result;
7387 
7388  tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7389  if (!tle)
7390  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7391 
7392  Assert(netlevelsup == 0);
7393  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7394 
7395  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7396  levelsup, context);
7397 
7398  pop_child_plan(dpns, &save_dpns);
7399  return result;
7400  }
7401  else if (varno == INNER_VAR && dpns->inner_tlist)
7402  {
7403  TargetEntry *tle;
7404  deparse_namespace save_dpns;
7405  const char *result;
7406 
7407  tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7408  if (!tle)
7409  elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7410 
7411  Assert(netlevelsup == 0);
7412  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7413 
7414  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7415  levelsup, context);
7416 
7417  pop_child_plan(dpns, &save_dpns);
7418  return result;
7419  }
7420  else if (varno == INDEX_VAR && dpns->index_tlist)
7421  {
7422  TargetEntry *tle;
7423  const char *result;
7424 
7425  tle = get_tle_by_resno(dpns->index_tlist, varattno);
7426  if (!tle)
7427  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7428 
7429  Assert(netlevelsup == 0);
7430 
7431  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7432  levelsup, context);
7433 
7434  return result;
7435  }
7436  else
7437  {
7438  elog(ERROR, "bogus varno: %d", varno);
7439  return NULL; /* keep compiler quiet */
7440  }
7441 
7442  if (attnum == InvalidAttrNumber)
7443  {
7444  /* Var is whole-row reference to RTE, so select the right field */
7445  return get_rte_attribute_name(rte, fieldno);
7446  }
7447 
7448  /*
7449  * This part has essentially the same logic as the parser's
7450  * expandRecordVariable() function, but we are dealing with a different
7451  * representation of the input context, and we only need one field name
7452  * not a TupleDesc. Also, we need special cases for finding subquery and
7453  * CTE subplans when deparsing Plan trees.
7454  */
7455  expr = (Node *) var; /* default if we can't drill down */
7456 
7457  switch (rte->rtekind)
7458  {
7459  case RTE_RELATION:
7460  case RTE_VALUES:
7461  case RTE_NAMEDTUPLESTORE:
7462  case RTE_RESULT:
7463 
7464  /*
7465  * This case should not occur: a column of a table, values list,
7466  * or ENR shouldn't have type RECORD. Fall through and fail (most
7467  * likely) at the bottom.
7468  */
7469  break;
7470  case RTE_SUBQUERY:
7471  /* Subselect-in-FROM: examine sub-select's output expr */
7472  {
7473  if (rte->subquery)
7474  {
7476  attnum);
7477 
7478  if (ste == NULL || ste->resjunk)
7479  elog(ERROR, "subquery %s does not have attribute %d",
7480  rte->eref->aliasname, attnum);
7481  expr = (Node *) ste->expr;
7482  if (IsA(expr, Var))
7483  {
7484  /*
7485  * Recurse into the sub-select to see what its Var
7486  * refers to. We have to build an additional level of
7487  * namespace to keep in step with varlevelsup in the
7488  * subselect.
7489  */
7490  deparse_namespace mydpns;
7491  const char *result;
7492 
7493  set_deparse_for_query(&mydpns, rte->subquery,
7494  context->namespaces);
7495 
7496  context->namespaces = lcons(&mydpns,
7497  context->namespaces);
7498 
7499  result = get_name_for_var_field((Var *) expr, fieldno,
7500  0, context);
7501 
7502  context->namespaces =
7503  list_delete_first(context->namespaces);
7504 
7505  return result;
7506  }
7507  /* else fall through to inspect the expression */
7508  }
7509  else
7510  {
7511  /*
7512  * We're deparsing a Plan tree so we don't have complete
7513  * RTE entries (in particular, rte->subquery is NULL). But
7514  * the only place we'd see a Var directly referencing a
7515  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7516  * look into the child plan's tlist instead.
7517  */
7518  TargetEntry *tle;
7519  deparse_namespace save_dpns;
7520  const char *result;
7521 
7522  if (!dpns->inner_plan)
7523  elog(ERROR, "failed to find plan for subquery %s",
7524  rte->eref->aliasname);
7525  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7526  if (!tle)
7527  elog(ERROR, "bogus varattno for subquery var: %d",
7528  attnum);
7529  Assert(netlevelsup == 0);
7530  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7531 
7532  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7533  levelsup, context);
7534 
7535  pop_child_plan(dpns, &save_dpns);
7536  return result;
7537  }
7538  }
7539  break;
7540  case RTE_JOIN:
7541  /* Join RTE --- recursively inspect the alias variable */
7542  if (rte->joinaliasvars == NIL)
7543  elog(ERROR, "cannot decompile join alias var in plan tree");
7544  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7545  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7546  Assert(expr != NULL);
7547  /* we intentionally don't strip implicit coercions here */
7548  if (IsA(expr, Var))
7549  return get_name_for_var_field((Var *) expr, fieldno,
7550  var->varlevelsup + levelsup,
7551  context);
7552  /* else fall through to inspect the expression */
7553  break;
7554  case RTE_FUNCTION:
7555  case RTE_TABLEFUNC:
7556 
7557  /*
7558  * We couldn't get here unless a function is declared with one of
7559  * its result columns as RECORD, which is not allowed.
7560  */
7561  break;
7562  case RTE_CTE:
7563  /* CTE reference: examine subquery's output expr */
7564  {
7565  CommonTableExpr *cte = NULL;
7566  Index ctelevelsup;
7567  ListCell *lc;
7568 
7569  /*
7570  * Try to find the referenced CTE using the namespace stack.
7571  */
7572  ctelevelsup = rte->ctelevelsup + netlevelsup;
7573  if (ctelevelsup >= list_length(context->namespaces))
7574  lc = NULL;
7575  else
7576  {
7577  deparse_namespace *ctedpns;
7578 
7579  ctedpns = (deparse_namespace *)
7580  list_nth(context->namespaces, ctelevelsup);
7581  foreach(lc, ctedpns->ctes)
7582  {
7583  cte = (CommonTableExpr *) lfirst(lc);
7584  if (strcmp(cte->ctename, rte->ctename) == 0)
7585  break;
7586  }
7587  }
7588  if (lc != NULL)
7589  {
7590  Query *ctequery = (Query *) cte->ctequery;
7592  attnum);
7593 
7594  if (ste == NULL || ste->resjunk)
7595  elog(ERROR, "subquery %s does not have attribute %d",
7596  rte->eref->aliasname, attnum);
7597  expr = (Node *) ste->expr;
7598  if (IsA(expr, Var))
7599  {
7600  /*
7601  * Recurse into the CTE to see what its Var refers to.
7602  * We have to build an additional level of namespace
7603  * to keep in step with varlevelsup in the CTE.
7604  * Furthermore it could be an outer CTE, so we may
7605  * have to delete some levels of namespace.
7606  */
7607  List *save_nslist = context->namespaces;
7608  List *new_nslist;
7609  deparse_namespace mydpns;
7610  const char *result;
7611 
7612  set_deparse_for_query(&mydpns, ctequery,
7613  context->namespaces);
7614 
7615  new_nslist = list_copy_tail(context->namespaces,
7616  ctelevelsup);
7617  context->namespaces = lcons(&mydpns, new_nslist);
7618 
7619  result = get_name_for_var_field((Var *) expr, fieldno,
7620  0, context);
7621 
7622  context->namespaces = save_nslist;
7623 
7624  return result;
7625  }
7626  /* else fall through to inspect the expression */
7627  }
7628  else
7629  {
7630  /*
7631  * We're deparsing a Plan tree so we don't have a CTE
7632  * list. But the only place we'd see a Var directly
7633  * referencing a CTE RTE is in a CteScan plan node, and we
7634  * can look into the subplan's tlist instead.
7635  */
7636  TargetEntry *tle;
7637  deparse_namespace save_dpns;
7638  const char *result;
7639 
7640  if (!dpns->inner_plan)
7641  elog(ERROR, "failed to find plan for CTE %s",
7642  rte->eref->aliasname);
7643  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7644  if (!tle)
7645  elog(ERROR, "bogus varattno for subquery var: %d",
7646  attnum);
7647  Assert(netlevelsup == 0);
7648  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7649 
7650  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7651  levelsup, context);
7652 
7653  pop_child_plan(dpns, &save_dpns);
7654  return result;
7655  }
7656  }
7657  break;
7658  }
7659 
7660  /*
7661  * We now have an expression we can't expand any more, so see if
7662  * get_expr_result_tupdesc() can do anything with it.
7663  */
7664  tupleDesc = get_expr_result_tupdesc(expr, false);
7665  /* Got the tupdesc, so we can extract the field name */
7666  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7667  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7668 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
List * joinaliasvars
Definition: parsenodes.h:1070
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:7679
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:539
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:191
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4966
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:1451
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
List * colnames
Definition: primnodes.h:1074
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
Index varno
Definition: primnodes.h:189
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:7284
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:4915
#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:4898
Expr * expr
Definition: primnodes.h:1444
static int list_length(const List *l)
Definition: pg_list.h:149
Index ctelevelsup
Definition: parsenodes.h:1106
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3853
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:995
char * ctename
Definition: parsenodes.h:1105
Query * subquery
Definition: parsenodes.h:1030
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:4945
#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:1141
#define INDEX_VAR
Definition: primnodes.h:177
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1519
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 11155 of file ruleutils.c.

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

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

11157 {
11158  HeapTuple ht_opc;
11159  Form_pg_opclass opcrec;
11160  char *opcname;
11161  char *nspname;
11162 
11163  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
11164  if (!HeapTupleIsValid(ht_opc))
11165  elog(ERROR, "cache lookup failed for opclass %u", opclass);
11166  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
11167 
11168  if (!OidIsValid(actual_datatype) ||
11169  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
11170  {
11171  /* Okay, we need the opclass name. Do we need to qualify it? */
11172  opcname = NameStr(opcrec->opcname);
11173  if (OpclassIsVisible(opclass))
11174  appendStringInfo(buf, " %s", quote_identifier(opcname));
11175  else
11176  {
11177  nspname = get_namespace_name(opcrec->opcnamespace);
11178  appendStringInfo(buf, " %s.%s",
11179  quote_identifier(nspname),
11180  quote_identifier(opcname));
11181  }
11182  }
11183  ReleaseSysCache(ht_opc);
11184 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2099
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11323
#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
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
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1832
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#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 9540 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().

9541 {
9542  StringInfo buf = context->buf;
9543  Oid opno = expr->opno;
9544  List *args = expr->args;
9545 
9546  if (!PRETTY_PAREN(context))
9547  appendStringInfoChar(buf, '(');
9548  if (list_length(args) == 2)
9549  {
9550  /* binary operator */
9551  Node *arg1 = (Node *) linitial(args);
9552  Node *arg2 = (Node *) lsecond(args);
9553 
9554  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9555  appendStringInfo(buf, " %s ",
9557  exprType(arg1),
9558  exprType(arg2)));
9559  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9560  }
9561  else
9562  {
9563  /* prefix operator */
9564  Node *arg = (Node *) linitial(args);
9565 
9566  appendStringInfo(buf, "%s ",
9568  InvalidOid,
9569  exprType(arg)));
9570  get_rule_expr_paren(arg, context, true, (Node *) expr);
9571  }
9572  if (!PRETTY_PAREN(context))
9573  appendStringInfoChar(buf, ')');
9574 }
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:8237
Definition: nodes.h:539
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:11654
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 7814 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().

7815 {
7816  Node *expr;
7817  deparse_namespace *dpns;
7818  ListCell *ancestor_cell;
7819 
7820  /*
7821  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7822  * the parameter was computed. Note that failing to find a referent isn't
7823  * an error, since the Param might well be a subplan output rather than an
7824  * input.
7825  */
7826  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7827  if (expr)
7828  {
7829  /* Found a match, so print it */
7830  deparse_namespace save_dpns;
7831  bool save_varprefix;
7832  bool need_paren;
7833 
7834  /* Switch attention to the ancestor plan node */
7835  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7836 
7837  /*
7838  * Force prefixing of Vars, since they won't belong to the relation
7839  * being scanned in the original plan node.
7840  */
7841  save_varprefix = context->varprefix;
7842  context->varprefix = true;
7843 
7844  /*
7845  * A Param's expansion is typically a Var, Aggref, or upper-level
7846  * Param, which wouldn't need extra parentheses. Otherwise, insert
7847  * parens to ensure the expression looks atomic.
7848  */
7849  need_paren = !(IsA(expr, Var) ||
7850  IsA(expr, Aggref) ||
7851  IsA(expr, Param));
7852  if (need_paren)
7853  appendStringInfoChar(context->buf, '(');
7854 
7855  get_rule_expr(expr, context, false);
7856 
7857  if (need_paren)
7858  appendStringInfoChar(context->buf, ')');
7859 
7860  context->varprefix = save_varprefix;
7861 
7862  pop_ancestor_plan(dpns, &save_dpns);
7863 
7864  return;
7865  }
7866 
7867  /*
7868  * If it's an external parameter, see if the outermost namespace provides
7869  * function argument names.
7870  */
7871  if (param->paramkind == PARAM_EXTERN)
7872  {
7873  dpns = lfirst(list_tail(context->namespaces));
7874  if (dpns->argnames)
7875  {
7876  char *argname = dpns->argnames[param->paramid - 1];
7877 
7878  if (argname)
7879  {
7880  bool should_qualify = false;
7881  ListCell *lc;
7882 
7883  /*
7884  * Qualify the parameter name if there are any other deparse
7885  * namespaces with range tables. This avoids qualifying in
7886  * trivial cases like "RETURN a + b", but makes it safe in all
7887  * other cases.
7888  */
7889  foreach(lc, context->