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 missing_ok)
 
static char * pg_get_partkeydef_worker (Oid relid, int prettyFlags, bool attrsOnly, bool missing_ok)
 
static char * pg_get_constraintdef_worker (Oid constraintId, bool fullCommand, int prettyFlags, bool missing_ok)
 
static textpg_get_expr_worker (text *expr, Oid relid, const char *relname, int prettyFlags)
 
static int print_function_arguments (StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults)
 
static void print_function_rettype (StringInfo buf, HeapTuple proctup)
 
static void print_function_trftypes (StringInfo buf, HeapTuple proctup)
 
static void set_rtable_names (deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
 
static void set_deparse_for_query (deparse_namespace *dpns, Query *query, List *parent_namespaces)
 
static void set_simple_column_names (deparse_namespace *dpns)
 
static bool has_dangerous_join_using (deparse_namespace *dpns, Node *jtnode)
 
static void set_using_names (deparse_namespace *dpns, Node *jtnode, List *parentUsing)
 
static void set_relation_column_names (deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
 
static void set_join_column_names (deparse_namespace *dpns, RangeTblEntry *rte, deparse_columns *colinfo)
 
static bool colname_is_unique (const char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
 
static char * make_colname_unique (char *colname, deparse_namespace *dpns, deparse_columns *colinfo)
 
static void expand_colnames_array_to (deparse_columns *colinfo, int n)
 
static void identify_join_columns (JoinExpr *j, RangeTblEntry *jrte, deparse_columns *colinfo)
 
static 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)
 
Datum pg_get_partkeydef (PG_FUNCTION_ARGS)
 
char * pg_get_partkeydef_columns (Oid relid, bool pretty)
 
Datum pg_get_partition_constraintdef (PG_FUNCTION_ARGS)
 
char * pg_get_partconstrdef_string (Oid partitionId, char *aliasname)
 
Datum pg_get_constraintdef (PG_FUNCTION_ARGS)
 
Datum pg_get_constraintdef_ext (PG_FUNCTION_ARGS)
 
char * pg_get_constraintdef_command (Oid constraintId)
 
Datum pg_get_expr (PG_FUNCTION_ARGS)
 
Datum pg_get_expr_ext (PG_FUNCTION_ARGS)
 
Datum pg_get_userbyid (PG_FUNCTION_ARGS)
 
Datum pg_get_serial_sequence (PG_FUNCTION_ARGS)
 
Datum pg_get_functiondef (PG_FUNCTION_ARGS)
 
Datum pg_get_function_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_identity_arguments (PG_FUNCTION_ARGS)
 
Datum pg_get_function_result (PG_FUNCTION_ARGS)
 
static bool is_input_argument (int nth, const char *argmodes)
 
Datum pg_get_function_arg_default (PG_FUNCTION_ARGS)
 
char * deparse_expression (Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
 
Listdeparse_context_for (const char *aliasname, Oid relid)
 
Listdeparse_context_for_plan_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 484 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 300 of file ruleutils.c.

Function Documentation

◆ add_cast_to()

static void add_cast_to ( StringInfo  buf,
Oid  typid 
)
static

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

11382 {
11383  HeapTuple typetup;
11384  Form_pg_type typform;
11385  char *typname;
11386  char *nspname;
11387 
11388  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11389  if (!HeapTupleIsValid(typetup))
11390  elog(ERROR, "cache lookup failed for type %u", typid);
11391  typform = (Form_pg_type) GETSTRUCT(typetup);
11392 
11393  typname = NameStr(typform->typname);
11394  nspname = get_namespace_name(typform->typnamespace);
11395 
11396  appendStringInfo(buf, "::%s.%s",
11397  quote_identifier(nspname), quote_identifier(typname));
11398 
11399  ReleaseSysCache(typetup);
11400 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
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:228
#define NameStr(name)
Definition: c.h:669

◆ appendContextKeyword()

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

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

7803 {
7804  StringInfo buf = context->buf;
7805 
7806  if (PRETTY_INDENT(context))
7807  {
7808  int indentAmount;
7809 
7810  context->indentLevel += indentBefore;
7811 
7812  /* remove any trailing spaces currently in the buffer ... */
7814  /* ... then add a newline and some spaces */
7815  appendStringInfoChar(buf, '\n');
7816 
7817  if (context->indentLevel < PRETTYINDENT_LIMIT)
7818  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7819  else
7820  {
7821  /*
7822  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7823  * to conserve horizontal space by reducing the per-level
7824  * indentation. For best results the scale factor here should
7825  * divide all the indent amounts that get added to indentLevel
7826  * (PRETTYINDENT_STD, etc). It's important that the indentation
7827  * not grow unboundedly, else deeply-nested trees use O(N^2)
7828  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7829  */
7830  indentAmount = PRETTYINDENT_LIMIT +
7831  (context->indentLevel - PRETTYINDENT_LIMIT) /
7832  (PRETTYINDENT_STD / 2);
7833  indentAmount %= PRETTYINDENT_LIMIT;
7834  /* scale/wrap logic affects indentLevel, but not indentPlus */
7835  indentAmount += indentPlus;
7836  }
7837  appendStringInfoSpaces(buf, indentAmount);
7838 
7840 
7841  context->indentLevel += indentAfter;
7842  if (context->indentLevel < 0)
7843  context->indentLevel = 0;
7844  }
7845  else
7847 }
#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:7855
#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:968
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 4362 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().

4364 {
4365  int i;
4366  ListCell *lc;
4367 
4368  /* Check against already-assigned column aliases within RTE */
4369  for (i = 0; i < colinfo->num_cols; i++)
4370  {
4371  char *oldname = colinfo->colnames[i];
4372 
4373  if (oldname && strcmp(oldname, colname) == 0)
4374  return false;
4375  }
4376 
4377  /*
4378  * If we're building a new_colnames array, check that too (this will be
4379  * partially but not completely redundant with the previous checks)
4380  */
4381  for (i = 0; i < colinfo->num_new_cols; i++)
4382  {
4383  char *oldname = colinfo->new_colnames[i];
4384 
4385  if (oldname && strcmp(oldname, colname) == 0)
4386  return false;
4387  }
4388 
4389  /* Also check against USING-column names that must be globally unique */
4390  foreach(lc, dpns->using_names)
4391  {
4392  char *oldname = (char *) lfirst(lc);
4393 
4394  if (strcmp(oldname, colname) == 0)
4395  return false;
4396  }
4397 
4398  /* Also check against names already assigned for parent-join USING cols */
4399  foreach(lc, colinfo->parentUsing)
4400  {
4401  char *oldname = (char *) lfirst(lc);
4402 
4403  if (strcmp(oldname, colname) == 0)
4404  return false;
4405  }
4406 
4407  return true;
4408 }
List * using_names
Definition: ruleutils.c:166
#define lfirst(lc)
Definition: pg_list.h:169
int i
List * parentUsing
Definition: ruleutils.c:260
char ** new_colnames
Definition: ruleutils.c:253
char ** colnames
Definition: ruleutils.c:236

◆ decompile_column_index_array()

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

Definition at line 2339 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2341 {
2342  Datum *keys;
2343  int nKeys;
2344  int j;
2345 
2346  /* Extract data from array of int16 */
2347  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2348  INT2OID, 2, true, TYPALIGN_SHORT,
2349  &keys, NULL, &nKeys);
2350 
2351  for (j = 0; j < nKeys; j++)
2352  {
2353  char *colName;
2354 
2355  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2356 
2357  if (j == 0)
2359  else
2360  appendStringInfo(buf, ", %s", quote_identifier(colName));
2361  }
2362 
2363  return nKeys;
2364 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
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:444
uintptr_t Datum
Definition: postgres.h:367
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c: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 3282 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(), transformPartitionBound(), and transformPartitionRangeBounds().

3283 {
3284  deparse_namespace *dpns;
3285  RangeTblEntry *rte;
3286 
3287  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3288 
3289  /* Build a minimal RTE for the rel */
3290  rte = makeNode(RangeTblEntry);
3291  rte->rtekind = RTE_RELATION;
3292  rte->relid = relid;
3293  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3295  rte->alias = makeAlias(aliasname, NIL);
3296  rte->eref = rte->alias;
3297  rte->lateral = false;
3298  rte->inh = false;
3299  rte->inFromCl = true;
3300 
3301  /* Build one-element rtable */
3302  dpns->rtable = list_make1(rte);
3303  dpns->subplans = NIL;
3304  dpns->ctes = NIL;
3305  dpns->appendrels = NULL;
3306  set_rtable_names(dpns, NIL, NULL);
3308 
3309  /* Return a one-deep namespace stack */
3310  return list_make1(dpns);
3311 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1119
#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:3448
void * palloc0(Size size)
Definition: mcxt.c:981
#define makeNode(_type_)
Definition: nodes.h:576
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3658
RTEKind rtekind
Definition: parsenodes.h:981
Alias * eref
Definition: parsenodes.h:1120

◆ deparse_context_for_plan_tree()

List* deparse_context_for_plan_tree ( PlannedStmt pstmt,
List rtable_names 
)

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

3328 {
3329  deparse_namespace *dpns;
3330 
3331  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3332 
3333  /* Initialize fields that stay the same across the whole plan tree */
3334  dpns->rtable = pstmt->rtable;
3335  dpns->rtable_names = rtable_names;
3336  dpns->subplans = pstmt->subplans;
3337  dpns->ctes = NIL;
3338  if (pstmt->appendRelations)
3339  {
3340  /* Set up the array, indexed by child relid */
3341  int ntables = list_length(dpns->rtable);
3342  ListCell *lc;
3343 
3344  dpns->appendrels = (AppendRelInfo **)
3345  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3346  foreach(lc, pstmt->appendRelations)
3347  {
3348  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3349  Index crelid = appinfo->child_relid;
3350 
3351  Assert(crelid > 0 && crelid <= ntables);
3352  Assert(dpns->appendrels[crelid] == NULL);
3353  dpns->appendrels[crelid] = appinfo;
3354  }
3355  }
3356  else
3357  dpns->appendrels = NULL; /* don't need it */
3358 
3359  /*
3360  * Set up column name aliases. We will get rather bogus results for join
3361  * RTEs, but that doesn't matter because plan trees don't contain any join
3362  * alias Vars.
3363  */
3365 
3366  /* Return a one-deep namespace stack */
3367  return list_make1(dpns);
3368 }
#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:981
unsigned int Index
Definition: c.h:537
List * subplans
Definition: plannodes.h:73
#define Assert(condition)
Definition: c.h:792
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:3658
Index child_relid
Definition: pathnodes.h:2239
List * appendRelations
Definition: plannodes.h:71

◆ deparse_expression()

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

Definition at line 3222 of file ruleutils.c.

References deparse_expression_pretty().

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

3224 {
3225  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3226  showimplicit, 0, 0);
3227 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3249

◆ deparse_expression_pretty()

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

Definition at line 3249 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(), and pg_get_partkeydef_worker().

3252 {
3254  deparse_context context;
3255 
3256  initStringInfo(&buf);
3257  context.buf = &buf;
3258  context.namespaces = dpcontext;
3259  context.windowClause = NIL;
3260  context.windowTList = NIL;
3261  context.varprefix = forceprefix;
3262  context.prettyFlags = prettyFlags;
3263  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3264  context.indentLevel = startIndent;
3265  context.special_exprkind = EXPR_KIND_NONE;
3266  context.appendparents = NULL;
3267 
3268  get_rule_expr(expr, &context, showimplicit);
3269 
3270  return buf.data;
3271 }
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:7906
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 4455 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().

4456 {
4457  if (n > colinfo->num_cols)
4458  {
4459  if (colinfo->colnames == NULL)
4460  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4461  else
4462  {
4463  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4464  n * sizeof(char *));
4465  memset(colinfo->colnames + colinfo->num_cols, 0,
4466  (n - colinfo->num_cols) * sizeof(char *));
4467  }
4468  colinfo->num_cols = n;
4469  }
4470 }
void * palloc0(Size size)
Definition: mcxt.c:981
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
char ** colnames
Definition: ruleutils.c:236

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

7362 {
7363  /* Initialize output parameters to prevent compiler warnings */
7364  *dpns_p = NULL;
7365  *ancestor_cell_p = NULL;
7366 
7367  /*
7368  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7369  * SubPlan argument. This will necessarily be in some ancestor of the
7370  * current expression's Plan node.
7371  */
7372  if (param->paramkind == PARAM_EXEC)
7373  {
7374  deparse_namespace *dpns;
7375  Plan *child_plan;
7376  bool in_same_plan_level;
7377  ListCell *lc;
7378 
7379  dpns = (deparse_namespace *) linitial(context->namespaces);
7380  child_plan = dpns->plan;
7381  in_same_plan_level = true;
7382 
7383  foreach(lc, dpns->ancestors)
7384  {
7385  Node *ancestor = (Node *) lfirst(lc);
7386  ListCell *lc2;
7387 
7388  /*
7389  * NestLoops transmit params to their inner child only; also, once
7390  * we've crawled up out of a subplan, this couldn't possibly be
7391  * the right match.
7392  */
7393  if (IsA(ancestor, NestLoop) &&
7394  child_plan == innerPlan(ancestor) &&
7395  in_same_plan_level)
7396  {
7397  NestLoop *nl = (NestLoop *) ancestor;
7398 
7399  foreach(lc2, nl->nestParams)
7400  {
7401  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7402 
7403  if (nlp->paramno == param->paramid)
7404  {
7405  /* Found a match, so return it */
7406  *dpns_p = dpns;
7407  *ancestor_cell_p = lc;
7408  return (Node *) nlp->paramval;
7409  }
7410  }
7411  }
7412 
7413  /*
7414  * If ancestor is a SubPlan, check the arguments it provides.
7415  */
7416  if (IsA(ancestor, SubPlan))
7417  {
7418  SubPlan *subplan = (SubPlan *) ancestor;
7419  ListCell *lc3;
7420  ListCell *lc4;
7421 
7422  forboth(lc3, subplan->parParam, lc4, subplan->args)
7423  {
7424  int paramid = lfirst_int(lc3);
7425  Node *arg = (Node *) lfirst(lc4);
7426 
7427  if (paramid == param->paramid)
7428  {
7429  /*
7430  * Found a match, so return it. But, since Vars in
7431  * the arg are to be evaluated in the surrounding
7432  * context, we have to point to the next ancestor item
7433  * that is *not* a SubPlan.
7434  */
7435  ListCell *rest;
7436 
7437  for_each_cell(rest, dpns->ancestors,
7438  lnext(dpns->ancestors, lc))
7439  {
7440  Node *ancestor2 = (Node *) lfirst(rest);
7441 
7442  if (!IsA(ancestor2, SubPlan))
7443  {
7444  *dpns_p = dpns;
7445  *ancestor_cell_p = rest;
7446  return arg;
7447  }
7448  }
7449  elog(ERROR, "SubPlan cannot be outermost ancestor");
7450  }
7451  }
7452 
7453  /* We have emerged from a subplan. */
7454  in_same_plan_level = false;
7455 
7456  /* SubPlan isn't a kind of Plan, so skip the rest */
7457  continue;
7458  }
7459 
7460  /*
7461  * Check to see if we're emerging from an initplan of the current
7462  * ancestor plan. Initplans never have any parParams, so no need
7463  * to search that list, but we need to know if we should reset
7464  * in_same_plan_level.
7465  */
7466  foreach(lc2, ((Plan *) ancestor)->initPlan)
7467  {
7468  SubPlan *subplan = castNode(SubPlan, lfirst(lc2));
7469 
7470  if (child_plan != (Plan *) list_nth(dpns->subplans,
7471  subplan->plan_id - 1))
7472  continue;
7473 
7474  /* No parameters to be had here. */
7475  Assert(subplan->parParam == NIL);
7476 
7477  /* We have emerged from an initplan. */
7478  in_same_plan_level = false;
7479  break;
7480  }
7481 
7482  /* No luck, crawl up to next ancestor */
7483  child_plan = (Plan *) ancestor;
7484  }
7485  }
7486 
7487  /* No referent found */
7488  return NULL;
7489 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:434
int plan_id
Definition: primnodes.h:730
List * nestParams
Definition: plannodes.h:703
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:405
ParamKind paramkind
Definition: primnodes.h:262
Definition: nodes.h:528
Var * paramval
Definition: plannodes.h:710
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:45
#define lfirst_int(lc)
Definition: pg_list.h:170
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
#define innerPlan(node)
Definition: plannodes.h:165
#define Assert(condition)
Definition: c.h:792
#define lfirst(lc)
Definition: pg_list.h:169
int paramid
Definition: primnodes.h:263
List * parParam
Definition: primnodes.h:750
#define elog(elevel,...)
Definition: elog.h:228
void * arg
List * args
Definition: primnodes.h:751

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

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

11547 {
11548  char *result = NULL;
11549  HeapTuple tuple;
11550  Datum reloptions;
11551  bool isnull;
11552 
11553  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11554  if (!HeapTupleIsValid(tuple))
11555  elog(ERROR, "cache lookup failed for relation %u", relid);
11556 
11557  reloptions = SysCacheGetAttr(RELOID, tuple,
11558  Anum_pg_class_reloptions, &isnull);
11559  if (!isnull)
11560  {
11562 
11563  initStringInfo(&buf);
11564  get_reloptions(&buf, reloptions);
11565 
11566  result = buf.data;
11567  }
11568 
11569  ReleaseSysCache(tuple);
11570 
11571  return result;
11572 }
static void get_reloptions(StringInfo buf, Datum reloptions)
Definition: ruleutils.c:11490
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
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:367
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:228

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

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

11446 {
11447  HeapTuple tp;
11448  Form_pg_collation colltup;
11449  char *collname;
11450  char *nspname;
11451  char *result;
11452 
11453  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11454  if (!HeapTupleIsValid(tp))
11455  elog(ERROR, "cache lookup failed for collation %u", collid);
11456  colltup = (Form_pg_collation) GETSTRUCT(tp);
11457  collname = NameStr(colltup->collname);
11458 
11459  if (!CollationIsVisible(collid))
11460  nspname = get_namespace_name(colltup->collnamespace);
11461  else
11462  nspname = NULL;
11463 
11464  result = quote_qualified_identifier(nspname, collname);
11465 
11466  ReleaseSysCache(tp);
11467 
11468  return result;
11469 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2047
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11017
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:47
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:669

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

11162 {
11163  char *result;
11164  HeapTuple proctup;
11165  Form_pg_proc procform;
11166  char *proname;
11167  bool use_variadic;
11168  char *nspname;
11169  FuncDetailCode p_result;
11170  Oid p_funcid;
11171  Oid p_rettype;
11172  bool p_retset;
11173  int p_nvargs;
11174  Oid p_vatype;
11175  Oid *p_true_typeids;
11176  bool force_qualify = false;
11177 
11178  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
11179  if (!HeapTupleIsValid(proctup))
11180  elog(ERROR, "cache lookup failed for function %u", funcid);
11181  procform = (Form_pg_proc) GETSTRUCT(proctup);
11182  proname = NameStr(procform->proname);
11183 
11184  /*
11185  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
11186  * qualification in some special cases.
11187  */
11188  if (special_exprkind == EXPR_KIND_GROUP_BY)
11189  {
11190  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
11191  force_qualify = true;
11192  }
11193 
11194  /*
11195  * Determine whether VARIADIC should be printed. We must do this first
11196  * since it affects the lookup rules in func_get_detail().
11197  *
11198  * We always print VARIADIC if the function has a merged variadic-array
11199  * argument. Note that this is always the case for functions taking a
11200  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
11201  * and printed the array elements as separate arguments, the call could
11202  * match a newer non-VARIADIC function.
11203  */
11204  if (use_variadic_p)
11205  {
11206  /* Parser should not have set funcvariadic unless fn is variadic */
11207  Assert(!has_variadic || OidIsValid(procform->provariadic));
11208  use_variadic = has_variadic;
11209  *use_variadic_p = use_variadic;
11210  }
11211  else
11212  {
11213  Assert(!has_variadic);
11214  use_variadic = false;
11215  }
11216 
11217  /*
11218  * The idea here is to schema-qualify only if the parser would fail to
11219  * resolve the correct function given the unqualified func name with the
11220  * specified argtypes and VARIADIC flag. But if we already decided to
11221  * force qualification, then we can skip the lookup and pretend we didn't
11222  * find it.
11223  */
11224  if (!force_qualify)
11225  p_result = func_get_detail(list_make1(makeString(proname)),
11226  NIL, argnames, nargs, argtypes,
11227  !use_variadic, true,
11228  &p_funcid, &p_rettype,
11229  &p_retset, &p_nvargs, &p_vatype,
11230  &p_true_typeids, NULL);
11231  else
11232  {
11233  p_result = FUNCDETAIL_NOTFOUND;
11234  p_funcid = InvalidOid;
11235  }
11236 
11237  if ((p_result == FUNCDETAIL_NORMAL ||
11238  p_result == FUNCDETAIL_AGGREGATE ||
11239  p_result == FUNCDETAIL_WINDOWFUNC) &&
11240  p_funcid == funcid)
11241  nspname = NULL;
11242  else
11243  nspname = get_namespace_name(procform->pronamespace);
11244 
11245  result = quote_qualified_identifier(nspname, proname);
11246 
11247  ReleaseSysCache(proctup);
11248 
11249  return result;
11250 }
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:655
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
#define list_make1(x1)
Definition: pg_list.h:206
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11017
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:133
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
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:1386
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:669

◆ generate_opclass_name()

char* generate_opclass_name ( Oid  opclass)

Definition at line 10803 of file ruleutils.c.

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

Referenced by index_opclass_options().

10804 {
10806 
10807  initStringInfo(&buf);
10808  get_opclass_name(opclass, InvalidOid, &buf);
10809 
10810  return &buf.data[1]; /* get_opclass_name() prepends space */
10811 }
static char * buf
Definition: pg_test_fsync.c:68
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:10765
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 11341 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().

11345 {
11346  HeapTuple opertup;
11347  Form_pg_operator operform;
11348  char *oprname;
11349  char *nspname;
11350 
11351  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11352  if (!HeapTupleIsValid(opertup))
11353  elog(ERROR, "cache lookup failed for operator %u", opoid);
11354  operform = (Form_pg_operator) GETSTRUCT(opertup);
11355  Assert(operform->oprkind == 'b');
11356  oprname = NameStr(operform->oprname);
11357 
11358  nspname = get_namespace_name(operform->oprnamespace);
11359 
11360  appendStringInfoString(buf, leftop);
11361  if (leftoptype != operform->oprleft)
11362  add_cast_to(buf, operform->oprleft);
11363  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11364  appendStringInfoString(buf, oprname);
11365  appendStringInfo(buf, ") %s", rightop);
11366  if (rightoptype != operform->oprright)
11367  add_cast_to(buf, operform->oprright);
11368 
11369  ReleaseSysCache(opertup);
11370 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11381
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
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:792
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:669

◆ generate_operator_name()

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

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

11265 {
11267  HeapTuple opertup;
11268  Form_pg_operator operform;
11269  char *oprname;
11270  char *nspname;
11271  Operator p_result;
11272 
11273  initStringInfo(&buf);
11274 
11275  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11276  if (!HeapTupleIsValid(opertup))
11277  elog(ERROR, "cache lookup failed for operator %u", operid);
11278  operform = (Form_pg_operator) GETSTRUCT(opertup);
11279  oprname = NameStr(operform->oprname);
11280 
11281  /*
11282  * The idea here is to schema-qualify only if the parser would fail to
11283  * resolve the correct operator given the unqualified op name with the
11284  * specified argtypes.
11285  */
11286  switch (operform->oprkind)
11287  {
11288  case 'b':
11289  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11290  true, -1);
11291  break;
11292  case 'l':
11293  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11294  true, -1);
11295  break;
11296  default:
11297  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11298  p_result = NULL; /* keep compiler quiet */
11299  break;
11300  }
11301 
11302  if (p_result != NULL && oprid(p_result) == operid)
11303  nspname = NULL;
11304  else
11305  {
11306  nspname = get_namespace_name(operform->oprnamespace);
11307  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11308  }
11309 
11310  appendStringInfoString(&buf, oprname);
11311 
11312  if (nspname)
11313  appendStringInfoChar(&buf, ')');
11314 
11315  if (p_result != NULL)
11316  ReleaseSysCache(p_result);
11317 
11318  ReleaseSysCache(opertup);
11319 
11320  return buf.data;
11321 }
Value * makeString(char *str)
Definition: value.c:53
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
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:507
#define ERROR
Definition: elog.h:45
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:3289
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:228
#define NameStr(name)
Definition: c.h:669
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 11117 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().

11118 {
11119  HeapTuple tp;
11120  Form_pg_class reltup;
11121  char *relname;
11122  char *nspname;
11123  char *result;
11124 
11125  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11126  if (!HeapTupleIsValid(tp))
11127  elog(ERROR, "cache lookup failed for relation %u", relid);
11128  reltup = (Form_pg_class) GETSTRUCT(tp);
11129  relname = NameStr(reltup->relname);
11130 
11131  nspname = get_namespace_name(reltup->relnamespace);
11132  if (!nspname)
11133  elog(ERROR, "cache lookup failed for namespace %u",
11134  reltup->relnamespace);
11135 
11136  result = quote_qualified_identifier(nspname, relname);
11137 
11138  ReleaseSysCache(tp);
11139 
11140  return result;
11141 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:38
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11017
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:228
#define NameStr(name)
Definition: c.h:669

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

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

11413 {
11414  HeapTuple tp;
11415  Form_pg_type typtup;
11416  char *typname;
11417  char *nspname;
11418  char *result;
11419 
11421  if (!HeapTupleIsValid(tp))
11422  elog(ERROR, "cache lookup failed for type %u", typid);
11423  typtup = (Form_pg_type) GETSTRUCT(tp);
11424  typname = NameStr(typtup->typname);
11425 
11426  nspname = get_namespace_name(typtup->typnamespace);
11427  if (!nspname)
11428  elog(ERROR, "cache lookup failed for namespace %u",
11429  typtup->typnamespace);
11430 
11431  result = quote_qualified_identifier(nspname, typname);
11432 
11433  ReleaseSysCache(tp);
11434 
11435  return result;
11436 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
NameData typname
Definition: pg_type.h:41
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11017
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:228
#define NameStr(name)
Definition: c.h:669

◆ generate_relation_name()

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

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

11058 {
11059  HeapTuple tp;
11060  Form_pg_class reltup;
11061  bool need_qual;
11062  ListCell *nslist;
11063  char *relname;
11064  char *nspname;
11065  char *result;
11066 
11067  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11068  if (!HeapTupleIsValid(tp))
11069  elog(ERROR, "cache lookup failed for relation %u", relid);
11070  reltup = (Form_pg_class) GETSTRUCT(tp);
11071  relname = NameStr(reltup->relname);
11072 
11073  /* Check for conflicting CTE name */
11074  need_qual = false;
11075  foreach(nslist, namespaces)
11076  {
11077  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
11078  ListCell *ctlist;
11079 
11080  foreach(ctlist, dpns->ctes)
11081  {
11082  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
11083 
11084  if (strcmp(cte->ctename, relname) == 0)
11085  {
11086  need_qual = true;
11087  break;
11088  }
11089  }
11090  if (need_qual)
11091  break;
11092  }
11093 
11094  /* Otherwise, qualify the name if not visible in search path */
11095  if (!need_qual)
11096  need_qual = !RelationIsVisible(relid);
11097 
11098  if (need_qual)
11099  nspname = get_namespace_name(reltup->relnamespace);
11100  else
11101  nspname = NULL;
11102 
11103  result = quote_qualified_identifier(nspname, relname);
11104 
11105  ReleaseSysCache(tp);
11106 
11107  return result;
11108 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:38
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11017
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:228
#define NameStr(name)
Definition: c.h:669

◆ get_agg_combine_expr()

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

Definition at line 9420 of file ruleutils.c.

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

Referenced by get_agg_expr().

9421 {
9422  Aggref *aggref;
9423  Aggref *original_aggref = callback_arg;
9424 
9425  if (!IsA(node, Aggref))
9426  elog(ERROR, "combining Aggref does not point to an Aggref");
9427 
9428  aggref = (Aggref *) node;
9429  get_agg_expr(aggref, context, original_aggref);
9430 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define ERROR
Definition: elog.h:45
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9313
#define elog(elevel,...)
Definition: elog.h:228

◆ get_agg_expr()

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

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

9315 {
9316  StringInfo buf = context->buf;
9317  Oid argtypes[FUNC_MAX_ARGS];
9318  int nargs;
9319  bool use_variadic;
9320 
9321  /*
9322  * For a combining aggregate, we look up and deparse the corresponding
9323  * partial aggregate instead. This is necessary because our input
9324  * argument list has been replaced; the new argument list always has just
9325  * one element, which will point to a partial Aggref that supplies us with
9326  * transition states to combine.
9327  */
9328  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9329  {
9330  TargetEntry *tle;
9331 
9332  Assert(list_length(aggref->args) == 1);
9333  tle = linitial_node(TargetEntry, aggref->args);
9334  resolve_special_varno((Node *) tle->expr, context,
9335  get_agg_combine_expr, original_aggref);
9336  return;
9337  }
9338 
9339  /*
9340  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9341  * to avoid printing this when recursing from the code just above.
9342  */
9343  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9344  appendStringInfoString(buf, "PARTIAL ");
9345 
9346  /* Extract the argument types as seen by the parser */
9347  nargs = get_aggregate_argtypes(aggref, argtypes);
9348 
9349  /* Print the aggregate name, schema-qualified if needed */
9350  appendStringInfo(buf, "%s(%s",
9351  generate_function_name(aggref->aggfnoid, nargs,
9352  NIL, argtypes,
9353  aggref->aggvariadic,
9354  &use_variadic,
9355  context->special_exprkind),
9356  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9357 
9358  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9359  {
9360  /*
9361  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9362  * worry about inserting VARIADIC. So we can just dump the direct
9363  * args as-is.
9364  */
9365  Assert(!aggref->aggvariadic);
9366  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9367  Assert(aggref->aggorder != NIL);
9368  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9369  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9370  }
9371  else
9372  {
9373  /* aggstar can be set only in zero-argument aggregates */
9374  if (aggref->aggstar)
9375  appendStringInfoChar(buf, '*');
9376  else
9377  {
9378  ListCell *l;
9379  int i;
9380 
9381  i = 0;
9382  foreach(l, aggref->args)
9383  {
9384  TargetEntry *tle = (TargetEntry *) lfirst(l);
9385  Node *arg = (Node *) tle->expr;
9386 
9387  Assert(!IsA(arg, NamedArgExpr));
9388  if (tle->resjunk)
9389  continue;
9390  if (i++ > 0)
9391  appendStringInfoString(buf, ", ");
9392  if (use_variadic && i == nargs)
9393  appendStringInfoString(buf, "VARIADIC ");
9394  get_rule_expr(arg, context, true);
9395  }
9396  }
9397 
9398  if (aggref->aggorder != NIL)
9399  {
9400  appendStringInfoString(buf, " ORDER BY ");
9401  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9402  }
9403  }
9404 
9405  if (aggref->aggfilter != NULL)
9406  {
9407  appendStringInfoString(buf, ") FILTER (WHERE ");
9408  get_rule_expr((Node *) aggref->aggfilter, context, false);
9409  }
9410 
9411  appendStringInfoChar(buf, ')');
9412 }
static void resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
Definition: ruleutils.c:6857
List * aggdistinct
Definition: primnodes.h:327
#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:11159
bool aggvariadic
Definition: primnodes.h:330
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5894
Definition: nodes.h:528
List * args
Definition: primnodes.h:325
bool aggstar
Definition: primnodes.h:329
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:790
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1438
static void get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:9420
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:326
List * aggdirectargs
Definition: primnodes.h:324
ParseExprKind special_exprkind
Definition: ruleutils.c:118
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
Oid aggfnoid
Definition: primnodes.h:318
#define Assert(condition)
Definition: c.h:792
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1431
AggSplit aggsplit
Definition: primnodes.h:334
static int list_length(const List *l)
Definition: pg_list.h:149
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:791
Expr * aggfilter
Definition: primnodes.h:328
StringInfo buf
Definition: ruleutils.c:110
int i
void * arg
char aggkind
Definition: primnodes.h:332
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1819

◆ get_basic_select_query()

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

Definition at line 5387 of file ruleutils.c.

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

Referenced by get_select_query_def().

5389 {
5390  StringInfo buf = context->buf;
5391  RangeTblEntry *values_rte;
5392  char *sep;
5393  ListCell *l;
5394 
5395  if (PRETTY_INDENT(context))
5396  {
5397  context->indentLevel += PRETTYINDENT_STD;
5398  appendStringInfoChar(buf, ' ');
5399  }
5400 
5401  /*
5402  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5403  * VALUES part. This reverses what transformValuesClause() did at parse
5404  * time.
5405  */
5406  values_rte = get_simple_values_rte(query, resultDesc);
5407  if (values_rte)
5408  {
5409  get_values_def(values_rte->values_lists, context);
5410  return;
5411  }
5412 
5413  /*
5414  * Build up the query string - first we say SELECT
5415  */
5416  appendStringInfoString(buf, "SELECT");
5417 
5418  /* Add the DISTINCT clause if given */
5419  if (query->distinctClause != NIL)
5420  {
5421  if (query->hasDistinctOn)
5422  {
5423  appendStringInfoString(buf, " DISTINCT ON (");
5424  sep = "";
5425  foreach(l, query->distinctClause)
5426  {
5427  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5428 
5429  appendStringInfoString(buf, sep);
5431  false, context);
5432  sep = ", ";
5433  }
5434  appendStringInfoChar(buf, ')');
5435  }
5436  else
5437  appendStringInfoString(buf, " DISTINCT");
5438  }
5439 
5440  /* Then we tell what to select (the targetlist) */
5441  get_target_list(query->targetList, context, resultDesc);
5442 
5443  /* Add the FROM clause if needed */
5444  get_from_clause(query, " FROM ", context);
5445 
5446  /* Add the WHERE clause if given */
5447  if (query->jointree->quals != NULL)
5448  {
5449  appendContextKeyword(context, " WHERE ",
5451  get_rule_expr(query->jointree->quals, context, false);
5452  }
5453 
5454  /* Add the GROUP BY clause if given */
5455  if (query->groupClause != NULL || query->groupingSets != NULL)
5456  {
5457  ParseExprKind save_exprkind;
5458 
5459  appendContextKeyword(context, " GROUP BY ",
5461 
5462  save_exprkind = context->special_exprkind;
5464 
5465  if (query->groupingSets == NIL)
5466  {
5467  sep = "";
5468  foreach(l, query->groupClause)
5469  {
5470  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5471 
5472  appendStringInfoString(buf, sep);
5474  false, context);
5475  sep = ", ";
5476  }
5477  }
5478  else
5479  {
5480  sep = "";
5481  foreach(l, query->groupingSets)
5482  {
5483  GroupingSet *grp = lfirst(l);
5484 
5485  appendStringInfoString(buf, sep);
5486  get_rule_groupingset(grp, query->targetList, true, context);
5487  sep = ", ";
5488  }
5489  }
5490 
5491  context->special_exprkind = save_exprkind;
5492  }
5493 
5494  /* Add the HAVING clause if given */
5495  if (query->havingQual != NULL)
5496  {
5497  appendContextKeyword(context, " HAVING ",
5499  get_rule_expr(query->havingQual, context, false);
5500  }
5501 
5502  /* Add the WINDOW clause if needed */
5503  if (query->windowClause != NIL)
5504  get_rule_windowclause(query, context);
5505 }
#define NIL
Definition: pg_list.h:65
FromExpr * jointree
Definition: parsenodes.h:138
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5514
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5778
Index tleSortGroupRef
Definition: parsenodes.h:1262
List * groupingSets
Definition: parsenodes.h:150
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10201
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5952
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
ParseExprKind
Definition: parse_node.h:38
List * values_lists
Definition: parsenodes.h:1079
Node * quals
Definition: primnodes.h:1535
bool hasDistinctOn
Definition: parsenodes.h:129
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * distinctClause
Definition: parsenodes.h:156
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c: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:7801
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5318
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5834
#define PRETTYINDENT_STD
Definition: ruleutils.c:82
ParseExprKind special_exprkind
Definition: ruleutils.c:118
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#define lfirst(lc)
Definition: pg_list.h:169
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5064
List * groupClause
Definition: parsenodes.h:148
StringInfo buf
Definition: ruleutils.c:110
Node * havingQual
Definition: parsenodes.h:152

◆ get_coercion_expr()

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

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

9733 {
9734  StringInfo buf = context->buf;
9735 
9736  /*
9737  * Since parse_coerce.c doesn't immediately collapse application of
9738  * length-coercion functions to constants, what we'll typically see in
9739  * such cases is a Const with typmod -1 and a length-coercion function
9740  * right above it. Avoid generating redundant output. However, beware of
9741  * suppressing casts when the user actually wrote something like
9742  * 'foo'::text::char(3).
9743  *
9744  * Note: it might seem that we are missing the possibility of needing to
9745  * print a COLLATE clause for such a Const. However, a Const could only
9746  * have nondefault collation in a post-constant-folding tree, in which the
9747  * length coercion would have been folded too. See also the special
9748  * handling of CollateExpr in coerce_to_target_type(): any collation
9749  * marking will be above the coercion node, not below it.
9750  */
9751  if (arg && IsA(arg, Const) &&
9752  ((Const *) arg)->consttype == resulttype &&
9753  ((Const *) arg)->consttypmod == -1)
9754  {
9755  /* Show the constant without normal ::typename decoration */
9756  get_const_expr((Const *) arg, context, -1);
9757  }
9758  else
9759  {
9760  if (!PRETTY_PAREN(context))
9761  appendStringInfoChar(buf, '(');
9762  get_rule_expr_paren(arg, context, false, parentNode);
9763  if (!PRETTY_PAREN(context))
9764  appendStringInfoChar(buf, ')');
9765  }
9766 
9767  /*
9768  * Never emit resulttype(arg) functional notation. A pg_proc entry could
9769  * take precedence, and a resulttype in pg_temp would require schema
9770  * qualification that format_type_with_typemod() would usually omit. We've
9771  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
9772  * would work fine.
9773  */
9774  appendStringInfo(buf, "::%s",
9775  format_type_with_typemod(resulttype, resulttypmod));
9776 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7874
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9794
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 10630 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().

10631 {
10632  StringInfo buf = context->buf;
10633  int i;
10634  bool first = true;
10635 
10636  /* Don't print aliases if not needed */
10637  if (!colinfo->printaliases)
10638  return;
10639 
10640  for (i = 0; i < colinfo->num_new_cols; i++)
10641  {
10642  char *colname = colinfo->new_colnames[i];
10643 
10644  if (first)
10645  {
10646  appendStringInfoChar(buf, '(');
10647  first = false;
10648  }
10649  else
10650  appendStringInfoString(buf, ", ");
10652  }
10653  if (!first)
10654  appendStringInfoChar(buf, ')');
10655 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
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:253

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9925 {
9926  StringInfo buf = context->buf;
9927 
9928  if (OidIsValid(constval->constcollid))
9929  {
9930  Oid typcollation = get_typcollation(constval->consttype);
9931 
9932  if (constval->constcollid != typcollation)
9933  {
9934  appendStringInfo(buf, " COLLATE %s",
9936  }
9937  }
9938 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11445
Oid consttype
Definition: primnodes.h:210
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
Oid constcollid
Definition: primnodes.h:212
static char * buf
Definition: pg_test_fsync.c:68
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2976
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 9794 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().

9795 {
9796  StringInfo buf = context->buf;
9797  Oid typoutput;
9798  bool typIsVarlena;
9799  char *extval;
9800  bool needlabel = false;
9801 
9802  if (constval->constisnull)
9803  {
9804  /*
9805  * Always label the type of a NULL constant to prevent misdecisions
9806  * about type when reparsing.
9807  */
9808  appendStringInfoString(buf, "NULL");
9809  if (showtype >= 0)
9810  {
9811  appendStringInfo(buf, "::%s",
9813  constval->consttypmod));
9814  get_const_collation(constval, context);
9815  }
9816  return;
9817  }
9818 
9819  getTypeOutputInfo(constval->consttype,
9820  &typoutput, &typIsVarlena);
9821 
9822  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9823 
9824  switch (constval->consttype)
9825  {
9826  case INT4OID:
9827 
9828  /*
9829  * INT4 can be printed without any decoration, unless it is
9830  * negative; in that case print it as '-nnn'::integer to ensure
9831  * that the output will re-parse as a constant, not as a constant
9832  * plus operator. In most cases we could get away with printing
9833  * (-nnn) instead, because of the way that gram.y handles negative
9834  * literals; but that doesn't work for INT_MIN, and it doesn't
9835  * seem that much prettier anyway.
9836  */
9837  if (extval[0] != '-')
9838  appendStringInfoString(buf, extval);
9839  else
9840  {
9841  appendStringInfo(buf, "'%s'", extval);
9842  needlabel = true; /* we must attach a cast */
9843  }
9844  break;
9845 
9846  case NUMERICOID:
9847 
9848  /*
9849  * NUMERIC can be printed without quotes if it looks like a float
9850  * constant (not an integer, and not Infinity or NaN) and doesn't
9851  * have a leading sign (for the same reason as for INT4).
9852  */
9853  if (isdigit((unsigned char) extval[0]) &&
9854  strcspn(extval, "eE.") != strlen(extval))
9855  {
9856  appendStringInfoString(buf, extval);
9857  }
9858  else
9859  {
9860  appendStringInfo(buf, "'%s'", extval);
9861  needlabel = true; /* we must attach a cast */
9862  }
9863  break;
9864 
9865  case BOOLOID:
9866  if (strcmp(extval, "t") == 0)
9867  appendStringInfoString(buf, "true");
9868  else
9869  appendStringInfoString(buf, "false");
9870  break;
9871 
9872  default:
9873  simple_quote_literal(buf, extval);
9874  break;
9875  }
9876 
9877  pfree(extval);
9878 
9879  if (showtype < 0)
9880  return;
9881 
9882  /*
9883  * For showtype == 0, append ::typename unless the constant will be
9884  * implicitly typed as the right type when it is read in.
9885  *
9886  * XXX this code has to be kept in sync with the behavior of the parser,
9887  * especially make_const.
9888  */
9889  switch (constval->consttype)
9890  {
9891  case BOOLOID:
9892  case UNKNOWNOID:
9893  /* These types can be left unlabeled */
9894  needlabel = false;
9895  break;
9896  case INT4OID:
9897  /* We determined above whether a label is needed */
9898  break;
9899  case NUMERICOID:
9900 
9901  /*
9902  * Float-looking constants will be typed as numeric, which we
9903  * checked above; but if there's a nondefault typmod we need to
9904  * show it.
9905  */
9906  needlabel |= (constval->consttypmod >= 0);
9907  break;
9908  default:
9909  needlabel = true;
9910  break;
9911  }
9912  if (needlabel || showtype > 0)
9913  appendStringInfo(buf, "::%s",
9915  constval->consttypmod));
9916 
9917  get_const_collation(constval, context);
9918 }
Datum constvalue
Definition: primnodes.h:214
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2827
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:210
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9944
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9924
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:211
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1656
StringInfo buf
Definition: ruleutils.c:110
bool constisnull
Definition: primnodes.h:215

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6514 {
6515  StringInfo buf = context->buf;
6516  RangeTblEntry *rte;
6517 
6518  /* Insert the WITH clause if given */
6519  get_with_clause(query, context);
6520 
6521  /*
6522  * Start the query with DELETE FROM relname
6523  */
6524  rte = rt_fetch(query->resultRelation, query->rtable);
6525  Assert(rte->rtekind == RTE_RELATION);
6526  if (PRETTY_INDENT(context))
6527  {
6528  appendStringInfoChar(buf, ' ');
6529  context->indentLevel += PRETTYINDENT_STD;
6530  }
6531  appendStringInfo(buf, "DELETE FROM %s%s",
6532  only_marker(rte),
6534  if (rte->alias != NULL)
6535  appendStringInfo(buf, " %s",
6537 
6538  /* Add the USING clause if given */
6539  get_from_clause(query, " USING ", context);
6540 
6541  /* Add a WHERE clause if given */
6542  if (query->jointree->quals != NULL)
6543  {
6544  appendContextKeyword(context, " WHERE ",
6546  get_rule_expr(query->jointree->quals, context, false);
6547  }
6548 
6549  /* Add RETURNING if present */
6550  if (query->returningList)
6551  {
6552  appendContextKeyword(context, " RETURNING",
6554  get_target_list(query->returningList, context, NULL);
6555  }
6556 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5107
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
Alias * alias
Definition: parsenodes.h:1119
FromExpr * jointree
Definition: parsenodes.h:138
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5514
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10201
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
Node * quals
Definition: primnodes.h:1535
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
List * rtable
Definition: parsenodes.h:137
static char * buf
Definition: pg_test_fsync.c:68
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7801
List * returningList
Definition: parsenodes.h:146
#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:792
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:484
RTEKind rtekind
Definition: parsenodes.h:981
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 10201 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().

10202 {
10203  StringInfo buf = context->buf;
10204  bool first = true;
10205  ListCell *l;
10206 
10207  /*
10208  * We use the query's jointree as a guide to what to print. However, we
10209  * must ignore auto-added RTEs that are marked not inFromCl. (These can
10210  * only appear at the top level of the jointree, so it's sufficient to
10211  * check here.) This check also ensures we ignore the rule pseudo-RTEs
10212  * for NEW and OLD.
10213  */
10214  foreach(l, query->jointree->fromlist)
10215  {
10216  Node *jtnode = (Node *) lfirst(l);
10217 
10218  if (IsA(jtnode, RangeTblRef))
10219  {
10220  int varno = ((RangeTblRef *) jtnode)->rtindex;
10221  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10222 
10223  if (!rte->inFromCl)
10224  continue;
10225  }
10226 
10227  if (first)
10228  {
10229  appendContextKeyword(context, prefix,
10231  first = false;
10232 
10233  get_from_clause_item(jtnode, query, context);
10234  }
10235  else
10236  {
10237  StringInfoData itembuf;
10238 
10239  appendStringInfoString(buf, ", ");
10240 
10241  /*
10242  * Put the new FROM item's text into itembuf so we can decide
10243  * after we've got it whether or not it needs to go on a new line.
10244  */
10245  initStringInfo(&itembuf);
10246  context->buf = &itembuf;
10247 
10248  get_from_clause_item(jtnode, query, context);
10249 
10250  /* Restore context's output buffer */
10251  context->buf = buf;
10252 
10253  /* Consider line-wrapping if enabled */
10254  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10255  {
10256  /* Does the new item start with a new line? */
10257  if (itembuf.len > 0 && itembuf.data[0] == '\n')
10258  {
10259  /* If so, we shouldn't add anything */
10260  /* instead, remove any trailing spaces currently in buf */
10262  }
10263  else
10264  {
10265  char *trailing_nl;
10266 
10267  /* Locate the start of the current line in the buffer */
10268  trailing_nl = strrchr(buf->data, '\n');
10269  if (trailing_nl == NULL)
10270  trailing_nl = buf->data;
10271  else
10272  trailing_nl++;
10273 
10274  /*
10275  * Add a newline, plus some indentation, if the new item
10276  * would cause an overflow.
10277  */
10278  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10279  appendContextKeyword(context, "", -PRETTYINDENT_STD,
10282  }
10283  }
10284 
10285  /* Add the new item */
10286  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10287 
10288  /* clean up */
10289  pfree(itembuf.data);
10290  }
10291  }
10292 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
FromExpr * jointree
Definition: parsenodes.h:138
#define PRETTYINDENT_VAR
Definition: ruleutils.c:84
Definition: nodes.h:528
#define PRETTY_INDENT(context)
Definition: ruleutils.c:98
List * fromlist
Definition: primnodes.h:1534
void pfree(void *pointer)
Definition: mcxt.c:1057
List * rtable
Definition: parsenodes.h:137
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:7801
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7855
#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:10295

◆ get_from_clause_coldeflist()

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

Definition at line 10670 of file ruleutils.c.

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

Referenced by get_from_clause_item().

10673 {
10674  StringInfo buf = context->buf;
10675  ListCell *l1;
10676  ListCell *l2;
10677  ListCell *l3;
10678  ListCell *l4;
10679  int i;
10680 
10681  appendStringInfoChar(buf, '(');
10682 
10683  i = 0;
10684  forfour(l1, rtfunc->funccoltypes,
10685  l2, rtfunc->funccoltypmods,
10686  l3, rtfunc->funccolcollations,
10687  l4, rtfunc->funccolnames)
10688  {
10689  Oid atttypid = lfirst_oid(l1);
10690  int32 atttypmod = lfirst_int(l2);
10691  Oid attcollation = lfirst_oid(l3);
10692  char *attname;
10693 
10694  if (colinfo)
10695  attname = colinfo->colnames[i];
10696  else
10697  attname = strVal(lfirst(l4));
10698 
10699  Assert(attname); /* shouldn't be any dropped columns here */
10700 
10701  if (i > 0)
10702  appendStringInfoString(buf, ", ");
10703  appendStringInfo(buf, "%s %s",
10704  quote_identifier(attname),
10705  format_type_with_typemod(atttypid, atttypmod));
10706  if (OidIsValid(attcollation) &&
10707  attcollation != get_typcollation(atttypid))
10708  appendStringInfo(buf, " COLLATE %s",
10709  generate_collation_name(attcollation));
10710 
10711  i++;
10712  }
10713 
10714  appendStringInfoChar(buf, ')');
10715 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11445
signed int int32
Definition: c.h:417
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
NameData attname
Definition: pg_attribute.h:40
#define lfirst_int(lc)
Definition: pg_list.h:170
Oid attcollation
Definition: pg_attribute.h:157
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
Oid atttypid
Definition: pg_attribute.h:49
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:358
List * funccoltypmods
Definition: parsenodes.h:1158
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2976
List * funccolcollations
Definition: parsenodes.h:1159
#define Assert(condition)
Definition: c.h:792
#define lfirst(lc)
Definition: pg_list.h:169
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:491
StringInfo buf
Definition: ruleutils.c:110
int i
#define lfirst_oid(lc)
Definition: pg_list.h:171
char ** colnames
Definition: ruleutils.c:236

◆ get_from_clause_item()

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

Definition at line 10295 of file ruleutils.c.

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

Referenced by get_from_clause().

10296 {
10297  StringInfo buf = context->buf;
10299 
10300  if (IsA(jtnode, RangeTblRef))
10301  {
10302  int varno = ((RangeTblRef *) jtnode)->rtindex;
10303  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10304  char *refname = get_rtable_name(varno, context);
10305  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10306  RangeTblFunction *rtfunc1 = NULL;
10307  bool printalias;
10308 
10309  if (rte->lateral)
10310  appendStringInfoString(buf, "LATERAL ");
10311 
10312  /* Print the FROM item proper */
10313  switch (rte->rtekind)
10314  {
10315  case RTE_RELATION:
10316  /* Normal relation RTE */
10317  appendStringInfo(buf, "%s%s",
10318  only_marker(rte),
10320  context->namespaces));
10321  break;
10322  case RTE_SUBQUERY:
10323  /* Subquery RTE */
10324  appendStringInfoChar(buf, '(');
10325  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10326  context->prettyFlags, context->wrapColumn,
10327  context->indentLevel);
10328  appendStringInfoChar(buf, ')');
10329  break;
10330  case RTE_FUNCTION:
10331  /* Function RTE */
10332  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10333 
10334  /*
10335  * Omit ROWS FROM() syntax for just one function, unless it
10336  * has both a coldeflist and WITH ORDINALITY. If it has both,
10337  * we must use ROWS FROM() syntax to avoid ambiguity about
10338  * whether the coldeflist includes the ordinality column.
10339  */
10340  if (list_length(rte->functions) == 1 &&
10341  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10342  {
10343  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10344  /* we'll print the coldeflist below, if it has one */
10345  }
10346  else
10347  {
10348  bool all_unnest;
10349  ListCell *lc;
10350 
10351  /*
10352  * If all the function calls in the list are to unnest,
10353  * and none need a coldeflist, then collapse the list back
10354  * down to UNNEST(args). (If we had more than one
10355  * built-in unnest function, this would get more
10356  * difficult.)
10357  *
10358  * XXX This is pretty ugly, since it makes not-terribly-
10359  * future-proof assumptions about what the parser would do
10360  * with the output; but the alternative is to emit our
10361  * nonstandard ROWS FROM() notation for what might have
10362  * been a perfectly spec-compliant multi-argument
10363  * UNNEST().
10364  */
10365  all_unnest = true;
10366  foreach(lc, rte->functions)
10367  {
10368  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10369 
10370  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10371  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_UNNEST_ANYARRAY ||
10372  rtfunc->funccolnames != NIL)
10373  {
10374  all_unnest = false;
10375  break;
10376  }
10377  }
10378 
10379  if (all_unnest)
10380  {
10381  List *allargs = NIL;
10382 
10383  foreach(lc, rte->functions)
10384  {
10385  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10386  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10387 
10388  allargs = list_concat(allargs, args);
10389  }
10390 
10391  appendStringInfoString(buf, "UNNEST(");
10392  get_rule_expr((Node *) allargs, context, true);
10393  appendStringInfoChar(buf, ')');
10394  }
10395  else
10396  {
10397  int funcno = 0;
10398 
10399  appendStringInfoString(buf, "ROWS FROM(");
10400  foreach(lc, rte->functions)
10401  {
10402  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10403 
10404  if (funcno > 0)
10405  appendStringInfoString(buf, ", ");
10406  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10407  if (rtfunc->funccolnames != NIL)
10408  {
10409  /* Reconstruct the column definition list */
10410  appendStringInfoString(buf, " AS ");
10412  NULL,
10413  context);
10414  }
10415  funcno++;
10416  }
10417  appendStringInfoChar(buf, ')');
10418  }
10419  /* prevent printing duplicate coldeflist below */
10420  rtfunc1 = NULL;
10421  }
10422  if (rte->funcordinality)
10423  appendStringInfoString(buf, " WITH ORDINALITY");
10424  break;
10425  case RTE_TABLEFUNC:
10426  get_tablefunc(rte->tablefunc, context, true);
10427  break;
10428  case RTE_VALUES:
10429  /* Values list RTE */
10430  appendStringInfoChar(buf, '(');
10431  get_values_def(rte->values_lists, context);
10432  appendStringInfoChar(buf, ')');
10433  break;
10434  case RTE_CTE:
10436  break;
10437  default:
10438  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10439  break;
10440  }
10441 
10442  /* Print the relation alias, if needed */
10443  printalias = false;
10444  if (rte->alias != NULL)
10445  {
10446  /* Always print alias if user provided one */
10447  printalias = true;
10448  }
10449  else if (colinfo->printaliases)
10450  {
10451  /* Always print alias if we need to print column aliases */
10452  printalias = true;
10453  }
10454  else if (rte->rtekind == RTE_RELATION)
10455  {
10456  /*
10457  * No need to print alias if it's same as relation name (this
10458  * would normally be the case, but not if set_rtable_names had to
10459  * resolve a conflict).
10460  */
10461  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10462  printalias = true;
10463  }
10464  else if (rte->rtekind == RTE_FUNCTION)
10465  {
10466  /*
10467  * For a function RTE, always print alias. This covers possible
10468  * renaming of the function and/or instability of the
10469  * FigureColname rules for things that aren't simple functions.
10470  * Note we'd need to force it anyway for the columndef list case.
10471  */
10472  printalias = true;
10473  }
10474  else if (rte->rtekind == RTE_VALUES)
10475  {
10476  /* Alias is syntactically required for VALUES */
10477  printalias = true;
10478  }
10479  else if (rte->rtekind == RTE_CTE)
10480  {
10481  /*
10482  * No need to print alias if it's same as CTE name (this would
10483  * normally be the case, but not if set_rtable_names had to
10484  * resolve a conflict).
10485  */
10486  if (strcmp(refname, rte->ctename) != 0)
10487  printalias = true;
10488  }
10489  if (printalias)
10490  appendStringInfo(buf, " %s", quote_identifier(refname));
10491 
10492  /* Print the column definitions or aliases, if needed */
10493  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10494  {
10495  /* Reconstruct the columndef list, which is also the aliases */
10496  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10497  }
10498  else
10499  {
10500  /* Else print column aliases as needed */
10501  get_column_alias_list(colinfo, context);
10502  }
10503 
10504  /* Tablesample clause must go after any alias */
10505  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10506  get_tablesample_def(rte->tablesample, context);
10507  }
10508  else if (IsA(jtnode, JoinExpr))
10509  {
10510  JoinExpr *j = (JoinExpr *) jtnode;
10511  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10512  bool need_paren_on_right;
10513 
10514  need_paren_on_right = PRETTY_PAREN(context) &&
10515  !IsA(j->rarg, RangeTblRef) &&
10516  !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
10517 
10518  if (!PRETTY_PAREN(context) || j->alias != NULL)
10519  appendStringInfoChar(buf, '(');
10520 
10521  get_from_clause_item(j->larg, query, context);
10522 
10523  switch (j->jointype)
10524  {
10525  case JOIN_INNER:
10526  if (j->quals)
10527  appendContextKeyword(context, " JOIN ",
10531  else
10532  appendContextKeyword(context, " CROSS JOIN ",
10536  break;
10537  case JOIN_LEFT:
10538  appendContextKeyword(context, " LEFT JOIN ",
10542  break;
10543  case JOIN_FULL:
10544  appendContextKeyword(context, " FULL JOIN ",
10548  break;
10549  case JOIN_RIGHT:
10550  appendContextKeyword(context, " RIGHT JOIN ",
10554  break;
10555  default:
10556  elog(ERROR, "unrecognized join type: %d",
10557  (int) j->jointype);
10558  }
10559 
10560  if (need_paren_on_right)
10561  appendStringInfoChar(buf, '(');
10562  get_from_clause_item(j->rarg, query, context);
10563  if (need_paren_on_right)
10564  appendStringInfoChar(buf, ')');
10565 
10566  if (j->usingClause)
10567  {
10568  ListCell *lc;
10569  bool first = true;
10570 
10571  appendStringInfoString(buf, " USING (");
10572  /* Use the assigned names, not what's in usingClause */
10573  foreach(lc, colinfo->usingNames)
10574  {
10575  char *colname = (char *) lfirst(lc);
10576 
10577  if (first)
10578  first = false;
10579  else
10580  appendStringInfoString(buf, ", ");
10582  }
10583  appendStringInfoChar(buf, ')');
10584  }
10585  else if (j->quals)
10586  {
10587  appendStringInfoString(buf, " ON ");
10588  if (!PRETTY_PAREN(context))
10589  appendStringInfoChar(buf, '(');
10590  get_rule_expr(j->quals, context, false);
10591  if (!PRETTY_PAREN(context))
10592  appendStringInfoChar(buf, ')');
10593  }
10594  else if (j->jointype != JOIN_INNER)
10595  {
10596  /* If we didn't say CROSS JOIN above, we must provide an ON */
10597  appendStringInfoString(buf, " ON TRUE");
10598  }
10599 
10600  if (!PRETTY_PAREN(context) || j->alias != NULL)
10601  appendStringInfoChar(buf, ')');
10602 
10603  /* Yes, it's correct to put alias after the right paren ... */
10604  if (j->alias != NULL)
10605  {
10606  /*
10607  * Note that it's correct to emit an alias clause if and only if
10608  * there was one originally. Otherwise we'd be converting a named
10609  * join to unnamed or vice versa, which creates semantic
10610  * subtleties we don't want. However, we might print a different
10611  * alias name than was there originally.
10612  */
10613  appendStringInfo(buf, " %s",
10615  context)));
10616  get_column_alias_list(colinfo, context);
10617  }
10618  }
10619  else
10620  elog(ERROR, "unrecognized node type: %d",
10621  (int) nodeTag(jtnode));
10622 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:11037
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:83
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
Alias * alias
Definition: parsenodes.h:1119
Definition: nodes.h:528
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
bool funcordinality
Definition: parsenodes.h:1069
List * values_lists
Definition: parsenodes.h:1079
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11057
Node * larg
Definition: primnodes.h:1514
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10721
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:45
List * usingNames
Definition: ruleutils.c:283
TableFunc * tablefunc
Definition: parsenodes.h:1074
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:7801
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:287
#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:1516
Node * quals
Definition: primnodes.h:1517
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:10096
Node * rarg
Definition: primnodes.h:1515
Alias * alias
Definition: primnodes.h:1518
JoinType jointype
Definition: primnodes.h:1512
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#define lfirst(lc)
Definition: pg_list.h:169
List * functions
Definition: parsenodes.h:1068
#define only_marker(rte)
Definition: ruleutils.c:484
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:4990
#define nodeTag(nodeptr)
Definition: nodes.h:533
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5064
RTEKind rtekind
Definition: parsenodes.h:981
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10630
char * ctename
Definition: parsenodes.h:1084
Query * subquery
Definition: parsenodes.h:1016
StringInfo buf
Definition: ruleutils.c:110
#define elog(elevel,...)
Definition: elog.h:228
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10670
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9126
int rtindex
Definition: primnodes.h:1519
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1011
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4547
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10295

◆ get_func_expr()

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

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

9219 {
9220  StringInfo buf = context->buf;
9221  Oid funcoid = expr->funcid;
9222  Oid argtypes[FUNC_MAX_ARGS];
9223  int nargs;
9224  List *argnames;
9225  bool use_variadic;
9226  ListCell *l;
9227 
9228  /*
9229  * If the function call came from an implicit coercion, then just show the
9230  * first argument --- unless caller wants to see implicit coercions.
9231  */
9232  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9233  {
9234  get_rule_expr_paren((Node *) linitial(expr->args), context,
9235  false, (Node *) expr);
9236  return;
9237  }
9238 
9239  /*
9240  * If the function call came from a cast, then show the first argument
9241  * plus an explicit cast operation.
9242  */
9243  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9245  {
9246  Node *arg = linitial(expr->args);
9247  Oid rettype = expr->funcresulttype;
9248  int32 coercedTypmod;
9249 
9250  /* Get the typmod if this is a length-coercion function */
9251  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9252 
9253  get_coercion_expr(arg, context,
9254  rettype, coercedTypmod,
9255  (Node *) expr);
9256 
9257  return;
9258  }
9259 
9260  /*
9261  * If the function was called using one of the SQL spec's random special
9262  * syntaxes, try to reproduce that. If we don't recognize the function,
9263  * fall through.
9264  */
9265  if (expr->funcformat == COERCE_SQL_SYNTAX)
9266  {
9267  if (get_func_sql_syntax(expr, context))
9268  return;
9269  }
9270 
9271  /*
9272  * Normal function: display as proname(args). First we need to extract
9273  * the argument datatypes.
9274  */
9275  if (list_length(expr->args) > FUNC_MAX_ARGS)
9276  ereport(ERROR,
9277  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9278  errmsg("too many arguments")));
9279  nargs = 0;
9280  argnames = NIL;
9281  foreach(l, expr->args)
9282  {
9283  Node *arg = (Node *) lfirst(l);
9284 
9285  if (IsA(arg, NamedArgExpr))
9286  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9287  argtypes[nargs] = exprType(arg);
9288  nargs++;
9289  }
9290 
9291  appendStringInfo(buf, "%s(",
9292  generate_function_name(funcoid, nargs,
9293  argnames, argtypes,
9294  expr->funcvariadic,
9295  &use_variadic,
9296  context->special_exprkind));
9297  nargs = 0;
9298  foreach(l, expr->args)
9299  {
9300  if (nargs++ > 0)
9301  appendStringInfoString(buf, ", ");
9302  if (use_variadic && lnext(expr->args, l) == NULL)
9303  appendStringInfoString(buf, "VARIADIC ");
9304  get_rule_expr((Node *) lfirst(l), context, true);
9305  }
9306  appendStringInfoChar(buf, ')');
9307 }
Oid funcresulttype
Definition: primnodes.h:491
#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:11159
static bool get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Definition: ruleutils.c:9513
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7874
List * args
Definition: primnodes.h:498
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
Definition: nodes.h:528
int errcode(int sqlerrcode)
Definition: elog.c:704
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:417
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:495
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:490
#define ERROR
Definition: elog.h:45
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:9730
ParseExprKind special_exprkind
Definition: ruleutils.c:118
List * lappend(List *list, void *datum)
Definition: list.c:321
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ereport(elevel,...)
Definition: elog.h:155
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#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:915
void * arg
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:493

◆ get_func_sql_syntax()

static bool get_func_sql_syntax ( FuncExpr expr,
deparse_context context 
)
static

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

9514 {
9515  StringInfo buf = context->buf;
9516  Oid funcoid = expr->funcid;
9517 
9518  switch (funcoid)
9519  {
9520  case F_TIMEZONE_INTERVAL_TIMESTAMP:
9521  case F_TIMEZONE_INTERVAL_TIMESTAMPTZ:
9522  case F_TIMEZONE_INTERVAL_TIMETZ:
9523  case F_TIMEZONE_TEXT_TIMESTAMP:
9524  case F_TIMEZONE_TEXT_TIMESTAMPTZ:
9525  case F_TIMEZONE_TEXT_TIMETZ:
9526  /* AT TIME ZONE ... note reversed argument order */
9527  appendStringInfoChar(buf, '(');
9528  get_rule_expr((Node *) lsecond(expr->args), context, false);
9529  appendStringInfoString(buf, " AT TIME ZONE ");
9530  get_rule_expr((Node *) linitial(expr->args), context, false);
9531  appendStringInfoChar(buf, ')');
9532  return true;
9533 
9534  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_INTERVAL:
9535  case F_OVERLAPS_TIMESTAMPTZ_INTERVAL_TIMESTAMPTZ_TIMESTAMPTZ:
9536  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_INTERVAL:
9537  case F_OVERLAPS_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ_TIMESTAMPTZ:
9538  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_INTERVAL:
9539  case F_OVERLAPS_TIMESTAMP_INTERVAL_TIMESTAMP_TIMESTAMP:
9540  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_INTERVAL:
9541  case F_OVERLAPS_TIMESTAMP_TIMESTAMP_TIMESTAMP_TIMESTAMP:
9542  case F_OVERLAPS_TIMETZ_TIMETZ_TIMETZ_TIMETZ:
9543  case F_OVERLAPS_TIME_INTERVAL_TIME_INTERVAL:
9544  case F_OVERLAPS_TIME_INTERVAL_TIME_TIME:
9545  case F_OVERLAPS_TIME_TIME_TIME_INTERVAL:
9546  case F_OVERLAPS_TIME_TIME_TIME_TIME:
9547  /* (x1, x2) OVERLAPS (y1, y2) */
9548  appendStringInfoString(buf, "((");
9549  get_rule_expr((Node *) linitial(expr->args), context, false);
9550  appendStringInfoString(buf, ", ");
9551  get_rule_expr((Node *) lsecond(expr->args), context, false);
9552  appendStringInfoString(buf, ") OVERLAPS (");
9553  get_rule_expr((Node *) lthird(expr->args), context, false);
9554  appendStringInfoString(buf, ", ");
9555  get_rule_expr((Node *) lfourth(expr->args), context, false);
9556  appendStringInfoString(buf, "))");
9557  return true;
9558 
9559  case F_IS_NORMALIZED:
9560  /* IS xxx NORMALIZED */
9561  appendStringInfoString(buf, "((");
9562  get_rule_expr((Node *) linitial(expr->args), context, false);
9563  appendStringInfoString(buf, ") IS");
9564  if (list_length(expr->args) == 2)
9565  {
9566  Const *con = (Const *) lsecond(expr->args);
9567 
9568  Assert(IsA(con, Const) &&
9569  con->consttype == TEXTOID &&
9570  !con->constisnull);
9571  appendStringInfo(buf, " %s",
9573  }
9574  appendStringInfoString(buf, " NORMALIZED)");
9575  return true;
9576 
9577  case F_PG_COLLATION_FOR:
9578  /* COLLATION FOR */
9579  appendStringInfoString(buf, "COLLATION FOR (");
9580  get_rule_expr((Node *) linitial(expr->args), context, false);
9581  appendStringInfoChar(buf, ')');
9582  return true;
9583 
9584  /*
9585  * XXX EXTRACT, a/k/a date_part(), is intentionally not covered
9586  * yet. Add it after we change the return type to numeric.
9587  */
9588 
9589  case F_NORMALIZE:
9590  /* NORMALIZE() */
9591  appendStringInfoString(buf, "NORMALIZE(");
9592  get_rule_expr((Node *) linitial(expr->args), context, false);
9593  if (list_length(expr->args) == 2)
9594  {
9595  Const *con = (Const *) lsecond(expr->args);
9596 
9597  Assert(IsA(con, Const) &&
9598  con->consttype == TEXTOID &&
9599  !con->constisnull);
9600  appendStringInfo(buf, ", %s",
9602  }
9603  appendStringInfoChar(buf, ')');
9604  return true;
9605 
9606  case F_OVERLAY_BIT_BIT_INT4:
9607  case F_OVERLAY_BIT_BIT_INT4_INT4:
9608  case F_OVERLAY_BYTEA_BYTEA_INT4:
9609  case F_OVERLAY_BYTEA_BYTEA_INT4_INT4:
9610  case F_OVERLAY_TEXT_TEXT_INT4:
9611  case F_OVERLAY_TEXT_TEXT_INT4_INT4:
9612  /* OVERLAY() */
9613  appendStringInfoString(buf, "OVERLAY(");
9614  get_rule_expr((Node *) linitial(expr->args), context, false);
9615  appendStringInfoString(buf, " PLACING ");
9616  get_rule_expr((Node *) lsecond(expr->args), context, false);
9617  appendStringInfoString(buf, " FROM ");
9618  get_rule_expr((Node *) lthird(expr->args), context, false);
9619  if (list_length(expr->args) == 4)
9620  {
9621  appendStringInfoString(buf, " FOR ");
9622  get_rule_expr((Node *) lfourth(expr->args), context, false);
9623  }
9624  appendStringInfoChar(buf, ')');
9625  return true;
9626 
9627  case F_POSITION_BIT_BIT:
9628  case F_POSITION_BYTEA_BYTEA:
9629  case F_POSITION_TEXT_TEXT:
9630  /* POSITION() ... extra parens since args are b_expr not a_expr */
9631  appendStringInfoString(buf, "POSITION((");
9632  get_rule_expr((Node *) lsecond(expr->args), context, false);
9633  appendStringInfoString(buf, ") IN (");
9634  get_rule_expr((Node *) linitial(expr->args), context, false);
9635  appendStringInfoString(buf, "))");
9636  return true;
9637 
9638  case F_SUBSTRING_BIT_INT4:
9639  case F_SUBSTRING_BIT_INT4_INT4:
9640  case F_SUBSTRING_BYTEA_INT4:
9641  case F_SUBSTRING_BYTEA_INT4_INT4:
9642  case F_SUBSTRING_TEXT_INT4:
9643  case F_SUBSTRING_TEXT_INT4_INT4:
9644  /* SUBSTRING FROM/FOR (i.e., integer-position variants) */
9645  appendStringInfoString(buf, "SUBSTRING(");
9646  get_rule_expr((Node *) linitial(expr->args), context, false);
9647  appendStringInfoString(buf, " FROM ");
9648  get_rule_expr((Node *) lsecond(expr->args), context, false);
9649  if (list_length(expr->args) == 3)
9650  {
9651  appendStringInfoString(buf, " FOR ");
9652  get_rule_expr((Node *) lthird(expr->args), context, false);
9653  }
9654  appendStringInfoChar(buf, ')');
9655  return true;
9656 
9657  case F_SUBSTRING_TEXT_TEXT_TEXT:
9658  /* SUBSTRING SIMILAR/ESCAPE */
9659  appendStringInfoString(buf, "SUBSTRING(");
9660  get_rule_expr((Node *) linitial(expr->args), context, false);
9661  appendStringInfoString(buf, " SIMILAR ");
9662  get_rule_expr((Node *) lsecond(expr->args), context, false);
9663  appendStringInfoString(buf, " ESCAPE ");
9664  get_rule_expr((Node *) lthird(expr->args), context, false);
9665  appendStringInfoChar(buf, ')');
9666  return true;
9667 
9668  case F_BTRIM_BYTEA_BYTEA:
9669  case F_BTRIM_TEXT:
9670  case F_BTRIM_TEXT_TEXT:
9671  /* TRIM() */
9672  appendStringInfoString(buf, "TRIM(BOTH");
9673  if (list_length(expr->args) == 2)
9674  {
9675  appendStringInfoChar(buf, ' ');
9676  get_rule_expr((Node *) lsecond(expr->args), context, false);
9677  }
9678  appendStringInfoString(buf, " FROM ");
9679  get_rule_expr((Node *) linitial(expr->args), context, false);
9680  appendStringInfoChar(buf, ')');
9681  return true;
9682 
9683  case F_LTRIM_TEXT:
9684  case F_LTRIM_TEXT_TEXT:
9685  /* TRIM() */
9686  appendStringInfoString(buf, "TRIM(LEADING");
9687  if (list_length(expr->args) == 2)
9688  {
9689  appendStringInfoChar(buf, ' ');
9690  get_rule_expr((Node *) lsecond(expr->args), context, false);
9691  }
9692  appendStringInfoString(buf, " FROM ");
9693  get_rule_expr((Node *) linitial(expr->args), context, false);
9694  appendStringInfoChar(buf, ')');
9695  return true;
9696 
9697  case F_RTRIM_TEXT:
9698  case F_RTRIM_TEXT_TEXT:
9699  /* TRIM() */
9700  appendStringInfoString(buf, "TRIM(TRAILING");
9701  if (list_length(expr->args) == 2)
9702  {
9703  appendStringInfoChar(buf, ' ');
9704  get_rule_expr((Node *) lsecond(expr->args), context, false);
9705  }
9706  appendStringInfoString(buf, " FROM ");
9707  get_rule_expr((Node *) linitial(expr->args), context, false);
9708  appendStringInfoChar(buf, ')');
9709  return true;
9710 
9711  case F_XMLEXISTS:
9712  /* XMLEXISTS ... extra parens because args are c_expr */
9713  appendStringInfoString(buf, "XMLEXISTS((");
9714  get_rule_expr((Node *) linitial(expr->args), context, false);
9715  appendStringInfoString(buf, ") PASSING (");
9716  get_rule_expr((Node *) lsecond(expr->args), context, false);
9717  appendStringInfoString(buf, "))");
9718  return true;
9719  }
9720  return false;
9721 }
Datum constvalue
Definition: primnodes.h:214
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
List * args
Definition: primnodes.h:498
Definition: nodes.h:528
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:179
Oid consttype
Definition: primnodes.h:210
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:490
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:792
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#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:215

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

6094 {
6095  StringInfo buf = context->buf;
6096  RangeTblEntry *select_rte = NULL;
6097  RangeTblEntry *values_rte = NULL;
6098  RangeTblEntry *rte;
6099  char *sep;
6100  ListCell *l;
6101  List *strippedexprs;
6102 
6103  /* Insert the WITH clause if given */
6104  get_with_clause(query, context);
6105 
6106  /*
6107  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6108  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6109  */
6110  foreach(l, query->rtable)
6111  {
6112  rte = (RangeTblEntry *) lfirst(l);
6113 
6114  if (rte->rtekind == RTE_SUBQUERY)
6115  {
6116  if (select_rte)
6117  elog(ERROR, "too many subquery RTEs in INSERT");
6118  select_rte = rte;
6119  }
6120 
6121  if (rte->rtekind == RTE_VALUES)
6122  {
6123  if (values_rte)
6124  elog(ERROR, "too many values RTEs in INSERT");
6125  values_rte = rte;
6126  }
6127  }
6128  if (select_rte && values_rte)
6129  elog(ERROR, "both subquery and values RTEs in INSERT");
6130 
6131  /*
6132  * Start the query with INSERT INTO relname
6133  */
6134  rte = rt_fetch(query->resultRelation, query->rtable);
6135  Assert(rte->rtekind == RTE_RELATION);
6136 
6137  if (PRETTY_INDENT(context))
6138  {
6139  context->indentLevel += PRETTYINDENT_STD;
6140  appendStringInfoChar(buf, ' ');
6141  }
6142  appendStringInfo(buf, "INSERT INTO %s ",
6144  /* INSERT requires AS keyword for target alias */
6145  if (rte->alias != NULL)
6146  appendStringInfo(buf, "AS %s ",
6148 
6149  /*
6150  * Add the insert-column-names list. Any indirection decoration needed on
6151  * the column names can be inferred from the top targetlist.
6152  */
6153  strippedexprs = NIL;
6154  sep = "";
6155  if (query->targetList)
6156  appendStringInfoChar(buf, '(');
6157  foreach(l, query->targetList)
6158  {
6159  TargetEntry *tle = (TargetEntry *) lfirst(l);
6160 
6161  if (tle->resjunk)
6162  continue; /* ignore junk entries */
6163 
6164  appendStringInfoString(buf, sep);
6165  sep = ", ";
6166 
6167  /*
6168  * Put out name of target column; look in the catalogs, not at
6169  * tle->resname, since resname will fail to track RENAME.
6170  */
6173  tle->resno,
6174  false)));
6175 
6176  /*
6177  * Print any indirection needed (subfields or subscripts), and strip
6178  * off the top-level nodes representing the indirection assignments.
6179  * Add the stripped expressions to strippedexprs. (If it's a
6180  * single-VALUES statement, the stripped expressions are the VALUES to
6181  * print below. Otherwise they're just Vars and not really
6182  * interesting.)
6183  */
6184  strippedexprs = lappend(strippedexprs,
6185  processIndirection((Node *) tle->expr,
6186  context));
6187  }
6188  if (query->targetList)
6189  appendStringInfoString(buf, ") ");
6190 
6191  if (query->override)
6192  {
6193  if (query->override == OVERRIDING_SYSTEM_VALUE)
6194  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6195  else if (query->override == OVERRIDING_USER_VALUE)
6196  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6197  }
6198 
6199  if (select_rte)
6200  {
6201  /* Add the SELECT */
6202  get_query_def(select_rte->subquery, buf, NIL, NULL,
6203  context->prettyFlags, context->wrapColumn,
6204  context->indentLevel);
6205  }
6206  else if (values_rte)
6207  {
6208  /* Add the multi-VALUES expression lists */
6209  get_values_def(values_rte->values_lists, context);
6210  }
6211  else if (strippedexprs)
6212  {
6213  /* Add the single-VALUES expression list */
6214  appendContextKeyword(context, "VALUES (",
6216  get_rule_expr((Node *) strippedexprs, context, false);
6217  appendStringInfoChar(buf, ')');
6218  }
6219  else
6220  {
6221  /* No expressions, so it must be DEFAULT VALUES */
6222  appendStringInfoString(buf, "DEFAULT VALUES");
6223  }
6224 
6225  /* Add ON CONFLICT if present */
6226  if (query->onConflict)
6227  {
6228  OnConflictExpr *confl = query->onConflict;
6229 
6230  appendStringInfoString(buf, " ON CONFLICT");
6231 
6232  if (confl->arbiterElems)
6233  {
6234  /* Add the single-VALUES expression list */
6235  appendStringInfoChar(buf, '(');
6236  get_rule_expr((Node *) confl->arbiterElems, context, false);
6237  appendStringInfoChar(buf, ')');
6238 
6239  /* Add a WHERE clause (for partial indexes) if given */
6240  if (confl->arbiterWhere != NULL)
6241  {
6242  bool save_varprefix;
6243 
6244  /*
6245  * Force non-prefixing of Vars, since parser assumes that they
6246  * belong to target relation. WHERE clause does not use
6247  * InferenceElem, so this is separately required.
6248  */
6249  save_varprefix = context->varprefix;
6250  context->varprefix = false;
6251 
6252  appendContextKeyword(context, " WHERE ",
6254  get_rule_expr(confl->arbiterWhere, context, false);
6255 
6256  context->varprefix = save_varprefix;
6257  }
6258  }
6259  else if (OidIsValid(confl->constraint))
6260  {
6261  char *constraint = get_constraint_name(confl->constraint);
6262 
6263  if (!constraint)
6264  elog(ERROR, "cache lookup failed for constraint %u",
6265  confl->constraint);
6266  appendStringInfo(buf, " ON CONSTRAINT %s",
6267  quote_identifier(constraint));
6268  }
6269 
6270  if (confl->action == ONCONFLICT_NOTHING)
6271  {
6272  appendStringInfoString(buf, " DO NOTHING");
6273  }
6274  else
6275  {
6276  appendStringInfoString(buf, " DO UPDATE SET ");
6277  /* Deparse targetlist */
6279  context, rte);
6280 
6281  /* Add a WHERE clause if given */
6282  if (confl->onConflictWhere != NULL)
6283  {
6284  appendContextKeyword(context, " WHERE ",
6286  get_rule_expr(confl->onConflictWhere, context, false);
6287  }
6288  }
6289  }
6290 
6291  /* Add RETURNING if present */
6292  if (query->returningList)
6293  {
6294  appendContextKeyword(context, " RETURNING",
6296  get_target_list(query->returningList, context, NULL);
6297  }
6298 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5107
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
Alias * alias
Definition: parsenodes.h:1119
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:1079
OnConflictExpr * onConflict
Definition: parsenodes.h:144
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10825
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5514
Definition: nodes.h:528
#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:6361
#define OidIsValid(objectId)
Definition: c.h:698
List * values_lists
Definition: parsenodes.h:1079
List * targetList
Definition: parsenodes.h:140
List * arbiterElems
Definition: primnodes.h:1553
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:11057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1438
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:45
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:7801
AttrNumber resno
Definition: primnodes.h:1432
List * returningList
Definition: parsenodes.h:146
#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:321
OnConflictAction action
Definition: primnodes.h:1550
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
OverridingKind override
Definition: parsenodes.h:142
#define Assert(condition)
Definition: c.h:792
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1431
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:4990
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5064
RTEKind rtekind
Definition: parsenodes.h:981
Node * arbiterWhere
Definition: primnodes.h:1555
Query * subquery
Definition: parsenodes.h:1016
StringInfo buf
Definition: ruleutils.c:110
#define elog(elevel,...)
Definition: elog.h:228
List * onConflictSet
Definition: primnodes.h:1559
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
Node * onConflictWhere
Definition: primnodes.h:1560
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 6965 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().

6967 {
6968  RangeTblEntry *rte;
6970  int netlevelsup;
6971  deparse_namespace *dpns;
6972  Index varno;
6973  AttrNumber varattno;
6974  TupleDesc tupleDesc;
6975  Node *expr;
6976 
6977  /*
6978  * If it's a RowExpr that was expanded from a whole-row Var, use the
6979  * column names attached to it.
6980  */
6981  if (IsA(var, RowExpr))
6982  {
6983  RowExpr *r = (RowExpr *) var;
6984 
6985  if (fieldno > 0 && fieldno <= list_length(r->colnames))
6986  return strVal(list_nth(r->colnames, fieldno - 1));
6987  }
6988 
6989  /*
6990  * If it's a Param of type RECORD, try to find what the Param refers to.
6991  */
6992  if (IsA(var, Param))
6993  {
6994  Param *param = (Param *) var;
6995  ListCell *ancestor_cell;
6996 
6997  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
6998  if (expr)
6999  {
7000  /* Found a match, so recurse to decipher the field name */
7001  deparse_namespace save_dpns;
7002  const char *result;
7003 
7004  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7005  result = get_name_for_var_field((Var *) expr, fieldno,
7006  0, context);
7007  pop_ancestor_plan(dpns, &save_dpns);
7008  return result;
7009  }
7010  }
7011 
7012  /*
7013  * If it's a Var of type RECORD, we have to find what the Var refers to;
7014  * if not, we can use get_expr_result_tupdesc().
7015  */
7016  if (!IsA(var, Var) ||
7017  var->vartype != RECORDOID)
7018  {
7019  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7020  /* Got the tupdesc, so we can extract the field name */
7021  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7022  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7023  }
7024 
7025  /* Find appropriate nesting depth */
7026  netlevelsup = var->varlevelsup + levelsup;
7027  if (netlevelsup >= list_length(context->namespaces))
7028  elog(ERROR, "bogus varlevelsup: %d offset %d",
7029  var->varlevelsup, levelsup);
7030  dpns = (deparse_namespace *) list_nth(context->namespaces,
7031  netlevelsup);
7032 
7033  /*
7034  * If we have a syntactic referent for the Var, and we're working from a
7035  * parse tree, prefer to use the syntactic referent. Otherwise, fall back
7036  * on the semantic referent. (See comments in get_variable().)
7037  */
7038  if (var->varnosyn > 0 && dpns->plan == NULL)
7039  {
7040  varno = var->varnosyn;
7041  varattno = var->varattnosyn;
7042  }
7043  else
7044  {
7045  varno = var->varno;
7046  varattno = var->varattno;
7047  }
7048 
7049  /*
7050  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7051  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7052  * down into the subplans, or INDEX_VAR, which is resolved similarly.
7053  *
7054  * Note: unlike get_variable and resolve_special_varno, we need not worry
7055  * about inheritance mapping: a child Var should have the same datatype as
7056  * its parent, and here we're really only interested in the Var's type.
7057  */
7058  if (varno >= 1 && varno <= list_length(dpns->rtable))
7059  {
7060  rte = rt_fetch(varno, dpns->rtable);
7061  attnum = varattno;
7062  }
7063  else if (varno == OUTER_VAR && dpns->outer_tlist)
7064  {
7065  TargetEntry *tle;
7066  deparse_namespace save_dpns;
7067  const char *result;
7068 
7069  tle = get_tle_by_resno(dpns->outer_tlist, varattno);
7070  if (!tle)
7071  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", varattno);
7072 
7073  Assert(netlevelsup == 0);
7074  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7075 
7076  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7077  levelsup, context);
7078 
7079  pop_child_plan(dpns, &save_dpns);
7080  return result;
7081  }
7082  else if (varno == INNER_VAR && dpns->inner_tlist)
7083  {
7084  TargetEntry *tle;
7085  deparse_namespace save_dpns;
7086  const char *result;
7087 
7088  tle = get_tle_by_resno(dpns->inner_tlist, varattno);
7089  if (!tle)
7090  elog(ERROR, "bogus varattno for INNER_VAR var: %d", varattno);
7091 
7092  Assert(netlevelsup == 0);
7093  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7094 
7095  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7096  levelsup, context);
7097 
7098  pop_child_plan(dpns, &save_dpns);
7099  return result;
7100  }
7101  else if (varno == INDEX_VAR && dpns->index_tlist)
7102  {
7103  TargetEntry *tle;
7104  const char *result;
7105 
7106  tle = get_tle_by_resno(dpns->index_tlist, varattno);
7107  if (!tle)
7108  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", varattno);
7109 
7110  Assert(netlevelsup == 0);
7111 
7112  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7113  levelsup, context);
7114 
7115  return result;
7116  }
7117  else
7118  {
7119  elog(ERROR, "bogus varno: %d", varno);
7120  return NULL; /* keep compiler quiet */
7121  }
7122 
7123  if (attnum == InvalidAttrNumber)
7124  {
7125  /* Var is whole-row reference to RTE, so select the right field */
7126  return get_rte_attribute_name(rte, fieldno);
7127  }
7128 
7129  /*
7130  * This part has essentially the same logic as the parser's
7131  * expandRecordVariable() function, but we are dealing with a different
7132  * representation of the input context, and we only need one field name
7133  * not a TupleDesc. Also, we need special cases for finding subquery and
7134  * CTE subplans when deparsing Plan trees.
7135  */
7136  expr = (Node *) var; /* default if we can't drill down */
7137 
7138  switch (rte->rtekind)
7139  {
7140  case RTE_RELATION:
7141  case RTE_VALUES:
7142  case RTE_NAMEDTUPLESTORE:
7143  case RTE_RESULT:
7144 
7145  /*
7146  * This case should not occur: a column of a table, values list,
7147  * or ENR shouldn't have type RECORD. Fall through and fail (most
7148  * likely) at the bottom.
7149  */
7150  break;
7151  case RTE_SUBQUERY:
7152  /* Subselect-in-FROM: examine sub-select's output expr */
7153  {
7154  if (rte->subquery)
7155  {
7157  attnum);
7158 
7159  if (ste == NULL || ste->resjunk)
7160  elog(ERROR, "subquery %s does not have attribute %d",
7161  rte->eref->aliasname, attnum);
7162  expr = (Node *) ste->expr;
7163  if (IsA(expr, Var))
7164  {
7165  /*
7166  * Recurse into the sub-select to see what its Var
7167  * refers to. We have to build an additional level of
7168  * namespace to keep in step with varlevelsup in the
7169  * subselect.
7170  */
7171  deparse_namespace mydpns;
7172  const char *result;
7173 
7174  set_deparse_for_query(&mydpns, rte->subquery,
7175  context->namespaces);
7176 
7177  context->namespaces = lcons(&mydpns,
7178  context->namespaces);
7179 
7180  result = get_name_for_var_field((Var *) expr, fieldno,
7181  0, context);
7182 
7183  context->namespaces =
7184  list_delete_first(context->namespaces);
7185 
7186  return result;
7187  }
7188  /* else fall through to inspect the expression */
7189  }
7190  else
7191  {
7192  /*
7193  * We're deparsing a Plan tree so we don't have complete
7194  * RTE entries (in particular, rte->subquery is NULL). But
7195  * the only place we'd see a Var directly referencing a
7196  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7197  * look into the child plan's tlist instead.
7198  */
7199  TargetEntry *tle;
7200  deparse_namespace save_dpns;
7201  const char *result;
7202 
7203  if (!dpns->inner_plan)
7204  elog(ERROR, "failed to find plan for subquery %s",
7205  rte->eref->aliasname);
7206  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7207  if (!tle)
7208  elog(ERROR, "bogus varattno for subquery var: %d",
7209  attnum);
7210  Assert(netlevelsup == 0);
7211  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7212 
7213  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7214  levelsup, context);
7215 
7216  pop_child_plan(dpns, &save_dpns);
7217  return result;
7218  }
7219  }
7220  break;
7221  case RTE_JOIN:
7222  /* Join RTE --- recursively inspect the alias variable */
7223  if (rte->joinaliasvars == NIL)
7224  elog(ERROR, "cannot decompile join alias var in plan tree");
7225  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7226  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7227  Assert(expr != NULL);
7228  /* we intentionally don't strip implicit coercions here */
7229  if (IsA(expr, Var))
7230  return get_name_for_var_field((Var *) expr, fieldno,
7231  var->varlevelsup + levelsup,
7232  context);
7233  /* else fall through to inspect the expression */
7234  break;
7235  case RTE_FUNCTION:
7236  case RTE_TABLEFUNC:
7237 
7238  /*
7239  * We couldn't get here unless a function is declared with one of
7240  * its result columns as RECORD, which is not allowed.
7241  */
7242  break;
7243  case RTE_CTE:
7244  /* CTE reference: examine subquery's output expr */
7245  {
7246  CommonTableExpr *cte = NULL;
7247  Index ctelevelsup;
7248  ListCell *lc;
7249 
7250  /*
7251  * Try to find the referenced CTE using the namespace stack.
7252  */
7253  ctelevelsup = rte->ctelevelsup + netlevelsup;
7254  if (ctelevelsup >= list_length(context->namespaces))
7255  lc = NULL;
7256  else
7257  {
7258  deparse_namespace *ctedpns;
7259 
7260  ctedpns = (deparse_namespace *)
7261  list_nth(context->namespaces, ctelevelsup);
7262  foreach(lc, ctedpns->ctes)
7263  {
7264  cte = (CommonTableExpr *) lfirst(lc);
7265  if (strcmp(cte->ctename, rte->ctename) == 0)
7266  break;
7267  }
7268  }
7269  if (lc != NULL)
7270  {
7271  Query *ctequery = (Query *) cte->ctequery;
7273  attnum);
7274 
7275  if (ste == NULL || ste->resjunk)
7276  elog(ERROR, "subquery %s does not have attribute %d",
7277  rte->eref->aliasname, attnum);
7278  expr = (Node *) ste->expr;
7279  if (IsA(expr, Var))
7280  {
7281  /*
7282  * Recurse into the CTE to see what its Var refers to.
7283  * We have to build an additional level of namespace
7284  * to keep in step with varlevelsup in the CTE.
7285  * Furthermore it could be an outer CTE, so we may
7286  * have to delete some levels of namespace.
7287  */
7288  List *save_nslist = context->namespaces;
7289  List *new_nslist;
7290  deparse_namespace mydpns;
7291  const char *result;
7292 
7293  set_deparse_for_query(&mydpns, ctequery,
7294  context->namespaces);
7295 
7296  new_nslist = list_copy_tail(context->namespaces,
7297  ctelevelsup);
7298  context->namespaces = lcons(&mydpns, new_nslist);
7299 
7300  result = get_name_for_var_field((Var *) expr, fieldno,
7301  0, context);
7302 
7303  context->namespaces = save_nslist;
7304 
7305  return result;
7306  }
7307  /* else fall through to inspect the expression */
7308  }
7309  else
7310  {
7311  /*
7312  * We're deparsing a Plan tree so we don't have a CTE
7313  * list. But the only place we'd see a Var directly
7314  * referencing a CTE RTE is in a CteScan plan node, and we
7315  * can look into the subplan's tlist instead.
7316  */
7317  TargetEntry *tle;
7318  deparse_namespace save_dpns;
7319  const char *result;
7320 
7321  if (!dpns->inner_plan)
7322  elog(ERROR, "failed to find plan for CTE %s",
7323  rte->eref->aliasname);
7324  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7325  if (!tle)
7326  elog(ERROR, "bogus varattno for subquery var: %d",
7327  attnum);
7328  Assert(netlevelsup == 0);
7329  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7330 
7331  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7332  levelsup, context);
7333 
7334  pop_child_plan(dpns, &save_dpns);
7335  return result;
7336  }
7337  }
7338  break;
7339  }
7340 
7341  /*
7342  * We now have an expression we can't expand any more, so see if
7343  * get_expr_result_tupdesc() can do anything with it.
7344  */
7345  tupleDesc = get_expr_result_tupdesc(expr, false);
7346  /* Got the tupdesc, so we can extract the field name */
7347  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7348  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7349 }
List * namespaces
Definition: ruleutils.c:111
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
List * joinaliasvars
Definition: parsenodes.h:1056
Index varlevelsup
Definition: primnodes.h:191
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7360
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:528
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:186
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4710
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1422
Definition: primnodes.h:181
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1438
#define ERROR
Definition: elog.h:45
NameData attname
Definition: pg_attribute.h:40
List * colnames
Definition: primnodes.h:1062
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:266
Oid vartype
Definition: primnodes.h:188
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varnosyn
Definition: primnodes.h:194
Index varno
Definition: primnodes.h:184
AttrNumber varattnosyn
Definition: primnodes.h:195
List * outer_tlist
Definition: ruleutils.c:172
unsigned int Index
Definition: c.h:537
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:6965
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:171
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
List * lcons(void *datum, List *list)
Definition: list.c:453
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4659
#define Assert(condition)
Definition: c.h:792
#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:4642
Expr * expr
Definition: primnodes.h:1431
static int list_length(const List *l)
Definition: pg_list.h:149
Index ctelevelsup
Definition: parsenodes.h:1085
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3593
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:981
char * ctename
Definition: parsenodes.h:1084
Query * subquery
Definition: parsenodes.h:1016
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:4689
#define elog(elevel,...)
Definition: elog.h:228
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:669
Alias * eref
Definition: parsenodes.h:1120
#define INDEX_VAR
Definition: primnodes.h:173
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1472
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:172
List * list_delete_first(List *list)
Definition: list.c:860

◆ get_opclass_name()

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

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

10767 {
10768  HeapTuple ht_opc;
10769  Form_pg_opclass opcrec;
10770  char *opcname;
10771  char *nspname;
10772 
10773  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10774  if (!HeapTupleIsValid(ht_opc))
10775  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10776  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10777 
10778  if (!OidIsValid(actual_datatype) ||
10779  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10780  {
10781  /* Okay, we need the opclass name. Do we need to qualify it? */
10782  opcname = NameStr(opcrec->opcname);
10783  if (OpclassIsVisible(opclass))
10784  appendStringInfo(buf, " %s", quote_identifier(opcname));
10785  else
10786  {
10787  nspname = get_namespace_name(opcrec->opcnamespace);
10788  appendStringInfo(buf, " %s.%s",
10789  quote_identifier(nspname),
10790  quote_identifier(opcname));
10791  }
10792  }
10793  ReleaseSysCache(ht_opc);
10794 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2090
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10933
#define OidIsValid(objectId)
Definition: c.h:698
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
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:228
#define NameStr(name)
Definition: c.h:669
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 9177 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().

9178 {
9179  StringInfo buf = context->buf;
9180  Oid opno = expr->opno;
9181  List *args = expr->args;
9182 
9183  if (!PRETTY_PAREN(context))
9184  appendStringInfoChar(buf, '(');
9185  if (list_length(args) == 2)
9186  {
9187  /* binary operator */
9188  Node *arg1 = (Node *) linitial(args);
9189  Node *arg2 = (Node *) lsecond(args);
9190 
9191  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9192  appendStringInfo(buf, " %s ",
9194  exprType(arg1),
9195  exprType(arg2)));
9196  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9197  }
9198  else
9199  {
9200  /* prefix operator */
9201  Node *arg = (Node *) linitial(args);
9202 
9203  appendStringInfo(buf, "%s ",
9205  InvalidOid,
9206  exprType(arg)));
9207  get_rule_expr_paren(arg, context, true, (Node *) expr);
9208  }
9209  if (!PRETTY_PAREN(context))
9210  appendStringInfoChar(buf, ')');
9211 }
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7874
Definition: nodes.h:528
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:11264
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:537
List * args
Definition: primnodes.h:543
Definition: pg_list.h:50

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

Definition at line 7495 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), deparse_context::buf, find_param_referent(), get_rule_expr(), IsA, Param::paramid, pop_ancestor_plan(), push_ancestor_plan(), and deparse_context::varprefix.

Referenced by get_rule_expr().

7496 {
7497  Node *expr;
7498  deparse_namespace *dpns;
7499  ListCell *ancestor_cell;
7500 
7501  /*
7502  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7503  * the parameter was computed. Note that failing to find a referent isn't
7504  * an error, since the Param might well be a subplan output rather than an
7505  * input.
7506  */
7507  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7508  if (expr)
7509  {
7510  /* Found a match, so print it */
7511  deparse_namespace save_dpns;
7512  bool save_varprefix;
7513  bool need_paren;
7514 
7515  /* Switch attention to the ancestor plan node */
7516  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7517 
7518  /*
7519  * Force prefixing of Vars, since they won't belong to the relation
7520  * being scanned in the original plan node.
7521  */
7522  save_varprefix = context->varprefix;
7523  context->varprefix = true;
7524 
7525  /*
7526  * A Param's expansion is typically a Var, Aggref, or upper-level
7527  * Param, which wouldn't need extra parentheses. Otherwise, insert
7528  * parens to ensure the expression looks atomic.
7529  */
7530  need_paren = !(IsA(expr, Var) ||
7531  IsA(expr, Aggref) ||
7532  IsA(expr, Param));
7533  if (need_paren)
7534  appendStringInfoChar(context->buf, '(');
7535 
7536  get_rule_expr(expr, context, false);
7537 
7538  if (need_paren)
7539  appendStringInfoChar(context->buf, ')');
7540 
7541  context->varprefix = save_varprefix;
7542 
7543  pop_ancestor_plan(dpns, &save_dpns);
7544 
7545  return;
7546  }
7547 
7548  /*
7549  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7550  */
7551  appendStringInfo(context->buf, "$%d", param->paramid);
7552 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7360
Definition: nodes.h:528
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4710
Definition: primnodes.h:181
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7906
int paramid
Definition: primnodes.h:263
StringInfo buf
Definition: ruleutils.c:110
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4689

◆ get_query_def()

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

Definition at line 4990 of file ruleutils.c.

References AcquireRewriteLocks(), deparse_context::appendparents, appendStringInfoString(), buf, deparse_context::buf, CHECK_FOR_INTERRUPTS, check_stack_depth(), CMD_DELETE, CMD_INSERT, CMD_NOTHING, CMD_SELECT, CMD_UPDATE, CMD_UTILITY, Query::commandType, elog, ERROR, EXPR_KIND_NONE, get_delete_query_def(), get_insert_query_def(), get_select_query_def(), get_update_query_def(), get_utility_query_def(), deparse_context::indentLevel, lcons(), list_copy(), list_length(), deparse_context::namespaces, NIL, deparse_context::prettyFlags, Query::rtable, set_deparse_for_query(), deparse_context::special_exprkind, deparse_context::varprefix, deparse_context::windowClause, deparse_context::windowTList, and deparse_context::wrapColumn.

Referenced by get_from_clause_item(), get_insert_query_def(), get_setop_query(), get_sublink_expr(), get_with_clause(), make_ruledef(), and make_viewdef().

4993 {
4994  deparse_context context;
4995  deparse_namespace dpns;
4996 
4997  /* Guard against excessively long or deeply-nested queries */
5000 
5001  /*
5002  * Before we begin to examine the query, acquire locks on referenced
5003  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5004  * consistent results. Note we assume it's OK to scribble on the passed
5005  * querytree!
5006  *
5007  * We are only deparsing the query (we are not about to execute it), so we
5008  * only need AccessShareLock on the relations it mentions.
5009  */
5010  AcquireRewriteLocks(query, false, false);
5011 
5012  context.buf = buf;
5013  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5014  context.windowClause = NIL;
5015  context.windowTList = NIL;
5016  context.