PostgreSQL Source Code  git master
ruleutils.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "access/amapi.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_language.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/tablespace.h"
#include "common/keywords.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "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 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 485 of file ruleutils.c.

Referenced by get_delete_query_def(), get_from_clause_item(), and get_update_query_def().

◆ PRETTY_INDENT

◆ PRETTY_PAREN

#define PRETTY_PAREN (   context)    ((context)->prettyFlags & PRETTYFLAG_PAREN)

◆ PRETTY_SCHEMA

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

Definition at line 101 of file ruleutils.c.

◆ PRETTYFLAG_INDENT

◆ PRETTYFLAG_PAREN

◆ PRETTYFLAG_SCHEMA

◆ PRETTYINDENT_JOIN

#define PRETTYINDENT_JOIN   4

Definition at line 85 of file ruleutils.c.

Referenced by get_from_clause_item().

◆ PRETTYINDENT_LIMIT

#define PRETTYINDENT_LIMIT   40 /* wrap limit */

Definition at line 88 of file ruleutils.c.

Referenced by appendContextKeyword().

◆ PRETTYINDENT_STD

◆ PRETTYINDENT_VAR

#define PRETTYINDENT_VAR   4

Definition at line 86 of file ruleutils.c.

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

◆ WRAP_COLUMN_DEFAULT

Typedef Documentation

◆ rsv_callback

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

Definition at line 302 of file ruleutils.c.

Function Documentation

◆ add_cast_to()

static void add_cast_to ( StringInfo  buf,
Oid  typid 
)
static

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

11158 {
11159  HeapTuple typetup;
11160  Form_pg_type typform;
11161  char *typname;
11162  char *nspname;
11163 
11164  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11165  if (!HeapTupleIsValid(typetup))
11166  elog(ERROR, "cache lookup failed for type %u", typid);
11167  typform = (Form_pg_type) GETSTRUCT(typetup);
11168 
11169  typname = NameStr(typform->typname);
11170  nspname = get_namespace_name(typform->typnamespace);
11171 
11172  appendStringInfo(buf, "::%s.%s",
11173  quote_identifier(nspname), quote_identifier(typname));
11174 
11175  ReleaseSysCache(typetup);
11176 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
NameData typname
Definition: pg_type.h:41
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

◆ appendContextKeyword()

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

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

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

◆ colname_is_unique()

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

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

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

◆ decompile_column_index_array()

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

Definition at line 2340 of file ruleutils.c.

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

Referenced by pg_get_constraintdef_worker().

2342 {
2343  Datum *keys;
2344  int nKeys;
2345  int j;
2346 
2347  /* Extract data from array of int16 */
2348  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2349  INT2OID, 2, true, TYPALIGN_SHORT,
2350  &keys, NULL, &nKeys);
2351 
2352  for (j = 0; j < nKeys; j++)
2353  {
2354  char *colName;
2355 
2356  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2357 
2358  if (j == 0)
2360  else
2361  appendStringInfo(buf, ", %s", quote_identifier(colName));
2362  }
2363 
2364  return nKeys;
2365 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
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:3483
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ deparse_context_for()

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

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

3284 {
3285  deparse_namespace *dpns;
3286  RangeTblEntry *rte;
3287 
3288  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3289 
3290  /* Build a minimal RTE for the rel */
3291  rte = makeNode(RangeTblEntry);
3292  rte->rtekind = RTE_RELATION;
3293  rte->relid = relid;
3294  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3296  rte->alias = makeAlias(aliasname, NIL);
3297  rte->eref = rte->alias;
3298  rte->lateral = false;
3299  rte->inh = false;
3300  rte->inFromCl = true;
3301 
3302  /* Build one-element rtable */
3303  dpns->rtable = list_make1(rte);
3304  dpns->subplans = NIL;
3305  dpns->ctes = NIL;
3306  dpns->appendrels = NULL;
3307  set_rtable_names(dpns, NIL, NULL);
3309 
3310  /* Return a one-deep namespace stack */
3311  return list_make1(dpns);
3312 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1115
#define AccessShareLock
Definition: lockdefs.h:36
AppendRelInfo ** appendrels
Definition: ruleutils.c:165
#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:3449
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:3659
RTEKind rtekind
Definition: parsenodes.h:977
Alias * eref
Definition: parsenodes.h:1116

◆ deparse_context_for_plan_tree()

List* deparse_context_for_plan_tree ( PlannedStmt pstmt,
List rtable_names 
)

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

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

◆ deparse_expression()

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

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

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

◆ deparse_expression_pretty()

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

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

3253 {
3255  deparse_context context;
3256 
3257  initStringInfo(&buf);
3258  context.buf = &buf;
3259  context.namespaces = dpcontext;
3260  context.windowClause = NIL;
3261  context.windowTList = NIL;
3262  context.varprefix = forceprefix;
3263  context.prettyFlags = prettyFlags;
3264  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3265  context.indentLevel = startIndent;
3266  context.special_exprkind = EXPR_KIND_NONE;
3267  context.appendparents = NULL;
3268 
3269  get_rule_expr(expr, &context, showimplicit);
3270 
3271  return buf.data;
3272 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define WRAP_COLUMN_DEFAULT
Definition: ruleutils.c:96
static char * buf
Definition: pg_test_fsync.c:68
ParseExprKind special_exprkind
Definition: ruleutils.c:120
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
List * windowTList
Definition: ruleutils.c:115
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7911
List * windowClause
Definition: ruleutils.c:114
Bitmapset * appendparents
Definition: ruleutils.c:122
StringInfo buf
Definition: ruleutils.c:112

◆ expand_colnames_array_to()

static void expand_colnames_array_to ( deparse_columns colinfo,
int  n 
)
static

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

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

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

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

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

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

11323 {
11324  char *result = NULL;
11325  HeapTuple tuple;
11326  Datum reloptions;
11327  bool isnull;
11328 
11329  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11330  if (!HeapTupleIsValid(tuple))
11331  elog(ERROR, "cache lookup failed for relation %u", relid);
11332 
11333  reloptions = SysCacheGetAttr(RELOID, tuple,
11334  Anum_pg_class_reloptions, &isnull);
11335  if (!isnull)
11336  {
11338 
11339  initStringInfo(&buf);
11340  get_reloptions(&buf, reloptions);
11341 
11342  result = buf.data;
11343  }
11344 
11345  ReleaseSysCache(tuple);
11346 
11347  return result;
11348 }
static void get_reloptions(StringInfo buf, Datum reloptions)
Definition: ruleutils.c:11266
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
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:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

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

11222 {
11223  HeapTuple tp;
11224  Form_pg_collation colltup;
11225  char *collname;
11226  char *nspname;
11227  char *result;
11228 
11229  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11230  if (!HeapTupleIsValid(tp))
11231  elog(ERROR, "cache lookup failed for collation %u", collid);
11232  colltup = (Form_pg_collation) GETSTRUCT(tp);
11233  collname = NameStr(colltup->collname);
11234 
11235  if (!CollationIsVisible(collid))
11236  nspname = get_namespace_name(colltup->collnamespace);
11237  else
11238  nspname = NULL;
11239 
11240  result = quote_qualified_identifier(nspname, collname);
11241 
11242  ReleaseSysCache(tp);
11243 
11244  return result;
11245 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2047
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

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

10938 {
10939  char *result;
10940  HeapTuple proctup;
10941  Form_pg_proc procform;
10942  char *proname;
10943  bool use_variadic;
10944  char *nspname;
10945  FuncDetailCode p_result;
10946  Oid p_funcid;
10947  Oid p_rettype;
10948  bool p_retset;
10949  int p_nvargs;
10950  Oid p_vatype;
10951  Oid *p_true_typeids;
10952  bool force_qualify = false;
10953 
10954  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
10955  if (!HeapTupleIsValid(proctup))
10956  elog(ERROR, "cache lookup failed for function %u", funcid);
10957  procform = (Form_pg_proc) GETSTRUCT(proctup);
10958  proname = NameStr(procform->proname);
10959 
10960  /*
10961  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
10962  * qualification in some special cases.
10963  */
10964  if (special_exprkind == EXPR_KIND_GROUP_BY)
10965  {
10966  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
10967  force_qualify = true;
10968  }
10969 
10970  /*
10971  * Determine whether VARIADIC should be printed. We must do this first
10972  * since it affects the lookup rules in func_get_detail().
10973  *
10974  * We always print VARIADIC if the function has a merged variadic-array
10975  * argument. Note that this is always the case for functions taking a
10976  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
10977  * and printed the array elements as separate arguments, the call could
10978  * match a newer non-VARIADIC function.
10979  */
10980  if (use_variadic_p)
10981  {
10982  /* Parser should not have set funcvariadic unless fn is variadic */
10983  Assert(!has_variadic || OidIsValid(procform->provariadic));
10984  use_variadic = has_variadic;
10985  *use_variadic_p = use_variadic;
10986  }
10987  else
10988  {
10989  Assert(!has_variadic);
10990  use_variadic = false;
10991  }
10992 
10993  /*
10994  * The idea here is to schema-qualify only if the parser would fail to
10995  * resolve the correct function given the unqualified func name with the
10996  * specified argtypes and VARIADIC flag. But if we already decided to
10997  * force qualification, then we can skip the lookup and pretend we didn't
10998  * find it.
10999  */
11000  if (!force_qualify)
11001  p_result = func_get_detail(list_make1(makeString(proname)),
11002  NIL, argnames, nargs, argtypes,
11003  !use_variadic, true,
11004  &p_funcid, &p_rettype,
11005  &p_retset, &p_nvargs, &p_vatype,
11006  &p_true_typeids, NULL);
11007  else
11008  {
11009  p_result = FUNCDETAIL_NOTFOUND;
11010  p_funcid = InvalidOid;
11011  }
11012 
11013  if ((p_result == FUNCDETAIL_NORMAL ||
11014  p_result == FUNCDETAIL_AGGREGATE ||
11015  p_result == FUNCDETAIL_WINDOWFUNC) &&
11016  p_funcid == funcid)
11017  nspname = NULL;
11018  else
11019  nspname = get_namespace_name(procform->pronamespace);
11020 
11021  result = quote_qualified_identifier(nspname, proname);
11022 
11023  ReleaseSysCache(proctup);
11024 
11025  return result;
11026 }
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:651
#define list_make1(x1)
Definition: pg_list.h:206
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
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:745
FuncDetailCode func_get_detail(List *funcname, List *fargs, List *fargnames, int nargs, Oid *argtypes, bool expand_variadic, bool expand_defaults, Oid *funcid, Oid *rettype, bool *retset, int *nvargs, Oid *vatype, Oid **true_typeids, List **argdefaults)
Definition: parse_func.c:1382
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

◆ generate_opclass_name()

char* generate_opclass_name ( Oid  opclass)

Definition at line 10579 of file ruleutils.c.

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

Referenced by index_opclass_options().

10580 {
10582 
10583  initStringInfo(&buf);
10584  get_opclass_name(opclass, InvalidOid, &buf);
10585 
10586  return &buf.data[1]; /* get_opclass_name() prepends space */
10587 }
static char * buf
Definition: pg_test_fsync.c:68
static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf)
Definition: ruleutils.c:10541
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 11117 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().

11121 {
11122  HeapTuple opertup;
11123  Form_pg_operator operform;
11124  char *oprname;
11125  char *nspname;
11126 
11127  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11128  if (!HeapTupleIsValid(opertup))
11129  elog(ERROR, "cache lookup failed for operator %u", opoid);
11130  operform = (Form_pg_operator) GETSTRUCT(opertup);
11131  Assert(operform->oprkind == 'b');
11132  oprname = NameStr(operform->oprname);
11133 
11134  nspname = get_namespace_name(operform->oprnamespace);
11135 
11136  appendStringInfoString(buf, leftop);
11137  if (leftoptype != operform->oprleft)
11138  add_cast_to(buf, operform->oprleft);
11139  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11140  appendStringInfoString(buf, oprname);
11141  appendStringInfo(buf, ") %s", rightop);
11142  if (rightoptype != operform->oprright)
11143  add_cast_to(buf, operform->oprright);
11144 
11145  ReleaseSysCache(opertup);
11146 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11157
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

◆ generate_operator_name()

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

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

11041 {
11043  HeapTuple opertup;
11044  Form_pg_operator operform;
11045  char *oprname;
11046  char *nspname;
11047  Operator p_result;
11048 
11049  initStringInfo(&buf);
11050 
11051  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11052  if (!HeapTupleIsValid(opertup))
11053  elog(ERROR, "cache lookup failed for operator %u", operid);
11054  operform = (Form_pg_operator) GETSTRUCT(opertup);
11055  oprname = NameStr(operform->oprname);
11056 
11057  /*
11058  * The idea here is to schema-qualify only if the parser would fail to
11059  * resolve the correct operator given the unqualified op name with the
11060  * specified argtypes.
11061  */
11062  switch (operform->oprkind)
11063  {
11064  case 'b':
11065  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11066  true, -1);
11067  break;
11068  case 'l':
11069  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11070  true, -1);
11071  break;
11072  default:
11073  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11074  p_result = NULL; /* keep compiler quiet */
11075  break;
11076  }
11077 
11078  if (p_result != NULL && oprid(p_result) == operid)
11079  nspname = NULL;
11080  else
11081  {
11082  nspname = get_namespace_name(operform->oprnamespace);
11083  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11084  }
11085 
11086  appendStringInfoString(&buf, oprname);
11087 
11088  if (nspname)
11089  appendStringInfoChar(&buf, ')');
11090 
11091  if (p_result != NULL)
11092  ReleaseSysCache(p_result);
11093 
11094  ReleaseSysCache(opertup);
11095 
11096  return buf.data;
11097 }
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:10709
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:43
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:3191
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:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622
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 10893 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().

10894 {
10895  HeapTuple tp;
10896  Form_pg_class reltup;
10897  char *relname;
10898  char *nspname;
10899  char *result;
10900 
10901  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10902  if (!HeapTupleIsValid(tp))
10903  elog(ERROR, "cache lookup failed for relation %u", relid);
10904  reltup = (Form_pg_class) GETSTRUCT(tp);
10905  relname = NameStr(reltup->relname);
10906 
10907  nspname = get_namespace_name(reltup->relnamespace);
10908  if (!nspname)
10909  elog(ERROR, "cache lookup failed for namespace %u",
10910  reltup->relnamespace);
10911 
10912  result = quote_qualified_identifier(nspname, relname);
10913 
10914  ReleaseSysCache(tp);
10915 
10916  return result;
10917 }
#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:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

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

11189 {
11190  HeapTuple tp;
11191  Form_pg_type typtup;
11192  char *typname;
11193  char *nspname;
11194  char *result;
11195 
11197  if (!HeapTupleIsValid(tp))
11198  elog(ERROR, "cache lookup failed for type %u", typid);
11199  typtup = (Form_pg_type) GETSTRUCT(tp);
11200  typname = NameStr(typtup->typname);
11201 
11202  nspname = get_namespace_name(typtup->typnamespace);
11203  if (!nspname)
11204  elog(ERROR, "cache lookup failed for namespace %u",
11205  typtup->typnamespace);
11206 
11207  result = quote_qualified_identifier(nspname, typname);
11208 
11209  ReleaseSysCache(tp);
11210 
11211  return result;
11212 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
NameData typname
Definition: pg_type.h:41
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:255
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622

◆ generate_relation_name()

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

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

10834 {
10835  HeapTuple tp;
10836  Form_pg_class reltup;
10837  bool need_qual;
10838  ListCell *nslist;
10839  char *relname;
10840  char *nspname;
10841  char *result;
10842 
10843  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10844  if (!HeapTupleIsValid(tp))
10845  elog(ERROR, "cache lookup failed for relation %u", relid);
10846  reltup = (Form_pg_class) GETSTRUCT(tp);
10847  relname = NameStr(reltup->relname);
10848 
10849  /* Check for conflicting CTE name */
10850  need_qual = false;
10851  foreach(nslist, namespaces)
10852  {
10853  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10854  ListCell *ctlist;
10855 
10856  foreach(ctlist, dpns->ctes)
10857  {
10858  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10859 
10860  if (strcmp(cte->ctename, relname) == 0)
10861  {
10862  need_qual = true;
10863  break;
10864  }
10865  }
10866  if (need_qual)
10867  break;
10868  }
10869 
10870  /* Otherwise, qualify the name if not visible in search path */
10871  if (!need_qual)
10872  need_qual = !RelationIsVisible(relid);
10873 
10874  if (need_qual)
10875  nspname = get_namespace_name(reltup->relnamespace);
10876  else
10877  nspname = NULL;
10878 
10879  result = quote_qualified_identifier(nspname, relname);
10880 
10881  ReleaseSysCache(tp);
10882 
10883  return result;
10884 }
#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:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:214
#define NameStr(name)
Definition: c.h:622

◆ get_agg_combine_expr()

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

Definition at line 9413 of file ruleutils.c.

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

Referenced by get_agg_expr().

9414 {
9415  Aggref *aggref;
9416  Aggref *original_aggref = callback_arg;
9417 
9418  if (!IsA(node, Aggref))
9419  elog(ERROR, "combining Aggref does not point to an Aggref");
9420 
9421  aggref = (Aggref *) node;
9422  get_agg_expr(aggref, context, original_aggref);
9423 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9306
#define elog(elevel,...)
Definition: elog.h:214

◆ get_agg_expr()

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

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

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

5394 {
5395  StringInfo buf = context->buf;
5396  RangeTblEntry *values_rte;
5397  char *sep;
5398  ListCell *l;
5399 
5400  if (PRETTY_INDENT(context))
5401  {
5402  context->indentLevel += PRETTYINDENT_STD;
5403  appendStringInfoChar(buf, ' ');
5404  }
5405 
5406  /*
5407  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5408  * VALUES part. This reverses what transformValuesClause() did at parse
5409  * time.
5410  */
5411  values_rte = get_simple_values_rte(query, resultDesc);
5412  if (values_rte)
5413  {
5414  get_values_def(values_rte->values_lists, context);
5415  return;
5416  }
5417 
5418  /*
5419  * Build up the query string - first we say SELECT
5420  */
5421  appendStringInfoString(buf, "SELECT");
5422 
5423  /* Add the DISTINCT clause if given */
5424  if (query->distinctClause != NIL)
5425  {
5426  if (query->hasDistinctOn)
5427  {
5428  appendStringInfoString(buf, " DISTINCT ON (");
5429  sep = "";
5430  foreach(l, query->distinctClause)
5431  {
5432  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5433 
5434  appendStringInfoString(buf, sep);
5436  false, context);
5437  sep = ", ";
5438  }
5439  appendStringInfoChar(buf, ')');
5440  }
5441  else
5442  appendStringInfoString(buf, " DISTINCT");
5443  }
5444 
5445  /* Then we tell what to select (the targetlist) */
5446  get_target_list(query->targetList, context, resultDesc);
5447 
5448  /* Add the FROM clause if needed */
5449  get_from_clause(query, " FROM ", context);
5450 
5451  /* Add the WHERE clause if given */
5452  if (query->jointree->quals != NULL)
5453  {
5454  appendContextKeyword(context, " WHERE ",
5456  get_rule_expr(query->jointree->quals, context, false);
5457  }
5458 
5459  /* Add the GROUP BY clause if given */
5460  if (query->groupClause != NULL || query->groupingSets != NULL)
5461  {
5462  ParseExprKind save_exprkind;
5463 
5464  appendContextKeyword(context, " GROUP BY ",
5466 
5467  save_exprkind = context->special_exprkind;
5469 
5470  if (query->groupingSets == NIL)
5471  {
5472  sep = "";
5473  foreach(l, query->groupClause)
5474  {
5475  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5476 
5477  appendStringInfoString(buf, sep);
5479  false, context);
5480  sep = ", ";
5481  }
5482  }
5483  else
5484  {
5485  sep = "";
5486  foreach(l, query->groupingSets)
5487  {
5488  GroupingSet *grp = lfirst(l);
5489 
5490  appendStringInfoString(buf, sep);
5491  get_rule_groupingset(grp, query->targetList, true, context);
5492  sep = ", ";
5493  }
5494  }
5495 
5496  context->special_exprkind = save_exprkind;
5497  }
5498 
5499  /* Add the HAVING clause if given */
5500  if (query->havingQual != NULL)
5501  {
5502  appendContextKeyword(context, " HAVING ",
5504  get_rule_expr(query->havingQual, context, false);
5505  }
5506 
5507  /* Add the WINDOW clause if needed */
5508  if (query->windowClause != NIL)
5509  get_rule_windowclause(query, context);
5510 }
#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:5519
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5783
Index tleSortGroupRef
Definition: parsenodes.h:1258
List * groupingSets
Definition: parsenodes.h:150
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9977
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:5957
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
ParseExprKind
Definition: parse_node.h:38
List * values_lists
Definition: parsenodes.h:1075
Node * quals
Definition: primnodes.h:1514
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:7806
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5323
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5839
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
ParseExprKind special_exprkind
Definition: ruleutils.c:120
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:7911
#define lfirst(lc)
Definition: pg_list.h:169
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5069
List * groupClause
Definition: parsenodes.h:148
StringInfo buf
Definition: ruleutils.c:112
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 9506 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().

9509 {
9510  StringInfo buf = context->buf;
9511 
9512  /*
9513  * Since parse_coerce.c doesn't immediately collapse application of
9514  * length-coercion functions to constants, what we'll typically see in
9515  * such cases is a Const with typmod -1 and a length-coercion function
9516  * right above it. Avoid generating redundant output. However, beware of
9517  * suppressing casts when the user actually wrote something like
9518  * 'foo'::text::char(3).
9519  *
9520  * Note: it might seem that we are missing the possibility of needing to
9521  * print a COLLATE clause for such a Const. However, a Const could only
9522  * have nondefault collation in a post-constant-folding tree, in which the
9523  * length coercion would have been folded too. See also the special
9524  * handling of CollateExpr in coerce_to_target_type(): any collation
9525  * marking will be above the coercion node, not below it.
9526  */
9527  if (arg && IsA(arg, Const) &&
9528  ((Const *) arg)->consttype == resulttype &&
9529  ((Const *) arg)->consttypmod == -1)
9530  {
9531  /* Show the constant without normal ::typename decoration */
9532  get_const_expr((Const *) arg, context, -1);
9533  }
9534  else
9535  {
9536  if (!PRETTY_PAREN(context))
9537  appendStringInfoChar(buf, '(');
9538  get_rule_expr_paren(arg, context, false, parentNode);
9539  if (!PRETTY_PAREN(context))
9540  appendStringInfoChar(buf, ')');
9541  }
9542 
9543  /*
9544  * Never emit resulttype(arg) functional notation. A pg_proc entry could
9545  * take precedence, and a resulttype in pg_temp would require schema
9546  * qualification that format_type_with_typemod() would usually omit. We've
9547  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
9548  * would work fine.
9549  */
9550  appendStringInfo(buf, "::%s",
9551  format_type_with_typemod(resulttype, resulttypmod));
9552 }
#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:7879
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9570
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:99
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:112

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

10407 {
10408  StringInfo buf = context->buf;
10409  int i;
10410  bool first = true;
10411 
10412  /* Don't print aliases if not needed */
10413  if (!colinfo->printaliases)
10414  return;
10415 
10416  for (i = 0; i < colinfo->num_new_cols; i++)
10417  {
10418  char *colname = colinfo->new_colnames[i];
10419 
10420  if (first)
10421  {
10422  appendStringInfoChar(buf, '(');
10423  first = false;
10424  }
10425  else
10426  appendStringInfoString(buf, ", ");
10428  }
10429  if (!first)
10430  appendStringInfoChar(buf, ')');
10431 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
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:112
int i
char ** new_colnames
Definition: ruleutils.c:255

◆ get_const_collation()

static void get_const_collation ( Const constval,
deparse_context context 
)
static

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

9701 {
9702  StringInfo buf = context->buf;
9703 
9704  if (OidIsValid(constval->constcollid))
9705  {
9706  Oid typcollation = get_typcollation(constval->consttype);
9707 
9708  if (constval->constcollid != typcollation)
9709  {
9710  appendStringInfo(buf, " COLLATE %s",
9712  }
9713  }
9714 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11221
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:2933
StringInfo buf
Definition: ruleutils.c:112

◆ get_const_expr()

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

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

9571 {
9572  StringInfo buf = context->buf;
9573  Oid typoutput;
9574  bool typIsVarlena;
9575  char *extval;
9576  bool needlabel = false;
9577 
9578  if (constval->constisnull)
9579  {
9580  /*
9581  * Always label the type of a NULL constant to prevent misdecisions
9582  * about type when reparsing.
9583  */
9584  appendStringInfoString(buf, "NULL");
9585  if (showtype >= 0)
9586  {
9587  appendStringInfo(buf, "::%s",
9589  constval->consttypmod));
9590  get_const_collation(constval, context);
9591  }
9592  return;
9593  }
9594 
9595  getTypeOutputInfo(constval->consttype,
9596  &typoutput, &typIsVarlena);
9597 
9598  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9599 
9600  switch (constval->consttype)
9601  {
9602  case INT4OID:
9603 
9604  /*
9605  * INT4 can be printed without any decoration, unless it is
9606  * negative; in that case print it as '-nnn'::integer to ensure
9607  * that the output will re-parse as a constant, not as a constant
9608  * plus operator. In most cases we could get away with printing
9609  * (-nnn) instead, because of the way that gram.y handles negative
9610  * literals; but that doesn't work for INT_MIN, and it doesn't
9611  * seem that much prettier anyway.
9612  */
9613  if (extval[0] != '-')
9614  appendStringInfoString(buf, extval);
9615  else
9616  {
9617  appendStringInfo(buf, "'%s'", extval);
9618  needlabel = true; /* we must attach a cast */
9619  }
9620  break;
9621 
9622  case NUMERICOID:
9623 
9624  /*
9625  * NUMERIC can be printed without quotes if it looks like a float
9626  * constant (not an integer, and not Infinity or NaN) and doesn't
9627  * have a leading sign (for the same reason as for INT4).
9628  */
9629  if (isdigit((unsigned char) extval[0]) &&
9630  strcspn(extval, "eE.") != strlen(extval))
9631  {
9632  appendStringInfoString(buf, extval);
9633  }
9634  else
9635  {
9636  appendStringInfo(buf, "'%s'", extval);
9637  needlabel = true; /* we must attach a cast */
9638  }
9639  break;
9640 
9641  case BOOLOID:
9642  if (strcmp(extval, "t") == 0)
9643  appendStringInfoString(buf, "true");
9644  else
9645  appendStringInfoString(buf, "false");
9646  break;
9647 
9648  default:
9649  simple_quote_literal(buf, extval);
9650  break;
9651  }
9652 
9653  pfree(extval);
9654 
9655  if (showtype < 0)
9656  return;
9657 
9658  /*
9659  * For showtype == 0, append ::typename unless the constant will be
9660  * implicitly typed as the right type when it is read in.
9661  *
9662  * XXX this code has to be kept in sync with the behavior of the parser,
9663  * especially make_const.
9664  */
9665  switch (constval->consttype)
9666  {
9667  case BOOLOID:
9668  case UNKNOWNOID:
9669  /* These types can be left unlabeled */
9670  needlabel = false;
9671  break;
9672  case INT4OID:
9673  /* We determined above whether a label is needed */
9674  break;
9675  case NUMERICOID:
9676 
9677  /*
9678  * Float-looking constants will be typed as numeric, which we
9679  * checked above; but if there's a nondefault typmod we need to
9680  * show it.
9681  */
9682  needlabel |= (constval->consttypmod >= 0);
9683  break;
9684  default:
9685  needlabel = true;
9686  break;
9687  }
9688  if (needlabel || showtype > 0)
9689  appendStringInfo(buf, "::%s",
9691  constval->consttypmod));
9692 
9693  get_const_collation(constval, context);
9694 }
Datum constvalue
Definition: primnodes.h:214
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2784
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:9720
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9700
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:1657
StringInfo buf
Definition: ruleutils.c:112
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 6518 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().

6519 {
6520  StringInfo buf = context->buf;
6521  RangeTblEntry *rte;
6522 
6523  /* Insert the WITH clause if given */
6524  get_with_clause(query, context);
6525 
6526  /*
6527  * Start the query with DELETE FROM relname
6528  */
6529  rte = rt_fetch(query->resultRelation, query->rtable);
6530  Assert(rte->rtekind == RTE_RELATION);
6531  if (PRETTY_INDENT(context))
6532  {
6533  appendStringInfoChar(buf, ' ');
6534  context->indentLevel += PRETTYINDENT_STD;
6535  }
6536  appendStringInfo(buf, "DELETE FROM %s%s",
6537  only_marker(rte),
6539  if (rte->alias != NULL)
6540  appendStringInfo(buf, " %s",
6542 
6543  /* Add the USING clause if given */
6544  get_from_clause(query, " USING ", context);
6545 
6546  /* Add a WHERE clause if given */
6547  if (query->jointree->quals != NULL)
6548  {
6549  appendContextKeyword(context, " WHERE ",
6551  get_rule_expr(query->jointree->quals, context, false);
6552  }
6553 
6554  /* Add RETURNING if present */
6555  if (query->returningList)
6556  {
6557  appendContextKeyword(context, " RETURNING",
6559  get_target_list(query->returningList, context, NULL);
6560  }
6561 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5112
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
Alias * alias
Definition: parsenodes.h:1115
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:5519
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:9977
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
Node * quals
Definition: primnodes.h:1514
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10833
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:7806
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define Assert(condition)
Definition: c.h:745
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7911
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:485
RTEKind rtekind
Definition: parsenodes.h:977
StringInfo buf
Definition: ruleutils.c:112

◆ get_from_clause()

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

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

9978 {
9979  StringInfo buf = context->buf;
9980  bool first = true;
9981  ListCell *l;
9982 
9983  /*
9984  * We use the query's jointree as a guide to what to print. However, we
9985  * must ignore auto-added RTEs that are marked not inFromCl. (These can
9986  * only appear at the top level of the jointree, so it's sufficient to
9987  * check here.) This check also ensures we ignore the rule pseudo-RTEs
9988  * for NEW and OLD.
9989  */
9990  foreach(l, query->jointree->fromlist)
9991  {
9992  Node *jtnode = (Node *) lfirst(l);
9993 
9994  if (IsA(jtnode, RangeTblRef))
9995  {
9996  int varno = ((RangeTblRef *) jtnode)->rtindex;
9997  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
9998 
9999  if (!rte->inFromCl)
10000  continue;
10001  }
10002 
10003  if (first)
10004  {
10005  appendContextKeyword(context, prefix,
10007  first = false;
10008 
10009  get_from_clause_item(jtnode, query, context);
10010  }
10011  else
10012  {
10013  StringInfoData itembuf;
10014 
10015  appendStringInfoString(buf, ", ");
10016 
10017  /*
10018  * Put the new FROM item's text into itembuf so we can decide
10019  * after we've got it whether or not it needs to go on a new line.
10020  */
10021  initStringInfo(&itembuf);
10022  context->buf = &itembuf;
10023 
10024  get_from_clause_item(jtnode, query, context);
10025 
10026  /* Restore context's output buffer */
10027  context->buf = buf;
10028 
10029  /* Consider line-wrapping if enabled */
10030  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10031  {
10032  /* Does the new item start with a new line? */
10033  if (itembuf.len > 0 && itembuf.data[0] == '\n')
10034  {
10035  /* If so, we shouldn't add anything */
10036  /* instead, remove any trailing spaces currently in buf */
10038  }
10039  else
10040  {
10041  char *trailing_nl;
10042 
10043  /* Locate the start of the current line in the buffer */
10044  trailing_nl = strrchr(buf->data, '\n');
10045  if (trailing_nl == NULL)
10046  trailing_nl = buf->data;
10047  else
10048  trailing_nl++;
10049 
10050  /*
10051  * Add a newline, plus some indentation, if the new item
10052  * would cause an overflow.
10053  */
10054  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10055  appendContextKeyword(context, "", -PRETTYINDENT_STD,
10058  }
10059  }
10060 
10061  /* Add the new item */
10062  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10063 
10064  /* clean up */
10065  pfree(itembuf.data);
10066  }
10067  }
10068 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
FromExpr * jointree
Definition: parsenodes.h:138
#define PRETTYINDENT_VAR
Definition: ruleutils.c:86
Definition: nodes.h:528
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
List * fromlist
Definition: primnodes.h:1513
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:7806
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7860
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define lfirst(lc)
Definition: pg_list.h:169
StringInfo buf
Definition: ruleutils.c:112
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:10071

◆ get_from_clause_coldeflist()

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

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

10449 {
10450  StringInfo buf = context->buf;
10451  ListCell *l1;
10452  ListCell *l2;
10453  ListCell *l3;
10454  ListCell *l4;
10455  int i;
10456 
10457  appendStringInfoChar(buf, '(');
10458 
10459  i = 0;
10460  forfour(l1, rtfunc->funccoltypes,
10461  l2, rtfunc->funccoltypmods,
10462  l3, rtfunc->funccolcollations,
10463  l4, rtfunc->funccolnames)
10464  {
10465  Oid atttypid = lfirst_oid(l1);
10466  int32 atttypmod = lfirst_int(l2);
10467  Oid attcollation = lfirst_oid(l3);
10468  char *attname;
10469 
10470  if (colinfo)
10471  attname = colinfo->colnames[i];
10472  else
10473  attname = strVal(lfirst(l4));
10474 
10475  Assert(attname); /* shouldn't be any dropped columns here */
10476 
10477  if (i > 0)
10478  appendStringInfoString(buf, ", ");
10479  appendStringInfo(buf, "%s %s",
10480  quote_identifier(attname),
10481  format_type_with_typemod(atttypid, atttypmod));
10482  if (OidIsValid(attcollation) &&
10483  attcollation != get_typcollation(atttypid))
10484  appendStringInfo(buf, " COLLATE %s",
10485  generate_collation_name(attcollation));
10486 
10487  i++;
10488  }
10489 
10490  appendStringInfoChar(buf, ')');
10491 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11221
signed int int32
Definition: c.h:362
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:1154
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2933
List * funccolcollations
Definition: parsenodes.h:1155
#define Assert(condition)
Definition: c.h:745
#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:112
int i
#define lfirst_oid(lc)
Definition: pg_list.h:171
char ** colnames
Definition: ruleutils.c:238

◆ get_from_clause_item()

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

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

10072 {
10073  StringInfo buf = context->buf;
10075 
10076  if (IsA(jtnode, RangeTblRef))
10077  {
10078  int varno = ((RangeTblRef *) jtnode)->rtindex;
10079  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10080  char *refname = get_rtable_name(varno, context);
10081  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10082  RangeTblFunction *rtfunc1 = NULL;
10083  bool printalias;
10084 
10085  if (rte->lateral)
10086  appendStringInfoString(buf, "LATERAL ");
10087 
10088  /* Print the FROM item proper */
10089  switch (rte->rtekind)
10090  {
10091  case RTE_RELATION:
10092  /* Normal relation RTE */
10093  appendStringInfo(buf, "%s%s",
10094  only_marker(rte),
10096  context->namespaces));
10097  break;
10098  case RTE_SUBQUERY:
10099  /* Subquery RTE */
10100  appendStringInfoChar(buf, '(');
10101  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10102  context->prettyFlags, context->wrapColumn,
10103  context->indentLevel);
10104  appendStringInfoChar(buf, ')');
10105  break;
10106  case RTE_FUNCTION:
10107  /* Function RTE */
10108  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10109 
10110  /*
10111  * Omit ROWS FROM() syntax for just one function, unless it
10112  * has both a coldeflist and WITH ORDINALITY. If it has both,
10113  * we must use ROWS FROM() syntax to avoid ambiguity about
10114  * whether the coldeflist includes the ordinality column.
10115  */
10116  if (list_length(rte->functions) == 1 &&
10117  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10118  {
10119  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10120  /* we'll print the coldeflist below, if it has one */
10121  }
10122  else
10123  {
10124  bool all_unnest;
10125  ListCell *lc;
10126 
10127  /*
10128  * If all the function calls in the list are to unnest,
10129  * and none need a coldeflist, then collapse the list back
10130  * down to UNNEST(args). (If we had more than one
10131  * built-in unnest function, this would get more
10132  * difficult.)
10133  *
10134  * XXX This is pretty ugly, since it makes not-terribly-
10135  * future-proof assumptions about what the parser would do
10136  * with the output; but the alternative is to emit our
10137  * nonstandard ROWS FROM() notation for what might have
10138  * been a perfectly spec-compliant multi-argument
10139  * UNNEST().
10140  */
10141  all_unnest = true;
10142  foreach(lc, rte->functions)
10143  {
10144  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10145 
10146  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10147  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
10148  rtfunc->funccolnames != NIL)
10149  {
10150  all_unnest = false;
10151  break;
10152  }
10153  }
10154 
10155  if (all_unnest)
10156  {
10157  List *allargs = NIL;
10158 
10159  foreach(lc, rte->functions)
10160  {
10161  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10162  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10163 
10164  allargs = list_concat(allargs, args);
10165  }
10166 
10167  appendStringInfoString(buf, "UNNEST(");
10168  get_rule_expr((Node *) allargs, context, true);
10169  appendStringInfoChar(buf, ')');
10170  }
10171  else
10172  {
10173  int funcno = 0;
10174 
10175  appendStringInfoString(buf, "ROWS FROM(");
10176  foreach(lc, rte->functions)
10177  {
10178  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10179 
10180  if (funcno > 0)
10181  appendStringInfoString(buf, ", ");
10182  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10183  if (rtfunc->funccolnames != NIL)
10184  {
10185  /* Reconstruct the column definition list */
10186  appendStringInfoString(buf, " AS ");
10188  NULL,
10189  context);
10190  }
10191  funcno++;
10192  }
10193  appendStringInfoChar(buf, ')');
10194  }
10195  /* prevent printing duplicate coldeflist below */
10196  rtfunc1 = NULL;
10197  }
10198  if (rte->funcordinality)
10199  appendStringInfoString(buf, " WITH ORDINALITY");
10200  break;
10201  case RTE_TABLEFUNC:
10202  get_tablefunc(rte->tablefunc, context, true);
10203  break;
10204  case RTE_VALUES:
10205  /* Values list RTE */
10206  appendStringInfoChar(buf, '(');
10207  get_values_def(rte->values_lists, context);
10208  appendStringInfoChar(buf, ')');
10209  break;
10210  case RTE_CTE:
10212  break;
10213  default:
10214  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10215  break;
10216  }
10217 
10218  /* Print the relation alias, if needed */
10219  printalias = false;
10220  if (rte->alias != NULL)
10221  {
10222  /* Always print alias if user provided one */
10223  printalias = true;
10224  }
10225  else if (colinfo->printaliases)
10226  {
10227  /* Always print alias if we need to print column aliases */
10228  printalias = true;
10229  }
10230  else if (rte->rtekind == RTE_RELATION)
10231  {
10232  /*
10233  * No need to print alias if it's same as relation name (this
10234  * would normally be the case, but not if set_rtable_names had to
10235  * resolve a conflict).
10236  */
10237  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10238  printalias = true;
10239  }
10240  else if (rte->rtekind == RTE_FUNCTION)
10241  {
10242  /*
10243  * For a function RTE, always print alias. This covers possible
10244  * renaming of the function and/or instability of the
10245  * FigureColname rules for things that aren't simple functions.
10246  * Note we'd need to force it anyway for the columndef list case.
10247  */
10248  printalias = true;
10249  }
10250  else if (rte->rtekind == RTE_VALUES)
10251  {
10252  /* Alias is syntactically required for VALUES */
10253  printalias = true;
10254  }
10255  else if (rte->rtekind == RTE_CTE)
10256  {
10257  /*
10258  * No need to print alias if it's same as CTE name (this would
10259  * normally be the case, but not if set_rtable_names had to
10260  * resolve a conflict).
10261  */
10262  if (strcmp(refname, rte->ctename) != 0)
10263  printalias = true;
10264  }
10265  if (printalias)
10266  appendStringInfo(buf, " %s", quote_identifier(refname));
10267 
10268  /* Print the column definitions or aliases, if needed */
10269  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10270  {
10271  /* Reconstruct the columndef list, which is also the aliases */
10272  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10273  }
10274  else
10275  {
10276  /* Else print column aliases as needed */
10277  get_column_alias_list(colinfo, context);
10278  }
10279 
10280  /* Tablesample clause must go after any alias */
10281  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10282  get_tablesample_def(rte->tablesample, context);
10283  }
10284  else if (IsA(jtnode, JoinExpr))
10285  {
10286  JoinExpr *j = (JoinExpr *) jtnode;
10287  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10288  bool need_paren_on_right;
10289 
10290  need_paren_on_right = PRETTY_PAREN(context) &&
10291  !IsA(j->rarg, RangeTblRef) &&
10292  !(IsA(j->rarg, JoinExpr) && ((JoinExpr *) j->rarg)->alias != NULL);
10293 
10294  if (!PRETTY_PAREN(context) || j->alias != NULL)
10295  appendStringInfoChar(buf, '(');
10296 
10297  get_from_clause_item(j->larg, query, context);
10298 
10299  switch (j->jointype)
10300  {
10301  case JOIN_INNER:
10302  if (j->quals)
10303  appendContextKeyword(context, " JOIN ",
10307  else
10308  appendContextKeyword(context, " CROSS JOIN ",
10312  break;
10313  case JOIN_LEFT:
10314  appendContextKeyword(context, " LEFT JOIN ",
10318  break;
10319  case JOIN_FULL:
10320  appendContextKeyword(context, " FULL JOIN ",
10324  break;
10325  case JOIN_RIGHT:
10326  appendContextKeyword(context, " RIGHT JOIN ",
10330  break;
10331  default:
10332  elog(ERROR, "unrecognized join type: %d",
10333  (int) j->jointype);
10334  }
10335 
10336  if (need_paren_on_right)
10337  appendStringInfoChar(buf, '(');
10338  get_from_clause_item(j->rarg, query, context);
10339  if (need_paren_on_right)
10340  appendStringInfoChar(buf, ')');
10341 
10342  if (j->usingClause)
10343  {
10344  ListCell *lc;
10345  bool first = true;
10346 
10347  appendStringInfoString(buf, " USING (");
10348  /* Use the assigned names, not what's in usingClause */
10349  foreach(lc, colinfo->usingNames)
10350  {
10351  char *colname = (char *) lfirst(lc);
10352 
10353  if (first)
10354  first = false;
10355  else
10356  appendStringInfoString(buf, ", ");
10358  }
10359  appendStringInfoChar(buf, ')');
10360  }
10361  else if (j->quals)
10362  {
10363  appendStringInfoString(buf, " ON ");
10364  if (!PRETTY_PAREN(context))
10365  appendStringInfoChar(buf, '(');
10366  get_rule_expr(j->quals, context, false);
10367  if (!PRETTY_PAREN(context))
10368  appendStringInfoChar(buf, ')');
10369  }
10370  else if (j->jointype != JOIN_INNER)
10371  {
10372  /* If we didn't say CROSS JOIN above, we must provide an ON */
10373  appendStringInfoString(buf, " ON TRUE");
10374  }
10375 
10376  if (!PRETTY_PAREN(context) || j->alias != NULL)
10377  appendStringInfoChar(buf, ')');
10378 
10379  /* Yes, it's correct to put alias after the right paren ... */
10380  if (j->alias != NULL)
10381  {
10382  /*
10383  * Note that it's correct to emit an alias clause if and only if
10384  * there was one originally. Otherwise we'd be converting a named
10385  * join to unnamed or vice versa, which creates semantic
10386  * subtleties we don't want. However, we might print a different
10387  * alias name than was there originally.
10388  */
10389  appendStringInfo(buf, " %s",
10391  context)));
10392  get_column_alias_list(colinfo, context);
10393  }
10394  }
10395  else
10396  elog(ERROR, "unrecognized node type: %d",
10397  (int) nodeTag(jtnode));
10398 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10813
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:85
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
Alias * alias
Definition: parsenodes.h:1115
Definition: nodes.h:528
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
bool funcordinality
Definition: parsenodes.h:1065
List * values_lists
Definition: parsenodes.h:1075
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10833
Node * larg
Definition: primnodes.h:1493
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10497
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:43
List * usingNames
Definition: ruleutils.c:285
TableFunc * tablefunc
Definition: parsenodes.h:1070
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:99
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7806
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:289
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
List * usingClause
Definition: primnodes.h:1495
Node * quals
Definition: primnodes.h:1496
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9872
Node * rarg
Definition: primnodes.h:1494
Alias * alias
Definition: primnodes.h:1497
JoinType jointype
Definition: primnodes.h:1491
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7911
#define lfirst(lc)
Definition: pg_list.h:169
List * functions
Definition: parsenodes.h:1064
#define only_marker(rte)
Definition: ruleutils.c:485
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:4995
#define nodeTag(nodeptr)
Definition: nodes.h:533
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5069
RTEKind rtekind
Definition: parsenodes.h:977
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10406
char * ctename
Definition: parsenodes.h:1080
Query * subquery
Definition: parsenodes.h:1012
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:214
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10446
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9131
int rtindex
Definition: primnodes.h:1498
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1007
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4548
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10071

◆ get_func_expr()

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

Definition at line 9221 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, FuncExpr::args, buf, deparse_context::buf, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, ereport, errcode(), errmsg(), ERROR, exprIsLengthCoercion(), exprType(), FUNC_MAX_ARGS, FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcvariadic, generate_function_name(), get_coercion_expr(), get_rule_expr(), get_rule_expr_paren(), IsA, lappend(), lfirst, linitial, list_length(), lnext(), NIL, and deparse_context::special_exprkind.

Referenced by get_rule_expr().

9223 {
9224  StringInfo buf = context->buf;
9225  Oid funcoid = expr->funcid;
9226  Oid argtypes[FUNC_MAX_ARGS];
9227  int nargs;
9228  List *argnames;
9229  bool use_variadic;
9230  ListCell *l;
9231 
9232  /*
9233  * If the function call came from an implicit coercion, then just show the
9234  * first argument --- unless caller wants to see implicit coercions.
9235  */
9236  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9237  {
9238  get_rule_expr_paren((Node *) linitial(expr->args), context,
9239  false, (Node *) expr);
9240  return;
9241  }
9242 
9243  /*
9244  * If the function call came from a cast, then show the first argument
9245  * plus an explicit cast operation.
9246  */
9247  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9249  {
9250  Node *arg = linitial(expr->args);
9251  Oid rettype = expr->funcresulttype;
9252  int32 coercedTypmod;
9253 
9254  /* Get the typmod if this is a length-coercion function */
9255  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9256 
9257  get_coercion_expr(arg, context,
9258  rettype, coercedTypmod,
9259  (Node *) expr);
9260 
9261  return;
9262  }
9263 
9264  /*
9265  * Normal function: display as proname(args). First we need to extract
9266  * the argument datatypes.
9267  */
9268  if (list_length(expr->args) > FUNC_MAX_ARGS)
9269  ereport(ERROR,
9270  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9271  errmsg("too many arguments")));
9272  nargs = 0;
9273  argnames = NIL;
9274  foreach(l, expr->args)
9275  {
9276  Node *arg = (Node *) lfirst(l);
9277 
9278  if (IsA(arg, NamedArgExpr))
9279  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9280  argtypes[nargs] = exprType(arg);
9281  nargs++;
9282  }
9283 
9284  appendStringInfo(buf, "%s(",
9285  generate_function_name(funcoid, nargs,
9286  argnames, argtypes,
9287  expr->funcvariadic,
9288  &use_variadic,
9289  context->special_exprkind));
9290  nargs = 0;
9291  foreach(l, expr->args)
9292  {
9293  if (nargs++ > 0)
9294  appendStringInfoString(buf, ", ");
9295  if (use_variadic && lnext(expr->args, l) == NULL)
9296  appendStringInfoString(buf, "VARIADIC ");
9297  get_rule_expr((Node *) lfirst(l), context, true);
9298  }
9299  appendStringInfoChar(buf, ')');
9300 }
Oid funcresulttype
Definition: primnodes.h:470
#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:10935
#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:7879
List * args
Definition: primnodes.h:477
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:610
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:512
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:362
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:474
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:174
Oid funcid
Definition: primnodes.h:469
#define ERROR
Definition: elog.h:43
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:9506
ParseExprKind special_exprkind
Definition: ruleutils.c:120
List * lappend(List *list, void *datum)
Definition: list.c:321
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define ereport(elevel,...)
Definition: elog.h:144
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7911
#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:112
int errmsg(const char *fmt,...)
Definition: elog.c:824
void * arg
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:472

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

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

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

10543 {
10544  HeapTuple ht_opc;
10545  Form_pg_opclass opcrec;
10546  char *opcname;
10547  char *nspname;
10548 
10549  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10550  if (!HeapTupleIsValid(ht_opc))
10551  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10552  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10553 
10554  if (!OidIsValid(actual_datatype) ||
10555  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10556  {
10557  /* Okay, we need the opclass name. Do we need to qualify it? */
10558  opcname = NameStr(opcrec->opcname);
10559  if (OpclassIsVisible(opclass))
10560  appendStringInfo(buf, " %s", quote_identifier(opcname));
10561  else
10562  {
10563  nspname = get_namespace_name(opcrec->opcnamespace);
10564  appendStringInfo(buf, " %s.%s",
10565  quote_identifier(nspname),
10566  quote_identifier(opcname));
10567  }
10568  }
10569  ReleaseSysCache(ht_opc);
10570 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:2058
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
#define OidIsValid(objectId)
Definition: c.h:651
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
bool OpclassIsVisible(Oid opcid)
Definition: namespace.c:1832
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622
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 9181 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().

9182 {
9183  StringInfo buf = context->buf;
9184  Oid opno = expr->opno;
9185  List *args = expr->args;
9186 
9187  if (!PRETTY_PAREN(context))
9188  appendStringInfoChar(buf, '(');
9189  if (list_length(args) == 2)
9190  {
9191  /* binary operator */
9192  Node *arg1 = (Node *) linitial(args);
9193  Node *arg2 = (Node *) lsecond(args);
9194 
9195  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9196  appendStringInfo(buf, " %s ",
9198  exprType(arg1),
9199  exprType(arg2)));
9200  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9201  }
9202  else
9203  {
9204  /* prefix operator */
9205  Node *arg = (Node *) linitial(args);
9206 
9207  appendStringInfo(buf, "%s ",
9209  InvalidOid,
9210  exprType(arg)));
9211  get_rule_expr_paren(arg, context, true, (Node *) expr);
9212  }
9213  if (!PRETTY_PAREN(context))
9214  appendStringInfoChar(buf, ')');
9215 }
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7879
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:11040
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:99
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:112
void * arg
Oid opno
Definition: primnodes.h:516
List * args
Definition: primnodes.h:522
Definition: pg_list.h:50

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

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

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

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

4998 {
4999  deparse_context context;
5000  deparse_namespace dpns;
5001 
5002  /* Guard against excessively long or deeply-nested queries */
5005 
5006  /*
5007  * Before we begin to examine the query, acquire locks on referenced
5008  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5009  * consistent results. Note we assume it's OK to scribble on the passed
5010  * querytree!
5011  *
5012  * We are only deparsing the query (we are not about to execute it), so we
5013  * only need AccessShareLock on the relations it mentions.
5014  */
5015  AcquireRewriteLocks(query, false, false);
5016 
5017  context.buf = buf;
5018  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5019  context.windowClause = NIL;
5020  context.windowTList = NIL;
5021  context.varprefix = (parentnamespace != NIL ||
5022  list_length(query->rtable) != 1);
5023  context.prettyFlags = prettyFlags;
5024  context.wrapColumn = wrapColumn;
5025  context.indentLevel = startIndent;
5026  context.special_exprkind = EXPR_KIND_NONE;
5027  context.appendparents = NULL;
5028 
5029  set_deparse_for_query(&dpns, query, parentnamespace);
5030 
5031  switch (query->commandType)
5032  {
5033  case CMD_SELECT:
5034  get_select_query_def(query, &context, resultDesc);
5035  break;
5036 
5037  case CMD_UPDATE:
5038  get_update_query_def(query, &context);
5039  break;
5040 
5041  case CMD_INSERT:
5042  get_insert_query_def(query, &context);
5043  break;
5044 
5045  case CMD_DELETE:
5046  get_delete_query_def(query, &context);
5047  break;
5048 
5049  case CMD_NOTHING:
5050  appendStringInfoString(buf, "NOTHING");
5051  break;
5052 
5053  case CMD_UTILITY:
5054  get_utility_query_def(query, &context);
5055  break;
5056 
5057  default:
5058  elog(ERROR, "unrecognized query command type: %d",
5059  query->commandType);
5060  break;
5061  }
5062 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
List * list_copy(const List *oldlist)
Definition: list.c:1403
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6098
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6311
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
static void get_utility_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6569
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5192
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
void check_stack_depth(void)
Definition: postgres.c:3312
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
ParseExprKind special_exprkind
Definition: ruleutils.c:120
static void get_delete_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6518
List * windowTList
Definition: ruleutils.c:115
CmdType commandType
Definition: parsenodes.h:112
List * lcons(void *datum, List *list)
Definition: list.c:453
List * windowClause
Definition: ruleutils.c:114
static int list_length(const List *l)
Definition: pg_list.h:149
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3594
Bitmapset * appendparents
Definition: ruleutils.c:122
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:214
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99

◆ get_range_partbound_string()

char* get_range_partbound_string ( List bound_datums)

Definition at line 11355 of file ruleutils.c.

References appendStringInfoChar(), appendStringInfoString(), buf, deparse_context::buf, castNode, StringInfoData::data, get_const_expr(), PartitionRangeDatum::kind, lfirst, makeStringInfo(), PARTITION_RANGE_DATUM_MAXVALUE, PARTITION_RANGE_DATUM_MINVALUE, val, and PartitionRangeDatum::value.

Referenced by check_new_partition_bound(), and get_rule_expr().

11356 {
11357  deparse_context context;
11359  ListCell *cell;
11360  char *sep;
11361 
11362  memset(&context, 0, sizeof(deparse_context));
11363  context.buf = buf;
11364 
11365  appendStringInfoString(buf, "(");
11366  sep = "";
11367  foreach(cell, bound_datums)
11368  {
11369  PartitionRangeDatum *datum =
11371 
11372  appendStringInfoString(buf, sep);
11373  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
11374  appendStringInfoString(buf, "MINVALUE");
11375  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
11376  appendStringInfoString(buf, "MAXVALUE");
11377  else
11378  {
11379  Const *val = castNode(Const, datum->value);
11380 
11381  get_const_expr(val, &context, -1);
11382  }
11383  sep = ", ";
11384  }
11385  appendStringInfoChar(buf, ')');
11386 
11387  return buf->data;
11388 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
PartitionRangeDatumKind kind
Definition: parsenodes.h:848
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9570
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 lfirst(lc)
Definition: pg_list.h:169
StringInfo buf
Definition: ruleutils.c:112
long val
Definition: informix.c:664

◆ get_relation_name()

static char * get_relation_name ( Oid  relid)
static

Definition at line 10813 of file ruleutils.c.

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

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

10814 {
10815  char *relname = get_rel_name(relid);
10816 
10817  if (!relname)
10818  elog(ERROR, "cache lookup failed for relation %u", relid);
10819  return relname;
10820 }
NameData relname
Definition: pg_class.h:38
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:214
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1840

◆ get_reloptions()

static void get_reloptions ( StringInfo  buf,
Datum  reloptions 
)
static

Definition at line 11266 of file ruleutils.c.

References appendStringInfo(), appendStringInfoString(), DatumGetArrayTypeP, deconstruct_array(), i, name, noptions, options, pfree(), quote_identifier(), simple_quote_literal(), TextDatumGetCString, and value.

Referenced by flatten_reloptions(), and pg_get_indexdef_worker().

11267 {
11268  Datum *options;
11269  int noptions;
11270  int i;
11271 
11273  TEXTOID, -1, false, TYPALIGN_INT,
11274  &options, NULL, &noptions);
11275 
11276  for (i = 0; i < noptions; i++)
11277  {
11278  char *option = TextDatumGetCString(options[i]);
11279  char *name;
11280  char *separator;
11281  char *value;
11282 
11283  /*
11284  * Each array element should have the form name=value. If the "=" is
11285  * missing for some reason, treat it like an empty value.
11286  */
11287  name = option;
11288  separator = strchr(option, '=');
11289  if (separator)
11290  {
11291  *separator = '\0';
11292  value = separator + 1;
11293  }
11294  else
11295  value = "";
11296 
11297  if (i > 0)
11298  appendStringInfoString(buf, ", ");
11299  appendStringInfo(buf, "%s=", quote_identifier(name));
11300 
11301  /*
11302  * In general we need to quote the value; but to avoid unnecessary
11303  * clutter, do not quote if it is an identifier that would not need
11304  * quoting. (We could also allow numbers, but that is a bit trickier
11305  * than it looks --- for example, are leading zeroes significant? We
11306  * don't want to assume very much here about what custom reloptions
11307  * might mean.)
11308  */
11309  if (quote_identifier(value) == value)
11310  appendStringInfoString(buf, value);
11311  else
11312  simple_quote_literal(buf, value);
11313 
11314  pfree(option);
11315  }
11316 }
static struct @142 value
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
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:9720
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char ** options
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
const char * name
Definition: encode.c:561
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3483
int i
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ get_rtable_name()

static char * get_rtable_name ( int  rtindex,
deparse_context context 
)
static

Definition at line 4548 of file ruleutils.c.

References Assert, linitial, list_length(), list_nth(), deparse_context::namespaces, and deparse_namespace::rtable_names.

Referenced by get_from_clause_item(), and get_select_query_def().

4549 {
4551 
4552  Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names));
4553  return (char *) list_nth(dpns->rtable_names, rtindex - 1);
4554 }