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 void flatten_join_using_qual (Node *qual, List **leftvars, List **rightvars)
 
static char * get_rtable_name (int rtindex, deparse_context *context)
 
static void set_deparse_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)
 
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)
 
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 301 of file ruleutils.c.

Function Documentation

◆ add_cast_to()

static void add_cast_to ( StringInfo  buf,
Oid  typid 
)
static

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

11225 {
11226  HeapTuple typetup;
11227  Form_pg_type typform;
11228  char *typname;
11229  char *nspname;
11230 
11231  typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
11232  if (!HeapTupleIsValid(typetup))
11233  elog(ERROR, "cache lookup failed for type %u", typid);
11234  typform = (Form_pg_type) GETSTRUCT(typetup);
11235 
11236  typname = NameStr(typform->typname);
11237  nspname = get_namespace_name(typform->typnamespace);
11238 
11239  appendStringInfo(buf, "::%s.%s",
11240  quote_identifier(nspname), quote_identifier(typname));
11241 
11242  ReleaseSysCache(typetup);
11243 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
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:3094
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:250
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616

◆ appendContextKeyword()

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

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

7870 {
7871  StringInfo buf = context->buf;
7872 
7873  if (PRETTY_INDENT(context))
7874  {
7875  int indentAmount;
7876 
7877  context->indentLevel += indentBefore;
7878 
7879  /* remove any trailing spaces currently in the buffer ... */
7881  /* ... then add a newline and some spaces */
7882  appendStringInfoChar(buf, '\n');
7883 
7884  if (context->indentLevel < PRETTYINDENT_LIMIT)
7885  indentAmount = Max(context->indentLevel, 0) + indentPlus;
7886  else
7887  {
7888  /*
7889  * If we're indented more than PRETTYINDENT_LIMIT characters, try
7890  * to conserve horizontal space by reducing the per-level
7891  * indentation. For best results the scale factor here should
7892  * divide all the indent amounts that get added to indentLevel
7893  * (PRETTYINDENT_STD, etc). It's important that the indentation
7894  * not grow unboundedly, else deeply-nested trees use O(N^2)
7895  * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT.
7896  */
7897  indentAmount = PRETTYINDENT_LIMIT +
7898  (context->indentLevel - PRETTYINDENT_LIMIT) /
7899  (PRETTYINDENT_STD / 2);
7900  indentAmount %= PRETTYINDENT_LIMIT;
7901  /* scale/wrap logic affects indentLevel, but not indentPlus */
7902  indentAmount += indentPlus;
7903  }
7904  appendStringInfoSpaces(buf, indentAmount);
7905 
7907 
7908  context->indentLevel += indentAfter;
7909  if (context->indentLevel < 0)
7910  context->indentLevel = 0;
7911  }
7912  else
7914 }
#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:67
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7922
#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:905
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 4356 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().

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

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

Referenced by pg_get_constraintdef_worker().

2332 {
2333  Datum *keys;
2334  int nKeys;
2335  int j;
2336 
2337  /* Extract data from array of int16 */
2338  deconstruct_array(DatumGetArrayTypeP(column_index_array),
2339  INT2OID, 2, true, 's',
2340  &keys, NULL, &nKeys);
2341 
2342  for (j = 0; j < nKeys; j++)
2343  {
2344  char *colName;
2345 
2346  colName = get_attname(relId, DatumGetInt16(keys[j]), false);
2347 
2348  if (j == 0)
2350  else
2351  appendStringInfo(buf, ", %s", quote_identifier(colName));
2352  }
2353 
2354  return nKeys;
2355 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
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:3461
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ deparse_context_for()

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

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

3274 {
3275  deparse_namespace *dpns;
3276  RangeTblEntry *rte;
3277 
3278  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3279 
3280  /* Build a minimal RTE for the rel */
3281  rte = makeNode(RangeTblEntry);
3282  rte->rtekind = RTE_RELATION;
3283  rte->relid = relid;
3284  rte->relkind = RELKIND_RELATION; /* no need for exactness here */
3286  rte->alias = makeAlias(aliasname, NIL);
3287  rte->eref = rte->alias;
3288  rte->lateral = false;
3289  rte->inh = false;
3290  rte->inFromCl = true;
3291 
3292  /* Build one-element rtable */
3293  dpns->rtable = list_make1(rte);
3294  dpns->subplans = NIL;
3295  dpns->ctes = NIL;
3296  dpns->appendrels = NULL;
3297  set_rtable_names(dpns, NIL, NULL);
3299 
3300  /* Return a one-deep namespace stack */
3301  return list_make1(dpns);
3302 }
#define NIL
Definition: pg_list.h:65
Alias * alias
Definition: parsenodes.h:1091
#define AccessShareLock
Definition: lockdefs.h:36
AppendRelInfo ** appendrels
Definition: ruleutils.c:165
#define list_make1(x1)
Definition: pg_list.h:227
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:385
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used)
Definition: ruleutils.c:3439
void * palloc0(Size size)
Definition: mcxt.c:980
#define makeNode(_type_)
Definition: nodes.h:573
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3654
RTEKind rtekind
Definition: parsenodes.h:974
Alias * eref
Definition: parsenodes.h:1092

◆ deparse_context_for_plan_tree()

List* deparse_context_for_plan_tree ( PlannedStmt pstmt,
List rtable_names 
)

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

3319 {
3320  deparse_namespace *dpns;
3321 
3322  dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
3323 
3324  /* Initialize fields that stay the same across the whole plan tree */
3325  dpns->rtable = pstmt->rtable;
3326  dpns->rtable_names = rtable_names;
3327  dpns->subplans = pstmt->subplans;
3328  dpns->ctes = NIL;
3329  if (pstmt->appendRelations)
3330  {
3331  /* Set up the array, indexed by child relid */
3332  int ntables = list_length(dpns->rtable);
3333  ListCell *lc;
3334 
3335  dpns->appendrels = (AppendRelInfo **)
3336  palloc0((ntables + 1) * sizeof(AppendRelInfo *));
3337  foreach(lc, pstmt->appendRelations)
3338  {
3339  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
3340  Index crelid = appinfo->child_relid;
3341 
3342  Assert(crelid > 0 && crelid <= ntables);
3343  Assert(dpns->appendrels[crelid] == NULL);
3344  dpns->appendrels[crelid] = appinfo;
3345  }
3346  }
3347  else
3348  dpns->appendrels = NULL; /* don't need it */
3349 
3350  /*
3351  * Set up column name aliases. We will get rather bogus results for join
3352  * RTEs, but that doesn't matter because plan trees don't contain any join
3353  * alias Vars.
3354  */
3356 
3357  /* Return a one-deep namespace stack */
3358  return list_make1(dpns);
3359 }
#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:227
#define lfirst_node(type, lc)
Definition: pg_list.h:193
void * palloc0(Size size)
Definition: mcxt.c:980
unsigned int Index
Definition: c.h:476
List * subplans
Definition: plannodes.h:79
#define Assert(condition)
Definition: c.h:739
static int list_length(const List *l)
Definition: pg_list.h:169
List * rtable
Definition: plannodes.h:66
static void set_simple_column_names(deparse_namespace *dpns)
Definition: ruleutils.c:3654
Index child_relid
Definition: pathnodes.h:2190
List * appendRelations
Definition: plannodes.h:77

◆ deparse_expression()

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

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

3215 {
3216  return deparse_expression_pretty(expr, dpcontext, forceprefix,
3217  showimplicit, 0, 0);
3218 }
static char * deparse_expression_pretty(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit, int prettyFlags, int startIndent)
Definition: ruleutils.c:3240

◆ deparse_expression_pretty()

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

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

3243 {
3245  deparse_context context;
3246 
3247  initStringInfo(&buf);
3248  context.buf = &buf;
3249  context.namespaces = dpcontext;
3250  context.windowClause = NIL;
3251  context.windowTList = NIL;
3252  context.varprefix = forceprefix;
3253  context.prettyFlags = prettyFlags;
3254  context.wrapColumn = WRAP_COLUMN_DEFAULT;
3255  context.indentLevel = startIndent;
3256  context.special_exprkind = EXPR_KIND_NONE;
3257  context.appendparents = NULL;
3258 
3259  get_rule_expr(expr, &context, showimplicit);
3260 
3261  return buf.data;
3262 }
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:67
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:7973
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 4454 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().

4455 {
4456  if (n > colinfo->num_cols)
4457  {
4458  if (colinfo->colnames == NULL)
4459  colinfo->colnames = (char **) palloc0(n * sizeof(char *));
4460  else
4461  {
4462  colinfo->colnames = (char **) repalloc(colinfo->colnames,
4463  n * sizeof(char *));
4464  memset(colinfo->colnames + colinfo->num_cols, 0,
4465  (n - colinfo->num_cols) * sizeof(char *));
4466  }
4467  colinfo->num_cols = n;
4468  }
4469 }
void * palloc0(Size size)
Definition: mcxt.c:980
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
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 7427 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().

7429 {
7430  /* Initialize output parameters to prevent compiler warnings */
7431  *dpns_p = NULL;
7432  *ancestor_cell_p = NULL;
7433 
7434  /*
7435  * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
7436  * SubPlan argument. This will necessarily be in some ancestor of the
7437  * current expression's Plan node.
7438  */
7439  if (param->paramkind == PARAM_EXEC)
7440  {
7441  deparse_namespace *dpns;
7442  Plan *child_plan;
7443  bool in_same_plan_level;
7444  ListCell *lc;
7445 
7446  dpns = (deparse_namespace *) linitial(context->namespaces);
7447  child_plan = dpns->plan;
7448  in_same_plan_level = true;
7449 
7450  foreach(lc, dpns->ancestors)
7451  {
7452  Node *ancestor = (Node *) lfirst(lc);
7453  ListCell *lc2;
7454 
7455  /*
7456  * NestLoops transmit params to their inner child only; also, once
7457  * we've crawled up out of a subplan, this couldn't possibly be
7458  * the right match.
7459  */
7460  if (IsA(ancestor, NestLoop) &&
7461  child_plan == innerPlan(ancestor) &&
7462  in_same_plan_level)
7463  {
7464  NestLoop *nl = (NestLoop *) ancestor;
7465 
7466  foreach(lc2, nl->nestParams)
7467  {
7468  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
7469 
7470  if (nlp->paramno == param->paramid)
7471  {
7472  /* Found a match, so return it */
7473  *dpns_p = dpns;
7474  *ancestor_cell_p = lc;
7475  return (Node *) nlp->paramval;
7476  }
7477  }
7478  }
7479 
7480  /*
7481  * If ancestor is a SubPlan, check the arguments it provides.
7482  */
7483  if (IsA(ancestor, SubPlan))
7484  {
7485  SubPlan *subplan = (SubPlan *) ancestor;
7486  ListCell *lc3;
7487  ListCell *lc4;
7488 
7489  forboth(lc3, subplan->parParam, lc4, subplan->args)
7490  {
7491  int paramid = lfirst_int(lc3);
7492  Node *arg = (Node *) lfirst(lc4);
7493 
7494  if (paramid == param->paramid)
7495  {
7496  /*
7497  * Found a match, so return it. But, since Vars in
7498  * the arg are to be evaluated in the surrounding
7499  * context, we have to point to the next ancestor item
7500  * that is *not* a SubPlan.
7501  */
7502  ListCell *rest;
7503 
7504  for_each_cell(rest, dpns->ancestors,
7505  lnext(dpns->ancestors, lc))
7506  {
7507  Node *ancestor2 = (Node *) lfirst(rest);
7508 
7509  if (!IsA(ancestor2, SubPlan))
7510  {
7511  *dpns_p = dpns;
7512  *ancestor_cell_p = rest;
7513  return arg;
7514  }
7515  }
7516  elog(ERROR, "SubPlan cannot be outermost ancestor");
7517  }
7518  }
7519 
7520  /* We have emerged from a subplan. */
7521  in_same_plan_level = false;
7522 
7523  /* SubPlan isn't a kind of Plan, so skip the rest */
7524  continue;
7525  }
7526 
7527  /*
7528  * Check to see if we're emerging from an initplan of the current
7529  * ancestor plan. Initplans never have any parParams, so no need
7530  * to search that list, but we need to know if we should reset
7531  * in_same_plan_level.
7532  */
7533  foreach(lc2, ((Plan *) ancestor)->initPlan)
7534  {
7535  SubPlan *subplan = castNode(SubPlan, lfirst(lc2));
7536 
7537  if (child_plan != (Plan *) list_nth(dpns->subplans,
7538  subplan->plan_id - 1))
7539  continue;
7540 
7541  /* No parameters to be had here. */
7542  Assert(subplan->parParam == NIL);
7543 
7544  /* We have emerged from an initplan. */
7545  in_same_plan_level = false;
7546  break;
7547  }
7548 
7549  /* No luck, crawl up to next ancestor */
7550  child_plan = (Plan *) ancestor;
7551  }
7552  }
7553 
7554  /* No referent found */
7555  return NULL;
7556 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
int plan_id
Definition: primnodes.h:695
List * nestParams
Definition: plannodes.h:703
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:390
ParamKind paramkind
Definition: primnodes.h:248
Definition: nodes.h:525
Var * paramval
Definition: plannodes.h:710
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
#define innerPlan(node)
Definition: plannodes.h:171
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
int paramid
Definition: primnodes.h:249
List * parParam
Definition: primnodes.h:715
#define elog(elevel,...)
Definition: elog.h:228
void * arg
List * args
Definition: primnodes.h:716

◆ flatten_join_using_qual()

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

Definition at line 4605 of file ruleutils.c.

References AND_EXPR, OpExpr::args, BoolExpr::args, Assert, BoolExpr::boolop, elog, ERROR, IsA, lappend(), lfirst, linitial, list_length(), lsecond, nodeTag, and strip_implicit_coercions().

Referenced by identify_join_columns().

4606 {
4607  if (IsA(qual, BoolExpr))
4608  {
4609  /* Handle AND nodes by recursion */
4610  BoolExpr *b = (BoolExpr *) qual;
4611  ListCell *lc;
4612 
4613  Assert(b->boolop == AND_EXPR);
4614  foreach(lc, b->args)
4615  {
4617  leftvars, rightvars);
4618  }
4619  }
4620  else if (IsA(qual, OpExpr))
4621  {
4622  /* Otherwise we should have an equality operator */
4623  OpExpr *op = (OpExpr *) qual;
4624  Var *var;
4625 
4626  if (list_length(op->args) != 2)
4627  elog(ERROR, "unexpected unary operator in JOIN/USING qual");
4628  /* Arguments should be Vars with perhaps implicit coercions */
4629  var = (Var *) strip_implicit_coercions((Node *) linitial(op->args));
4630  if (!IsA(var, Var))
4631  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4632  (int) nodeTag(var));
4633  *leftvars = lappend(*leftvars, var);
4634  var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args));
4635  if (!IsA(var, Var))
4636  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4637  (int) nodeTag(var));
4638  *rightvars = lappend(*rightvars, var);
4639  }
4640  else
4641  {
4642  /* Perhaps we have an implicit coercion to boolean? */
4643  Node *q = strip_implicit_coercions(qual);
4644 
4645  if (q != qual)
4646  flatten_join_using_qual(q, leftvars, rightvars);
4647  else
4648  elog(ERROR, "unexpected node type in JOIN/USING qual: %d",
4649  (int) nodeTag(qual));
4650  }
4651 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Definition: nodes.h:525
Definition: primnodes.h:167
#define lsecond(l)
Definition: pg_list.h:200
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:568
List * lappend(List *list, void *datum)
Definition: list.c:322
static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars)
Definition: ruleutils.c:4605
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
List * args
Definition: primnodes.h:569
#define nodeTag(nodeptr)
Definition: nodes.h:530
#define elog(elevel,...)
Definition: elog.h:228
List * args
Definition: primnodes.h:508
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:611

◆ flatten_reloptions()

static char * flatten_reloptions ( Oid  relid)
static

Definition at line 11333 of file ruleutils.c.

References appendStringInfo(), appendStringInfoString(), buf, StringInfoData::data, DatumGetArrayTypeP, deconstruct_array(), elog, ERROR, HeapTupleIsValid, i, initStringInfo(), name, noptions, ObjectIdGetDatum, options, pfree(), quote_identifier(), ReleaseSysCache(), RELOID, SearchSysCache1(), simple_quote_literal(), SysCacheGetAttr(), TextDatumGetCString, and value.

Referenced by pg_get_constraintdef_worker(), and pg_get_indexdef_worker().

11334 {
11335  char *result = NULL;
11336  HeapTuple tuple;
11337  Datum reloptions;
11338  bool isnull;
11339 
11340  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11341  if (!HeapTupleIsValid(tuple))
11342  elog(ERROR, "cache lookup failed for relation %u", relid);
11343 
11344  reloptions = SysCacheGetAttr(RELOID, tuple,
11345  Anum_pg_class_reloptions, &isnull);
11346  if (!isnull)
11347  {
11349  Datum *options;
11350  int noptions;
11351  int i;
11352 
11353  initStringInfo(&buf);
11354 
11356  TEXTOID, -1, false, 'i',
11357  &options, NULL, &noptions);
11358 
11359  for (i = 0; i < noptions; i++)
11360  {
11361  char *option = TextDatumGetCString(options[i]);
11362  char *name;
11363  char *separator;
11364  char *value;
11365 
11366  /*
11367  * Each array element should have the form name=value. If the "="
11368  * is missing for some reason, treat it like an empty value.
11369  */
11370  name = option;
11371  separator = strchr(option, '=');
11372  if (separator)
11373  {
11374  *separator = '\0';
11375  value = separator + 1;
11376  }
11377  else
11378  value = "";
11379 
11380  if (i > 0)
11381  appendStringInfoString(&buf, ", ");
11382  appendStringInfo(&buf, "%s=", quote_identifier(name));
11383 
11384  /*
11385  * In general we need to quote the value; but to avoid unnecessary
11386  * clutter, do not quote if it is an identifier that would not
11387  * need quoting. (We could also allow numbers, but that is a bit
11388  * trickier than it looks --- for example, are leading zeroes
11389  * significant? We don't want to assume very much here about what
11390  * custom reloptions might mean.)
11391  */
11392  if (quote_identifier(value) == value)
11393  appendStringInfoString(&buf, value);
11394  else
11395  simple_quote_literal(&buf, value);
11396 
11397  pfree(option);
11398  }
11399 
11400  result = buf.data;
11401  }
11402 
11403  ReleaseSysCache(tuple);
11404 
11405  return result;
11406 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
static struct @145 value
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9800
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
static char ** options
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
#define TextDatumGetCString(d)
Definition: builtins.h:84
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
const char * name
Definition: encode.c:521
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
#define elog(elevel,...)
Definition: elog.h:228
int i
static size_t noptions
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ generate_collation_name()

char* generate_collation_name ( Oid  collid)

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

11289 {
11290  HeapTuple tp;
11291  Form_pg_collation colltup;
11292  char *collname;
11293  char *nspname;
11294  char *result;
11295 
11296  tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
11297  if (!HeapTupleIsValid(tp))
11298  elog(ERROR, "cache lookup failed for collation %u", collid);
11299  colltup = (Form_pg_collation) GETSTRUCT(tp);
11300  collname = NameStr(colltup->collname);
11301 
11302  if (!CollationIsVisible(collid))
11303  nspname = get_namespace_name(colltup->collnamespace);
11304  else
11305  nspname = NULL;
11306 
11307  result = quote_qualified_identifier(nspname, collname);
11308 
11309  ReleaseSysCache(tp);
11310 
11311  return result;
11312 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
bool CollationIsVisible(Oid collid)
Definition: namespace.c:2040
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10856
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:228
#define NameStr(name)
Definition: c.h:616

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

11001 {
11002  char *result;
11003  HeapTuple proctup;
11004  Form_pg_proc procform;
11005  char *proname;
11006  bool use_variadic;
11007  char *nspname;
11008  FuncDetailCode p_result;
11009  Oid p_funcid;
11010  Oid p_rettype;
11011  bool p_retset;
11012  int p_nvargs;
11013  Oid p_vatype;
11014  Oid *p_true_typeids;
11015  bool force_qualify = false;
11016 
11017  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
11018  if (!HeapTupleIsValid(proctup))
11019  elog(ERROR, "cache lookup failed for function %u", funcid);
11020  procform = (Form_pg_proc) GETSTRUCT(proctup);
11021  proname = NameStr(procform->proname);
11022 
11023  /*
11024  * Due to parser hacks to avoid needing to reserve CUBE, we need to force
11025  * qualification in some special cases.
11026  */
11027  if (special_exprkind == EXPR_KIND_GROUP_BY)
11028  {
11029  if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0)
11030  force_qualify = true;
11031  }
11032 
11033  /*
11034  * Determine whether VARIADIC should be printed. We must do this first
11035  * since it affects the lookup rules in func_get_detail().
11036  *
11037  * We always print VARIADIC if the function has a merged variadic-array
11038  * argument. Note that this is always the case for functions taking a
11039  * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
11040  * and printed the array elements as separate arguments, the call could
11041  * match a newer non-VARIADIC function.
11042  */
11043  if (use_variadic_p)
11044  {
11045  /* Parser should not have set funcvariadic unless fn is variadic */
11046  Assert(!has_variadic || OidIsValid(procform->provariadic));
11047  use_variadic = has_variadic;
11048  *use_variadic_p = use_variadic;
11049  }
11050  else
11051  {
11052  Assert(!has_variadic);
11053  use_variadic = false;
11054  }
11055 
11056  /*
11057  * The idea here is to schema-qualify only if the parser would fail to
11058  * resolve the correct function given the unqualified func name with the
11059  * specified argtypes and VARIADIC flag. But if we already decided to
11060  * force qualification, then we can skip the lookup and pretend we didn't
11061  * find it.
11062  */
11063  if (!force_qualify)
11064  p_result = func_get_detail(list_make1(makeString(proname)),
11065  NIL, argnames, nargs, argtypes,
11066  !use_variadic, true,
11067  &p_funcid, &p_rettype,
11068  &p_retset, &p_nvargs, &p_vatype,
11069  &p_true_typeids, NULL);
11070  else
11071  {
11072  p_result = FUNCDETAIL_NOTFOUND;
11073  p_funcid = InvalidOid;
11074  }
11075 
11076  if ((p_result == FUNCDETAIL_NORMAL ||
11077  p_result == FUNCDETAIL_AGGREGATE ||
11078  p_result == FUNCDETAIL_WINDOWFUNC) &&
11079  p_funcid == funcid)
11080  nspname = NULL;
11081  else
11082  nspname = get_namespace_name(procform->pronamespace);
11083 
11084  result = quote_qualified_identifier(nspname, proname);
11085 
11086  ReleaseSysCache(proctup);
11087 
11088  return result;
11089 }
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:645
#define list_make1(x1)
Definition: pg_list.h:227
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
FuncDetailCode
Definition: parse_func.h:22
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10856
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:739
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:228
#define NameStr(name)
Definition: c.h:616

◆ generate_operator_clause()

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

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

11188 {
11189  HeapTuple opertup;
11190  Form_pg_operator operform;
11191  char *oprname;
11192  char *nspname;
11193 
11194  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid));
11195  if (!HeapTupleIsValid(opertup))
11196  elog(ERROR, "cache lookup failed for operator %u", opoid);
11197  operform = (Form_pg_operator) GETSTRUCT(opertup);
11198  Assert(operform->oprkind == 'b');
11199  oprname = NameStr(operform->oprname);
11200 
11201  nspname = get_namespace_name(operform->oprnamespace);
11202 
11203  appendStringInfoString(buf, leftop);
11204  if (leftoptype != operform->oprleft)
11205  add_cast_to(buf, operform->oprleft);
11206  appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
11207  appendStringInfoString(buf, oprname);
11208  appendStringInfo(buf, ") %s", rightop);
11209  if (rightoptype != operform->oprright)
11210  add_cast_to(buf, operform->oprright);
11211 
11212  ReleaseSysCache(opertup);
11213 }
static void add_cast_to(StringInfo buf, Oid typid)
Definition: ruleutils.c:11224
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
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:3094
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:739
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616

◆ generate_operator_name()

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

Definition at line 11103 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, StringInfoData::data, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, initStringInfo(), left_oper(), list_make1, makeString(), NameStr, ObjectIdGetDatum, oper(), OPEROID, oprid(), quote_identifier(), ReleaseSysCache(), right_oper(), and SearchSysCache1().

Referenced by get_oper_expr(), get_rule_expr(), get_rule_orderby(), get_simple_binary_op_name(), get_sublink_expr(), and pg_get_indexdef_worker().

11104 {
11106  HeapTuple opertup;
11107  Form_pg_operator operform;
11108  char *oprname;
11109  char *nspname;
11110  Operator p_result;
11111 
11112  initStringInfo(&buf);
11113 
11114  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
11115  if (!HeapTupleIsValid(opertup))
11116  elog(ERROR, "cache lookup failed for operator %u", operid);
11117  operform = (Form_pg_operator) GETSTRUCT(opertup);
11118  oprname = NameStr(operform->oprname);
11119 
11120  /*
11121  * The idea here is to schema-qualify only if the parser would fail to
11122  * resolve the correct operator given the unqualified op name with the
11123  * specified argtypes.
11124  */
11125  switch (operform->oprkind)
11126  {
11127  case 'b':
11128  p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
11129  true, -1);
11130  break;
11131  case 'l':
11132  p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
11133  true, -1);
11134  break;
11135  case 'r':
11136  p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
11137  true, -1);
11138  break;
11139  default:
11140  elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
11141  p_result = NULL; /* keep compiler quiet */
11142  break;
11143  }
11144 
11145  if (p_result != NULL && oprid(p_result) == operid)
11146  nspname = NULL;
11147  else
11148  {
11149  nspname = get_namespace_name(operform->oprnamespace);
11150  appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
11151  }
11152 
11153  appendStringInfoString(&buf, oprname);
11154 
11155  if (nspname)
11156  appendStringInfoChar(&buf, ')');
11157 
11158  if (p_result != NULL)
11159  ReleaseSysCache(p_result);
11160 
11161  ReleaseSysCache(opertup);
11162 
11163  return buf.data;
11164 }
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:10772
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define list_make1(x1)
Definition: pg_list.h:227
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c: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:604
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:525
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
static char * buf
Definition: pg_test_fsync.c:67
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:228
#define NameStr(name)
Definition: c.h:616
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377

◆ generate_qualified_relation_name()

static char * generate_qualified_relation_name ( Oid  relid)
static

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

10957 {
10958  HeapTuple tp;
10959  Form_pg_class reltup;
10960  char *relname;
10961  char *nspname;
10962  char *result;
10963 
10964  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10965  if (!HeapTupleIsValid(tp))
10966  elog(ERROR, "cache lookup failed for relation %u", relid);
10967  reltup = (Form_pg_class) GETSTRUCT(tp);
10968  relname = NameStr(reltup->relname);
10969 
10970  nspname = get_namespace_name(reltup->relnamespace);
10971  if (!nspname)
10972  elog(ERROR, "cache lookup failed for namespace %u",
10973  reltup->relnamespace);
10974 
10975  result = quote_qualified_identifier(nspname, relname);
10976 
10977  ReleaseSysCache(tp);
10978 
10979  return result;
10980 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10856
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:150
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616

◆ generate_qualified_type_name()

static char * generate_qualified_type_name ( Oid  typid)
static

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

11256 {
11257  HeapTuple tp;
11258  Form_pg_type typtup;
11259  char *typname;
11260  char *nspname;
11261  char *result;
11262 
11264  if (!HeapTupleIsValid(tp))
11265  elog(ERROR, "cache lookup failed for type %u", typid);
11266  typtup = (Form_pg_type) GETSTRUCT(tp);
11267  typname = NameStr(typtup->typname);
11268 
11269  nspname = get_namespace_name(typtup->typnamespace);
11270  if (!nspname)
11271  elog(ERROR, "cache lookup failed for namespace %u",
11272  typtup->typnamespace);
11273 
11274  result = quote_qualified_identifier(nspname, typname);
11275 
11276  ReleaseSysCache(tp);
11277 
11278  return result;
11279 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
NameData typname
Definition: pg_type.h:41
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10856
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:250
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616

◆ generate_relation_name()

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

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

10897 {
10898  HeapTuple tp;
10899  Form_pg_class reltup;
10900  bool need_qual;
10901  ListCell *nslist;
10902  char *relname;
10903  char *nspname;
10904  char *result;
10905 
10906  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10907  if (!HeapTupleIsValid(tp))
10908  elog(ERROR, "cache lookup failed for relation %u", relid);
10909  reltup = (Form_pg_class) GETSTRUCT(tp);
10910  relname = NameStr(reltup->relname);
10911 
10912  /* Check for conflicting CTE name */
10913  need_qual = false;
10914  foreach(nslist, namespaces)
10915  {
10916  deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
10917  ListCell *ctlist;
10918 
10919  foreach(ctlist, dpns->ctes)
10920  {
10921  CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
10922 
10923  if (strcmp(cte->ctename, relname) == 0)
10924  {
10925  need_qual = true;
10926  break;
10927  }
10928  }
10929  if (need_qual)
10930  break;
10931  }
10932 
10933  /* Otherwise, qualify the name if not visible in search path */
10934  if (!need_qual)
10935  need_qual = !RelationIsVisible(relid);
10936 
10937  if (need_qual)
10938  nspname = get_namespace_name(reltup->relnamespace);
10939  else
10940  nspname = NULL;
10941 
10942  result = quote_qualified_identifier(nspname, relname);
10943 
10944  ReleaseSysCache(tp);
10945 
10946  return result;
10947 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
NameData relname
Definition: pg_class.h:35
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10856
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:190
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
bool RelationIsVisible(Oid relid)
Definition: namespace.c:700
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616

◆ get_agg_combine_expr()

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

Definition at line 9493 of file ruleutils.c.

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

Referenced by get_agg_expr().

9494 {
9495  Aggref *aggref;
9496  Aggref *original_aggref = callback_arg;
9497 
9498  if (!IsA(node, Aggref))
9499  elog(ERROR, "combining Aggref does not point to an Aggref");
9500 
9501  aggref = (Aggref *) node;
9502  get_agg_expr(aggref, context, original_aggref);
9503 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
#define ERROR
Definition: elog.h:43
static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
Definition: ruleutils.c:9386
#define elog(elevel,...)
Definition: elog.h:228

◆ get_agg_expr()

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

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

9388 {
9389  StringInfo buf = context->buf;
9390  Oid argtypes[FUNC_MAX_ARGS];
9391  int nargs;
9392  bool use_variadic;
9393 
9394  /*
9395  * For a combining aggregate, we look up and deparse the corresponding
9396  * partial aggregate instead. This is necessary because our input
9397  * argument list has been replaced; the new argument list always has just
9398  * one element, which will point to a partial Aggref that supplies us with
9399  * transition states to combine.
9400  */
9401  if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
9402  {
9403  TargetEntry *tle;
9404 
9405  Assert(list_length(aggref->args) == 1);
9406  tle = linitial_node(TargetEntry, aggref->args);
9407  resolve_special_varno((Node *) tle->expr, context,
9408  get_agg_combine_expr, original_aggref);
9409  return;
9410  }
9411 
9412  /*
9413  * Mark as PARTIAL, if appropriate. We look to the original aggref so as
9414  * to avoid printing this when recursing from the code just above.
9415  */
9416  if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
9417  appendStringInfoString(buf, "PARTIAL ");
9418 
9419  /* Extract the argument types as seen by the parser */
9420  nargs = get_aggregate_argtypes(aggref, argtypes);
9421 
9422  /* Print the aggregate name, schema-qualified if needed */
9423  appendStringInfo(buf, "%s(%s",
9424  generate_function_name(aggref->aggfnoid, nargs,
9425  NIL, argtypes,
9426  aggref->aggvariadic,
9427  &use_variadic,
9428  context->special_exprkind),
9429  (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
9430 
9431  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
9432  {
9433  /*
9434  * Ordered-set aggregates do not use "*" syntax. Also, we needn't
9435  * worry about inserting VARIADIC. So we can just dump the direct
9436  * args as-is.
9437  */
9438  Assert(!aggref->aggvariadic);
9439  get_rule_expr((Node *) aggref->aggdirectargs, context, true);
9440  Assert(aggref->aggorder != NIL);
9441  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
9442  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9443  }
9444  else
9445  {
9446  /* aggstar can be set only in zero-argument aggregates */
9447  if (aggref->aggstar)
9448  appendStringInfoChar(buf, '*');
9449  else
9450  {
9451  ListCell *l;
9452  int i;
9453 
9454  i = 0;
9455  foreach(l, aggref->args)
9456  {
9457  TargetEntry *tle = (TargetEntry *) lfirst(l);
9458  Node *arg = (Node *) tle->expr;
9459 
9460  Assert(!IsA(arg, NamedArgExpr));
9461  if (tle->resjunk)
9462  continue;
9463  if (i++ > 0)
9464  appendStringInfoString(buf, ", ");
9465  if (use_variadic && i == nargs)
9466  appendStringInfoString(buf, "VARIADIC ");
9467  get_rule_expr(arg, context, true);
9468  }
9469  }
9470 
9471  if (aggref->aggorder != NIL)
9472  {
9473  appendStringInfoString(buf, " ORDER BY ");
9474  get_rule_orderby(aggref->aggorder, aggref->args, false, context);
9475  }
9476  }
9477 
9478  if (aggref->aggfilter != NULL)
9479  {
9480  appendStringInfoString(buf, ") FILTER (WHERE ");
9481  get_rule_expr((Node *) aggref->aggfilter, context, false);
9482  }
9483 
9484  appendStringInfoChar(buf, ')');
9485 }
static void resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
Definition: ruleutils.c:6943
List * aggdistinct
Definition: primnodes.h:307
#define NIL
Definition: pg_list.h:65
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10998
bool aggvariadic
Definition: primnodes.h:310
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5997
Definition: nodes.h:525
List * args
Definition: primnodes.h:305
bool aggstar
Definition: primnodes.h:309
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:198
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:787
#define FUNC_MAX_ARGS
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1400
static void get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
Definition: ruleutils.c:9493
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
List * aggorder
Definition: primnodes.h:306
List * aggdirectargs
Definition: primnodes.h:304
ParseExprKind special_exprkind
Definition: ruleutils.c:120
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
Oid aggfnoid
Definition: primnodes.h:298
#define Assert(condition)
Definition: c.h:739
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7973
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
AggSplit aggsplit
Definition: primnodes.h:314
static int list_length(const List *l)
Definition: pg_list.h:169
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:788
Expr * aggfilter
Definition: primnodes.h:308
StringInfo buf
Definition: ruleutils.c:112
int i
void * arg
char aggkind
Definition: primnodes.h:312
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1819

◆ get_basic_select_query()

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

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

5492 {
5493  StringInfo buf = context->buf;
5494  RangeTblEntry *values_rte;
5495  char *sep;
5496  ListCell *l;
5497 
5498  if (PRETTY_INDENT(context))
5499  {
5500  context->indentLevel += PRETTYINDENT_STD;
5501  appendStringInfoChar(buf, ' ');
5502  }
5503 
5504  /*
5505  * If the query looks like SELECT * FROM (VALUES ...), then print just the
5506  * VALUES part. This reverses what transformValuesClause() did at parse
5507  * time.
5508  */
5509  values_rte = get_simple_values_rte(query, resultDesc);
5510  if (values_rte)
5511  {
5512  get_values_def(values_rte->values_lists, context);
5513  return;
5514  }
5515 
5516  /*
5517  * Build up the query string - first we say SELECT
5518  */
5519  appendStringInfoString(buf, "SELECT");
5520 
5521  /* Add the DISTINCT clause if given */
5522  if (query->distinctClause != NIL)
5523  {
5524  if (query->hasDistinctOn)
5525  {
5526  appendStringInfoString(buf, " DISTINCT ON (");
5527  sep = "";
5528  foreach(l, query->distinctClause)
5529  {
5530  SortGroupClause *srt = (SortGroupClause *) lfirst(l);
5531 
5532  appendStringInfoString(buf, sep);
5534  false, context);
5535  sep = ", ";
5536  }
5537  appendStringInfoChar(buf, ')');
5538  }
5539  else
5540  appendStringInfoString(buf, " DISTINCT");
5541  }
5542 
5543  /* Then we tell what to select (the targetlist) */
5544  get_target_list(query->targetList, context, resultDesc);
5545 
5546  /* Add the FROM clause if needed */
5547  get_from_clause(query, " FROM ", context);
5548 
5549  /* Add the WHERE clause if given */
5550  if (query->jointree->quals != NULL)
5551  {
5552  appendContextKeyword(context, " WHERE ",
5554  get_rule_expr(query->jointree->quals, context, false);
5555  }
5556 
5557  /* Add the GROUP BY clause if given */
5558  if (query->groupClause != NULL || query->groupingSets != NULL)
5559  {
5560  ParseExprKind save_exprkind;
5561 
5562  appendContextKeyword(context, " GROUP BY ",
5564 
5565  save_exprkind = context->special_exprkind;
5567 
5568  if (query->groupingSets == NIL)
5569  {
5570  sep = "";
5571  foreach(l, query->groupClause)
5572  {
5573  SortGroupClause *grp = (SortGroupClause *) lfirst(l);
5574 
5575  appendStringInfoString(buf, sep);
5577  false, context);
5578  sep = ", ";
5579  }
5580  }
5581  else
5582  {
5583  sep = "";
5584  foreach(l, query->groupingSets)
5585  {
5586  GroupingSet *grp = lfirst(l);
5587 
5588  appendStringInfoString(buf, sep);
5589  get_rule_groupingset(grp, query->targetList, true, context);
5590  sep = ", ";
5591  }
5592  }
5593 
5594  context->special_exprkind = save_exprkind;
5595  }
5596 
5597  /* Add the HAVING clause if given */
5598  if (query->havingQual != NULL)
5599  {
5600  appendContextKeyword(context, " HAVING ",
5602  get_rule_expr(query->havingQual, context, false);
5603  }
5604 
5605  /* Add the WINDOW clause if needed */
5606  if (query->windowClause != NIL)
5607  get_rule_windowclause(query, context);
5608 }
#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:5617
static Node * get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context)
Definition: ruleutils.c:5881
Index tleSortGroupRef
Definition: parsenodes.h:1234
List * groupingSets
Definition: parsenodes.h:150
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10057
static void get_rule_windowclause(Query *query, deparse_context *context)
Definition: ruleutils.c:6055
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
ParseExprKind
Definition: parse_node.h:33
List * values_lists
Definition: parsenodes.h:1051
Node * quals
Definition: primnodes.h:1497
bool hasDistinctOn
Definition: parsenodes.h:129
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * distinctClause
Definition: parsenodes.h:156
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7868
static RangeTblEntry * get_simple_values_rte(Query *query, TupleDesc resultDesc)
Definition: ruleutils.c:5421
static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context)
Definition: ruleutils.c:5937
#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:7973
#define lfirst(lc)
Definition: pg_list.h:190
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5180
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 9586 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().

9589 {
9590  StringInfo buf = context->buf;
9591 
9592  /*
9593  * Since parse_coerce.c doesn't immediately collapse application of
9594  * length-coercion functions to constants, what we'll typically see in
9595  * such cases is a Const with typmod -1 and a length-coercion function
9596  * right above it. Avoid generating redundant output. However, beware of
9597  * suppressing casts when the user actually wrote something like
9598  * 'foo'::text::char(3).
9599  *
9600  * Note: it might seem that we are missing the possibility of needing to
9601  * print a COLLATE clause for such a Const. However, a Const could only
9602  * have nondefault collation in a post-constant-folding tree, in which the
9603  * length coercion would have been folded too. See also the special
9604  * handling of CollateExpr in coerce_to_target_type(): any collation
9605  * marking will be above the coercion node, not below it.
9606  */
9607  if (arg && IsA(arg, Const) &&
9608  ((Const *) arg)->consttype == resulttype &&
9609  ((Const *) arg)->consttypmod == -1)
9610  {
9611  /* Show the constant without normal ::typename decoration */
9612  get_const_expr((Const *) arg, context, -1);
9613  }
9614  else
9615  {
9616  if (!PRETTY_PAREN(context))
9617  appendStringInfoChar(buf, '(');
9618  get_rule_expr_paren(arg, context, false, parentNode);
9619  if (!PRETTY_PAREN(context))
9620  appendStringInfoChar(buf, ')');
9621  }
9622 
9623  /*
9624  * Never emit resulttype(arg) functional notation. A pg_proc entry could
9625  * take precedence, and a resulttype in pg_temp would require schema
9626  * qualification that format_type_with_typemod() would usually omit. We've
9627  * standardized on arg::resulttype, but CAST(arg AS resulttype) notation
9628  * would work fine.
9629  */
9630  appendStringInfo(buf, "::%s",
9631  format_type_with_typemod(resulttype, resulttypmod));
9632 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7941
static void get_const_expr(Const *constval, deparse_context *context, int showtype)
Definition: ruleutils.c:9650
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static char * buf
Definition: pg_test_fsync.c:67
#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:345
StringInfo buf
Definition: ruleutils.c:112

◆ get_column_alias_list()

static void get_column_alias_list ( deparse_columns colinfo,
deparse_context context 
)
static

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

10487 {
10488  StringInfo buf = context->buf;
10489  int i;
10490  bool first = true;
10491 
10492  /* Don't print aliases if not needed */
10493  if (!colinfo->printaliases)
10494  return;
10495 
10496  for (i = 0; i < colinfo->num_new_cols; i++)
10497  {
10498  char *colname = colinfo->new_colnames[i];
10499 
10500  if (first)
10501  {
10502  appendStringInfoChar(buf, '(');
10503  first = false;
10504  }
10505  else
10506  appendStringInfoString(buf, ", ");
10508  }
10509  if (!first)
10510  appendStringInfoChar(buf, ')');
10511 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
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 9780 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().

9781 {
9782  StringInfo buf = context->buf;
9783 
9784  if (OidIsValid(constval->constcollid))
9785  {
9786  Oid typcollation = get_typcollation(constval->consttype);
9787 
9788  if (constval->constcollid != typcollation)
9789  {
9790  appendStringInfo(buf, " COLLATE %s",
9792  }
9793  }
9794 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11288
Oid consttype
Definition: primnodes.h:196
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
Oid constcollid
Definition: primnodes.h:198
static char * buf
Definition: pg_test_fsync.c:67
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2823
StringInfo buf
Definition: ruleutils.c:112

◆ get_const_expr()

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

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

9651 {
9652  StringInfo buf = context->buf;
9653  Oid typoutput;
9654  bool typIsVarlena;
9655  char *extval;
9656  bool needlabel = false;
9657 
9658  if (constval->constisnull)
9659  {
9660  /*
9661  * Always label the type of a NULL constant to prevent misdecisions
9662  * about type when reparsing.
9663  */
9664  appendStringInfoString(buf, "NULL");
9665  if (showtype >= 0)
9666  {
9667  appendStringInfo(buf, "::%s",
9669  constval->consttypmod));
9670  get_const_collation(constval, context);
9671  }
9672  return;
9673  }
9674 
9675  getTypeOutputInfo(constval->consttype,
9676  &typoutput, &typIsVarlena);
9677 
9678  extval = OidOutputFunctionCall(typoutput, constval->constvalue);
9679 
9680  switch (constval->consttype)
9681  {
9682  case INT4OID:
9683 
9684  /*
9685  * INT4 can be printed without any decoration, unless it is
9686  * negative; in that case print it as '-nnn'::integer to ensure
9687  * that the output will re-parse as a constant, not as a constant
9688  * plus operator. In most cases we could get away with printing
9689  * (-nnn) instead, because of the way that gram.y handles negative
9690  * literals; but that doesn't work for INT_MIN, and it doesn't
9691  * seem that much prettier anyway.
9692  */
9693  if (extval[0] != '-')
9694  appendStringInfoString(buf, extval);
9695  else
9696  {
9697  appendStringInfo(buf, "'%s'", extval);
9698  needlabel = true; /* we must attach a cast */
9699  }
9700  break;
9701 
9702  case NUMERICOID:
9703 
9704  /*
9705  * NUMERIC can be printed without quotes if it looks like a float
9706  * constant (not an integer, and not Infinity or NaN) and doesn't
9707  * have a leading sign (for the same reason as for INT4).
9708  */
9709  if (isdigit((unsigned char) extval[0]) &&
9710  strcspn(extval, "eE.") != strlen(extval))
9711  {
9712  appendStringInfoString(buf, extval);
9713  }
9714  else
9715  {
9716  appendStringInfo(buf, "'%s'", extval);
9717  needlabel = true; /* we must attach a cast */
9718  }
9719  break;
9720 
9721  case BOOLOID:
9722  if (strcmp(extval, "t") == 0)
9723  appendStringInfoString(buf, "true");
9724  else
9725  appendStringInfoString(buf, "false");
9726  break;
9727 
9728  default:
9729  simple_quote_literal(buf, extval);
9730  break;
9731  }
9732 
9733  pfree(extval);
9734 
9735  if (showtype < 0)
9736  return;
9737 
9738  /*
9739  * For showtype == 0, append ::typename unless the constant will be
9740  * implicitly typed as the right type when it is read in.
9741  *
9742  * XXX this code has to be kept in sync with the behavior of the parser,
9743  * especially make_const.
9744  */
9745  switch (constval->consttype)
9746  {
9747  case BOOLOID:
9748  case UNKNOWNOID:
9749  /* These types can be left unlabeled */
9750  needlabel = false;
9751  break;
9752  case INT4OID:
9753  /* We determined above whether a label is needed */
9754  break;
9755  case NUMERICOID:
9756 
9757  /*
9758  * Float-looking constants will be typed as numeric, which we
9759  * checked above; but if there's a nondefault typmod we need to
9760  * show it.
9761  */
9762  needlabel |= (constval->consttypmod >= 0);
9763  break;
9764  default:
9765  needlabel = true;
9766  break;
9767  }
9768  if (needlabel || showtype > 0)
9769  appendStringInfo(buf, "::%s",
9771  constval->consttypmod));
9772 
9773  get_const_collation(constval, context);
9774 }
Datum constvalue
Definition: primnodes.h:200
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:196
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
static void simple_quote_literal(StringInfo buf, const char *val)
Definition: ruleutils.c:9800
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static void get_const_collation(Const *constval, deparse_context *context)
Definition: ruleutils.c:9780
static char * buf
Definition: pg_test_fsync.c:67
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:345
int32 consttypmod
Definition: primnodes.h:197
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1655
StringInfo buf
Definition: ruleutils.c:112
bool constisnull
Definition: primnodes.h:201

◆ get_delete_query_def()

static void get_delete_query_def ( Query query,
deparse_context context 
)
static

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

6618 {
6619  StringInfo buf = context->buf;
6620  RangeTblEntry *rte;
6621 
6622  /* Insert the WITH clause if given */
6623  get_with_clause(query, context);
6624 
6625  /*
6626  * Start the query with DELETE FROM relname
6627  */
6628  rte = rt_fetch(query->resultRelation, query->rtable);
6629  Assert(rte->rtekind == RTE_RELATION);
6630  if (PRETTY_INDENT(context))
6631  {
6632  appendStringInfoChar(buf, ' ');
6633  context->indentLevel += PRETTYINDENT_STD;
6634  }
6635  appendStringInfo(buf, "DELETE FROM %s%s",
6636  only_marker(rte),
6638  if (rte->alias != NULL)
6639  appendStringInfo(buf, " %s",
6641 
6642  /* Add the USING clause if given */
6643  get_from_clause(query, " USING ", context);
6644 
6645  /* Add a WHERE clause if given */
6646  if (query->jointree->quals != NULL)
6647  {
6648  appendContextKeyword(context, " WHERE ",
6650  get_rule_expr(query->jointree->quals, context, false);
6651  }
6652 
6653  /* Add RETURNING if present */
6654  if (query->returningList)
6655  {
6656  appendContextKeyword(context, " RETURNING",
6658  get_target_list(query->returningList, context, NULL);
6659  }
6660 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5223
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
Alias * alias
Definition: parsenodes.h:1091
FromExpr * jointree
Definition: parsenodes.h:138
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5617
static void get_from_clause(Query *query, const char *prefix, deparse_context *context)
Definition: ruleutils.c:10057
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
Node * quals
Definition: primnodes.h:1497
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10896
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:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7868
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:739
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7973
char * aliasname
Definition: primnodes.h:42
#define only_marker(rte)
Definition: ruleutils.c:485
RTEKind rtekind
Definition: parsenodes.h:974
StringInfo buf
Definition: ruleutils.c:112

◆ get_from_clause()

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

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

10058 {
10059  StringInfo buf = context->buf;
10060  bool first = true;
10061  ListCell *l;
10062 
10063  /*
10064  * We use the query's jointree as a guide to what to print. However, we
10065  * must ignore auto-added RTEs that are marked not inFromCl. (These can
10066  * only appear at the top level of the jointree, so it's sufficient to
10067  * check here.) This check also ensures we ignore the rule pseudo-RTEs
10068  * for NEW and OLD.
10069  */
10070  foreach(l, query->jointree->fromlist)
10071  {
10072  Node *jtnode = (Node *) lfirst(l);
10073 
10074  if (IsA(jtnode, RangeTblRef))
10075  {
10076  int varno = ((RangeTblRef *) jtnode)->rtindex;
10077  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10078 
10079  if (!rte->inFromCl)
10080  continue;
10081  }
10082 
10083  if (first)
10084  {
10085  appendContextKeyword(context, prefix,
10087  first = false;
10088 
10089  get_from_clause_item(jtnode, query, context);
10090  }
10091  else
10092  {
10093  StringInfoData itembuf;
10094 
10095  appendStringInfoString(buf, ", ");
10096 
10097  /*
10098  * Put the new FROM item's text into itembuf so we can decide
10099  * after we've got it whether or not it needs to go on a new line.
10100  */
10101  initStringInfo(&itembuf);
10102  context->buf = &itembuf;
10103 
10104  get_from_clause_item(jtnode, query, context);
10105 
10106  /* Restore context's output buffer */
10107  context->buf = buf;
10108 
10109  /* Consider line-wrapping if enabled */
10110  if (PRETTY_INDENT(context) && context->wrapColumn >= 0)
10111  {
10112  /* Does the new item start with a new line? */
10113  if (itembuf.len > 0 && itembuf.data[0] == '\n')
10114  {
10115  /* If so, we shouldn't add anything */
10116  /* instead, remove any trailing spaces currently in buf */
10118  }
10119  else
10120  {
10121  char *trailing_nl;
10122 
10123  /* Locate the start of the current line in the buffer */
10124  trailing_nl = strrchr(buf->data, '\n');
10125  if (trailing_nl == NULL)
10126  trailing_nl = buf->data;
10127  else
10128  trailing_nl++;
10129 
10130  /*
10131  * Add a newline, plus some indentation, if the new item
10132  * would cause an overflow.
10133  */
10134  if (strlen(trailing_nl) + itembuf.len > context->wrapColumn)
10135  appendContextKeyword(context, "", -PRETTYINDENT_STD,
10138  }
10139  }
10140 
10141  /* Add the new item */
10142  appendBinaryStringInfo(buf, itembuf.data, itembuf.len);
10143 
10144  /* clean up */
10145  pfree(itembuf.data);
10146  }
10147  }
10148 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
FromExpr * jointree
Definition: parsenodes.h:138
#define PRETTYINDENT_VAR
Definition: ruleutils.c:86
Definition: nodes.h:525
#define PRETTY_INDENT(context)
Definition: ruleutils.c:100
List * fromlist
Definition: primnodes.h:1496
void pfree(void *pointer)
Definition: mcxt.c:1056
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:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7868
static void removeStringInfoSpaces(StringInfo str)
Definition: ruleutils.c:7922
#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:190
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:10151

◆ get_from_clause_coldeflist()

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

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

10529 {
10530  StringInfo buf = context->buf;
10531  ListCell *l1;
10532  ListCell *l2;
10533  ListCell *l3;
10534  ListCell *l4;
10535  int i;
10536 
10537  appendStringInfoChar(buf, '(');
10538 
10539  i = 0;
10540  forfour(l1, rtfunc->funccoltypes,
10541  l2, rtfunc->funccoltypmods,
10542  l3, rtfunc->funccolcollations,
10543  l4, rtfunc->funccolnames)
10544  {
10545  Oid atttypid = lfirst_oid(l1);
10546  int32 atttypmod = lfirst_int(l2);
10547  Oid attcollation = lfirst_oid(l3);
10548  char *attname;
10549 
10550  if (colinfo)
10551  attname = colinfo->colnames[i];
10552  else
10553  attname = strVal(lfirst(l4));
10554 
10555  Assert(attname); /* shouldn't be any dropped columns here */
10556 
10557  if (i > 0)
10558  appendStringInfoString(buf, ", ");
10559  appendStringInfo(buf, "%s %s",
10560  quote_identifier(attname),
10561  format_type_with_typemod(atttypid, atttypmod));
10562  if (OidIsValid(attcollation) &&
10563  attcollation != get_typcollation(atttypid))
10564  appendStringInfo(buf, " COLLATE %s",
10565  generate_collation_name(attcollation));
10566 
10567  i++;
10568  }
10569 
10570  appendStringInfoChar(buf, ')');
10571 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
#define strVal(v)
Definition: value.h:54
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
char * generate_collation_name(Oid collid)
Definition: ruleutils.c:11288
signed int int32
Definition: c.h:347
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:191
Oid attcollation
Definition: pg_attribute.h:164
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
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:345
List * funccoltypmods
Definition: parsenodes.h:1130
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2823
List * funccolcollations
Definition: parsenodes.h:1131
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:476
StringInfo buf
Definition: ruleutils.c:112
int i
#define lfirst_oid(lc)
Definition: pg_list.h:192
char ** colnames
Definition: ruleutils.c:238

◆ get_from_clause_item()

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

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

10152 {
10153  StringInfo buf = context->buf;
10155 
10156  if (IsA(jtnode, RangeTblRef))
10157  {
10158  int varno = ((RangeTblRef *) jtnode)->rtindex;
10159  RangeTblEntry *rte = rt_fetch(varno, query->rtable);
10160  char *refname = get_rtable_name(varno, context);
10161  deparse_columns *colinfo = deparse_columns_fetch(varno, dpns);
10162  RangeTblFunction *rtfunc1 = NULL;
10163  bool printalias;
10164 
10165  if (rte->lateral)
10166  appendStringInfoString(buf, "LATERAL ");
10167 
10168  /* Print the FROM item proper */
10169  switch (rte->rtekind)
10170  {
10171  case RTE_RELATION:
10172  /* Normal relation RTE */
10173  appendStringInfo(buf, "%s%s",
10174  only_marker(rte),
10176  context->namespaces));
10177  break;
10178  case RTE_SUBQUERY:
10179  /* Subquery RTE */
10180  appendStringInfoChar(buf, '(');
10181  get_query_def(rte->subquery, buf, context->namespaces, NULL,
10182  context->prettyFlags, context->wrapColumn,
10183  context->indentLevel);
10184  appendStringInfoChar(buf, ')');
10185  break;
10186  case RTE_FUNCTION:
10187  /* Function RTE */
10188  rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
10189 
10190  /*
10191  * Omit ROWS FROM() syntax for just one function, unless it
10192  * has both a coldeflist and WITH ORDINALITY. If it has both,
10193  * we must use ROWS FROM() syntax to avoid ambiguity about
10194  * whether the coldeflist includes the ordinality column.
10195  */
10196  if (list_length(rte->functions) == 1 &&
10197  (rtfunc1->funccolnames == NIL || !rte->funcordinality))
10198  {
10199  get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
10200  /* we'll print the coldeflist below, if it has one */
10201  }
10202  else
10203  {
10204  bool all_unnest;
10205  ListCell *lc;
10206 
10207  /*
10208  * If all the function calls in the list are to unnest,
10209  * and none need a coldeflist, then collapse the list back
10210  * down to UNNEST(args). (If we had more than one
10211  * built-in unnest function, this would get more
10212  * difficult.)
10213  *
10214  * XXX This is pretty ugly, since it makes not-terribly-
10215  * future-proof assumptions about what the parser would do
10216  * with the output; but the alternative is to emit our
10217  * nonstandard ROWS FROM() notation for what might have
10218  * been a perfectly spec-compliant multi-argument
10219  * UNNEST().
10220  */
10221  all_unnest = true;
10222  foreach(lc, rte->functions)
10223  {
10224  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10225 
10226  if (!IsA(rtfunc->funcexpr, FuncExpr) ||
10227  ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST ||
10228  rtfunc->funccolnames != NIL)
10229  {
10230  all_unnest = false;
10231  break;
10232  }
10233  }
10234 
10235  if (all_unnest)
10236  {
10237  List *allargs = NIL;
10238 
10239  foreach(lc, rte->functions)
10240  {
10241  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10242  List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
10243 
10244  allargs = list_concat(allargs, args);
10245  }
10246 
10247  appendStringInfoString(buf, "UNNEST(");
10248  get_rule_expr((Node *) allargs, context, true);
10249  appendStringInfoChar(buf, ')');
10250  }
10251  else
10252  {
10253  int funcno = 0;
10254 
10255  appendStringInfoString(buf, "ROWS FROM(");
10256  foreach(lc, rte->functions)
10257  {
10258  RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
10259 
10260  if (funcno > 0)
10261  appendStringInfoString(buf, ", ");
10262  get_rule_expr_funccall(rtfunc->funcexpr, context, true);
10263  if (rtfunc->funccolnames != NIL)
10264  {
10265  /* Reconstruct the column definition list */
10266  appendStringInfoString(buf, " AS ");
10268  NULL,
10269  context);
10270  }
10271  funcno++;
10272  }
10273  appendStringInfoChar(buf, ')');
10274  }
10275  /* prevent printing duplicate coldeflist below */
10276  rtfunc1 = NULL;
10277  }
10278  if (rte->funcordinality)
10279  appendStringInfoString(buf, " WITH ORDINALITY");
10280  break;
10281  case RTE_TABLEFUNC:
10282  get_tablefunc(rte->tablefunc, context, true);
10283  break;
10284  case RTE_VALUES:
10285  /* Values list RTE */
10286  appendStringInfoChar(buf, '(');
10287  get_values_def(rte->values_lists, context);
10288  appendStringInfoChar(buf, ')');
10289  break;
10290  case RTE_CTE:
10292  break;
10293  default:
10294  elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
10295  break;
10296  }
10297 
10298  /* Print the relation alias, if needed */
10299  printalias = false;
10300  if (rte->alias != NULL)
10301  {
10302  /* Always print alias if user provided one */
10303  printalias = true;
10304  }
10305  else if (colinfo->printaliases)
10306  {
10307  /* Always print alias if we need to print column aliases */
10308  printalias = true;
10309  }
10310  else if (rte->rtekind == RTE_RELATION)
10311  {
10312  /*
10313  * No need to print alias if it's same as relation name (this
10314  * would normally be the case, but not if set_rtable_names had to
10315  * resolve a conflict).
10316  */
10317  if (strcmp(refname, get_relation_name(rte->relid)) != 0)
10318  printalias = true;
10319  }
10320  else if (rte->rtekind == RTE_FUNCTION)
10321  {
10322  /*
10323  * For a function RTE, always print alias. This covers possible
10324  * renaming of the function and/or instability of the
10325  * FigureColname rules for things that aren't simple functions.
10326  * Note we'd need to force it anyway for the columndef list case.
10327  */
10328  printalias = true;
10329  }
10330  else if (rte->rtekind == RTE_VALUES)
10331  {
10332  /* Alias is syntactically required for VALUES */
10333  printalias = true;
10334  }
10335  else if (rte->rtekind == RTE_CTE)
10336  {
10337  /*
10338  * No need to print alias if it's same as CTE name (this would
10339  * normally be the case, but not if set_rtable_names had to
10340  * resolve a conflict).
10341  */
10342  if (strcmp(refname, rte->ctename) != 0)
10343  printalias = true;
10344  }
10345  if (printalias)
10346  appendStringInfo(buf, " %s", quote_identifier(refname));
10347 
10348  /* Print the column definitions or aliases, if needed */
10349  if (rtfunc1 && rtfunc1->funccolnames != NIL)
10350  {
10351  /* Reconstruct the columndef list, which is also the aliases */
10352  get_from_clause_coldeflist(rtfunc1, colinfo, context);
10353  }
10354  else
10355  {
10356  /* Else print column aliases as needed */
10357  get_column_alias_list(colinfo, context);
10358  }
10359 
10360  /* Tablesample clause must go after any alias */
10361  if (rte->rtekind == RTE_RELATION && rte->tablesample)
10362  get_tablesample_def(rte->tablesample, context);
10363  }
10364  else if (IsA(jtnode, JoinExpr))
10365  {
10366  JoinExpr *j = (JoinExpr *) jtnode;
10367  deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns);
10368  bool need_paren_on_right;
10369 
10370  need_paren_on_right = PRETTY_PAREN(context) &&
10371  !IsA(j->rarg, RangeTblRef) &&
10372  !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
10373 
10374  if (!PRETTY_PAREN(context) || j->alias != NULL)
10375  appendStringInfoChar(buf, '(');
10376 
10377  get_from_clause_item(j->larg, query, context);
10378 
10379  switch (j->jointype)
10380  {
10381  case JOIN_INNER:
10382  if (j->quals)
10383  appendContextKeyword(context, " JOIN ",
10387  else
10388  appendContextKeyword(context, " CROSS JOIN ",
10392  break;
10393  case JOIN_LEFT:
10394  appendContextKeyword(context, " LEFT JOIN ",
10398  break;
10399  case JOIN_FULL:
10400  appendContextKeyword(context, " FULL JOIN ",
10404  break;
10405  case JOIN_RIGHT:
10406  appendContextKeyword(context, " RIGHT JOIN ",
10410  break;
10411  default:
10412  elog(ERROR, "unrecognized join type: %d",
10413  (int) j->jointype);
10414  }
10415 
10416  if (need_paren_on_right)
10417  appendStringInfoChar(buf, '(');
10418  get_from_clause_item(j->rarg, query, context);
10419  if (need_paren_on_right)
10420  appendStringInfoChar(buf, ')');
10421 
10422  if (j->usingClause)
10423  {
10424  ListCell *lc;
10425  bool first = true;
10426 
10427  appendStringInfoString(buf, " USING (");
10428  /* Use the assigned names, not what's in usingClause */
10429  foreach(lc, colinfo->usingNames)
10430  {
10431  char *colname = (char *) lfirst(lc);
10432 
10433  if (first)
10434  first = false;
10435  else
10436  appendStringInfoString(buf, ", ");
10438  }
10439  appendStringInfoChar(buf, ')');
10440  }
10441  else if (j->quals)
10442  {
10443  appendStringInfoString(buf, " ON ");
10444  if (!PRETTY_PAREN(context))
10445  appendStringInfoChar(buf, '(');
10446  get_rule_expr(j->quals, context, false);
10447  if (!PRETTY_PAREN(context))
10448  appendStringInfoChar(buf, ')');
10449  }
10450  else if (j->jointype != JOIN_INNER)
10451  {
10452  /* If we didn't say CROSS JOIN above, we must provide an ON */
10453  appendStringInfoString(buf, " ON TRUE");
10454  }
10455 
10456  if (!PRETTY_PAREN(context) || j->alias != NULL)
10457  appendStringInfoChar(buf, ')');
10458 
10459  /* Yes, it's correct to put alias after the right paren ... */
10460  if (j->alias != NULL)
10461  {
10462  /*
10463  * Note that it's correct to emit an alias clause if and only if
10464  * there was one originally. Otherwise we'd be converting a named
10465  * join to unnamed or vice versa, which creates semantic
10466  * subtleties we don't want. However, we might print a different
10467  * alias name than was there originally.
10468  */
10469  appendStringInfo(buf, " %s",
10471  context)));
10472  get_column_alias_list(colinfo, context);
10473  }
10474  }
10475  else
10476  elog(ERROR, "unrecognized node type: %d",
10477  (int) nodeTag(jtnode));
10478 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
static char * get_relation_name(Oid relid)
Definition: ruleutils.c:10876
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
#define PRETTYINDENT_JOIN
Definition: ruleutils.c:85
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
Alias * alias
Definition: parsenodes.h:1091
Definition: nodes.h:525
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
bool funcordinality
Definition: parsenodes.h:1041
List * values_lists
Definition: parsenodes.h:1051
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10896
Node * larg
Definition: primnodes.h:1476
static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
Definition: ruleutils.c:10577
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:195
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
List * usingNames
Definition: ruleutils.c:284
TableFunc * tablefunc
Definition: parsenodes.h:1046
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
#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:7868
#define deparse_columns_fetch(rangetable_index, dpns)
Definition: ruleutils.c:288
#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:1478
Node * quals
Definition: primnodes.h:1479
static void get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9952
Node * rarg
Definition: primnodes.h:1477
Alias * alias
Definition: primnodes.h:1480
JoinType jointype
Definition: primnodes.h:1474
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7973
#define lfirst(lc)
Definition: pg_list.h:190
List * functions
Definition: parsenodes.h:1040
#define only_marker(rte)
Definition: ruleutils.c:485
static int list_length(const List *l)
Definition: pg_list.h:169
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5106
#define nodeTag(nodeptr)
Definition: nodes.h:530
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5180
RTEKind rtekind
Definition: parsenodes.h:974
static void get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10486
char * ctename
Definition: parsenodes.h:1056
Query * subquery
Definition: parsenodes.h:1009
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:228
static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_columns *colinfo, deparse_context *context)
Definition: ruleutils.c:10526
static void get_rule_expr_funccall(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:9190
int rtindex
Definition: primnodes.h:1481
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1004
static char * get_rtable_name(int rtindex, deparse_context *context)
Definition: ruleutils.c:4659
static void get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
Definition: ruleutils.c:10151

◆ get_func_expr()

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

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

9303 {
9304  StringInfo buf = context->buf;
9305  Oid funcoid = expr->funcid;
9306  Oid argtypes[FUNC_MAX_ARGS];
9307  int nargs;
9308  List *argnames;
9309  bool use_variadic;
9310  ListCell *l;
9311 
9312  /*
9313  * If the function call came from an implicit coercion, then just show the
9314  * first argument --- unless caller wants to see implicit coercions.
9315  */
9316  if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
9317  {
9318  get_rule_expr_paren((Node *) linitial(expr->args), context,
9319  false, (Node *) expr);
9320  return;
9321  }
9322 
9323  /*
9324  * If the function call came from a cast, then show the first argument
9325  * plus an explicit cast operation.
9326  */
9327  if (expr->funcformat == COERCE_EXPLICIT_CAST ||
9329  {
9330  Node *arg = linitial(expr->args);
9331  Oid rettype = expr->funcresulttype;
9332  int32 coercedTypmod;
9333 
9334  /* Get the typmod if this is a length-coercion function */
9335  (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
9336 
9337  get_coercion_expr(arg, context,
9338  rettype, coercedTypmod,
9339  (Node *) expr);
9340 
9341  return;
9342  }
9343 
9344  /*
9345  * Normal function: display as proname(args). First we need to extract
9346  * the argument datatypes.
9347  */
9348  if (list_length(expr->args) > FUNC_MAX_ARGS)
9349  ereport(ERROR,
9350  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
9351  errmsg("too many arguments")));
9352  nargs = 0;
9353  argnames = NIL;
9354  foreach(l, expr->args)
9355  {
9356  Node *arg = (Node *) lfirst(l);
9357 
9358  if (IsA(arg, NamedArgExpr))
9359  argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
9360  argtypes[nargs] = exprType(arg);
9361  nargs++;
9362  }
9363 
9364  appendStringInfo(buf, "%s(",
9365  generate_function_name(funcoid, nargs,
9366  argnames, argtypes,
9367  expr->funcvariadic,
9368  &use_variadic,
9369  context->special_exprkind));
9370  nargs = 0;
9371  foreach(l, expr->args)
9372  {
9373  if (nargs++ > 0)
9374  appendStringInfoString(buf, ", ");
9375  if (use_variadic && lnext(expr->args, l) == NULL)
9376  appendStringInfoString(buf, "VARIADIC ");
9377  get_rule_expr((Node *) lfirst(l), context, true);
9378  }
9379  appendStringInfoChar(buf, ')');
9380 }
Oid funcresulttype
Definition: primnodes.h:456
#define NIL
Definition: pg_list.h:65
static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, ParseExprKind special_exprkind)
Definition: ruleutils.c:10998
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7941
List * args
Definition: primnodes.h:463
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
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:347
#define FUNC_MAX_ARGS
CoercionForm funcformat
Definition: primnodes.h:460
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:195
Oid funcid
Definition: primnodes.h:455
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:141
static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, Node *parentNode)
Definition: ruleutils.c:9586
ParseExprKind special_exprkind
Definition: ruleutils.c:120
List * lappend(List *list, void *datum)
Definition: list.c:322
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:7973
#define lfirst(lc)
Definition: pg_list.h:190
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:169
StringInfo buf
Definition: ruleutils.c:112
int errmsg(const char *fmt,...)
Definition: elog.c:822
void * arg
Definition: pg_list.h:50
bool funcvariadic
Definition: primnodes.h:458

◆ get_insert_query_def()

static void get_insert_query_def ( Query query,
deparse_context context 
)
static

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

6197 {
6198  StringInfo buf = context->buf;
6199  RangeTblEntry *select_rte = NULL;
6200  RangeTblEntry *values_rte = NULL;
6201  RangeTblEntry *rte;
6202  char *sep;
6203  ListCell *l;
6204  List *strippedexprs;
6205 
6206  /* Insert the WITH clause if given */
6207  get_with_clause(query, context);
6208 
6209  /*
6210  * If it's an INSERT ... SELECT or multi-row VALUES, there will be a
6211  * single RTE for the SELECT or VALUES. Plain VALUES has neither.
6212  */
6213  foreach(l, query->rtable)
6214  {
6215  rte = (RangeTblEntry *) lfirst(l);
6216 
6217  if (rte->rtekind == RTE_SUBQUERY)
6218  {
6219  if (select_rte)
6220  elog(ERROR, "too many subquery RTEs in INSERT");
6221  select_rte = rte;
6222  }
6223 
6224  if (rte->rtekind == RTE_VALUES)
6225  {
6226  if (values_rte)
6227  elog(ERROR, "too many values RTEs in INSERT");
6228  values_rte = rte;
6229  }
6230  }
6231  if (select_rte && values_rte)
6232  elog(ERROR, "both subquery and values RTEs in INSERT");
6233 
6234  /*
6235  * Start the query with INSERT INTO relname
6236  */
6237  rte = rt_fetch(query->resultRelation, query->rtable);
6238  Assert(rte->rtekind == RTE_RELATION);
6239 
6240  if (PRETTY_INDENT(context))
6241  {
6242  context->indentLevel += PRETTYINDENT_STD;
6243  appendStringInfoChar(buf, ' ');
6244  }
6245  appendStringInfo(buf, "INSERT INTO %s ",
6247  /* INSERT requires AS keyword for target alias */
6248  if (rte->alias != NULL)
6249  appendStringInfo(buf, "AS %s ",
6251 
6252  /*
6253  * Add the insert-column-names list. Any indirection decoration needed on
6254  * the column names can be inferred from the top targetlist.
6255  */
6256  strippedexprs = NIL;
6257  sep = "";
6258  if (query->targetList)
6259  appendStringInfoChar(buf, '(');
6260  foreach(l, query->targetList)
6261  {
6262  TargetEntry *tle = (TargetEntry *) lfirst(l);
6263 
6264  if (tle->resjunk)
6265  continue; /* ignore junk entries */
6266 
6267  appendStringInfoString(buf, sep);
6268  sep = ", ";
6269 
6270  /*
6271  * Put out name of target column; look in the catalogs, not at
6272  * tle->resname, since resname will fail to track RENAME.
6273  */
6276  tle->resno,
6277  false)));
6278 
6279  /*
6280  * Print any indirection needed (subfields or subscripts), and strip
6281  * off the top-level nodes representing the indirection assignments.
6282  * Add the stripped expressions to strippedexprs. (If it's a
6283  * single-VALUES statement, the stripped expressions are the VALUES to
6284  * print below. Otherwise they're just Vars and not really
6285  * interesting.)
6286  */
6287  strippedexprs = lappend(strippedexprs,
6288  processIndirection((Node *) tle->expr,
6289  context));
6290  }
6291  if (query->targetList)
6292  appendStringInfoString(buf, ") ");
6293 
6294  if (query->override)
6295  {
6296  if (query->override == OVERRIDING_SYSTEM_VALUE)
6297  appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE ");
6298  else if (query->override == OVERRIDING_USER_VALUE)
6299  appendStringInfoString(buf, "OVERRIDING USER VALUE ");
6300  }
6301 
6302  if (select_rte)
6303  {
6304  /* Add the SELECT */
6305  get_query_def(select_rte->subquery, buf, NIL, NULL,
6306  context->prettyFlags, context->wrapColumn,
6307  context->indentLevel);
6308  }
6309  else if (values_rte)
6310  {
6311  /* Add the multi-VALUES expression lists */
6312  get_values_def(values_rte->values_lists, context);
6313  }
6314  else if (strippedexprs)
6315  {
6316  /* Add the single-VALUES expression list */
6317  appendContextKeyword(context, "VALUES (",
6319  get_rule_expr((Node *) strippedexprs, context, false);
6320  appendStringInfoChar(buf, ')');
6321  }
6322  else
6323  {
6324  /* No expressions, so it must be DEFAULT VALUES */
6325  appendStringInfoString(buf, "DEFAULT VALUES");
6326  }
6327 
6328  /* Add ON CONFLICT if present */
6329  if (query->onConflict)
6330  {
6331  OnConflictExpr *confl = query->onConflict;
6332 
6333  appendStringInfoString(buf, " ON CONFLICT");
6334 
6335  if (confl->arbiterElems)
6336  {
6337  /* Add the single-VALUES expression list */
6338  appendStringInfoChar(buf, '(');
6339  get_rule_expr((Node *) confl->arbiterElems, context, false);
6340  appendStringInfoChar(buf, ')');
6341 
6342  /* Add a WHERE clause (for partial indexes) if given */
6343  if (confl->arbiterWhere != NULL)
6344  {
6345  bool save_varprefix;
6346 
6347  /*
6348  * Force non-prefixing of Vars, since parser assumes that they
6349  * belong to target relation. WHERE clause does not use
6350  * InferenceElem, so this is separately required.
6351  */
6352  save_varprefix = context->varprefix;
6353  context->varprefix = false;
6354 
6355  appendContextKeyword(context, " WHERE ",
6357  get_rule_expr(confl->arbiterWhere, context, false);
6358 
6359  context->varprefix = save_varprefix;
6360  }
6361  }
6362  else if (OidIsValid(confl->constraint))
6363  {
6364  char *constraint = get_constraint_name(confl->constraint);
6365 
6366  if (!constraint)
6367  elog(ERROR, "cache lookup failed for constraint %u",
6368  confl->constraint);
6369  appendStringInfo(buf, " ON CONSTRAINT %s",
6370  quote_identifier(constraint));
6371  }
6372 
6373  if (confl->action == ONCONFLICT_NOTHING)
6374  {
6375  appendStringInfoString(buf, " DO NOTHING");
6376  }
6377  else
6378  {
6379  appendStringInfoString(buf, " DO UPDATE SET ");
6380  /* Deparse targetlist */
6382  context, rte);
6383 
6384  /* Add a WHERE clause if given */
6385  if (confl->onConflictWhere != NULL)
6386  {
6387  appendContextKeyword(context, " WHERE ",
6389  get_rule_expr(confl->onConflictWhere, context, false);
6390  }
6391  }
6392  }
6393 
6394  /* Add RETURNING if present */
6395  if (query->returningList)
6396  {
6397  appendContextKeyword(context, " RETURNING",
6399  get_target_list(query->returningList, context, NULL);
6400  }
6401 }
#define NIL
Definition: pg_list.h:65
static void get_with_clause(Query *query, deparse_context *context)
Definition: ruleutils.c:5223
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
Alias * alias
Definition: parsenodes.h:1091
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:969
OnConflictExpr * onConflict
Definition: parsenodes.h:144
static Node * processIndirection(Node *node, deparse_context *context)
Definition: ruleutils.c:10664
int resultRelation
Definition: parsenodes.h:122
static void get_target_list(List *targetList, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5617
Definition: nodes.h:525
#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:6464
#define OidIsValid(objectId)
Definition: c.h:645
List * values_lists
Definition: parsenodes.h:1051
List * targetList
Definition: parsenodes.h:140
List * arbiterElems
Definition: primnodes.h:1515
static char * generate_relation_name(Oid relid, List *namespaces)
Definition: ruleutils.c:10896
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1400
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
static void appendContextKeyword(deparse_context *context, const char *str, int indentBefore, int indentAfter, int indentPlus)
Definition: ruleutils.c:7868
AttrNumber resno
Definition: primnodes.h:1394
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define PRETTYINDENT_STD
Definition: ruleutils.c:84
List * lappend(List *list, void *datum)
Definition: list.c:322
OnConflictAction action
Definition: primnodes.h:1512
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
OverridingKind override
Definition: parsenodes.h:142
#define Assert(condition)
Definition: c.h:739
static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit)
Definition: ruleutils.c:7973
#define lfirst(lc)
Definition: pg_list.h:190
char * aliasname
Definition: primnodes.h:42
Expr * expr
Definition: primnodes.h:1393
static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent)
Definition: ruleutils.c:5106
static void get_values_def(List *values_lists, deparse_context *context)
Definition: ruleutils.c:5180
RTEKind rtekind
Definition: parsenodes.h:974
Node * arbiterWhere
Definition: primnodes.h:1517
Query * subquery
Definition: parsenodes.h:1009
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:228
List * onConflictSet
Definition: primnodes.h:1521
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
Node * onConflictWhere
Definition: primnodes.h:1522
Definition: pg_list.h:50

◆ get_name_for_var_field()

static const char* get_name_for_var_field ( Var var,
int  fieldno,
int  levelsup,
deparse_context context 
)
static

Definition at line 7050 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, pop_ancestor_plan(), pop_child_plan(), push_ancestor_plan(), push_child_plan(), TargetEntry::resjunk, rt_fetch, deparse_namespace::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, set_deparse_for_query(), strVal, RangeTblEntry::subquery, Query::targetList, TupleDescAttr, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

Referenced by get_rule_expr().

7052 {
7053  RangeTblEntry *rte;
7055  int netlevelsup;
7056  deparse_namespace *dpns;
7057  TupleDesc tupleDesc;
7058  Node *expr;
7059 
7060  /*
7061  * If it's a RowExpr that was expanded from a whole-row Var, use the
7062  * column names attached to it.
7063  */
7064  if (IsA(var, RowExpr))
7065  {
7066  RowExpr *r = (RowExpr *) var;
7067 
7068  if (fieldno > 0 && fieldno <= list_length(r->colnames))
7069  return strVal(list_nth(r->colnames, fieldno - 1));
7070  }
7071 
7072  /*
7073  * If it's a Param of type RECORD, try to find what the Param refers to.
7074  */
7075  if (IsA(var, Param))
7076  {
7077  Param *param = (Param *) var;
7078  ListCell *ancestor_cell;
7079 
7080  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7081  if (expr)
7082  {
7083  /* Found a match, so recurse to decipher the field name */
7084  deparse_namespace save_dpns;
7085  const char *result;
7086 
7087  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7088  result = get_name_for_var_field((Var *) expr, fieldno,
7089  0, context);
7090  pop_ancestor_plan(dpns, &save_dpns);
7091  return result;
7092  }
7093  }
7094 
7095  /*
7096  * If it's a Var of type RECORD, we have to find what the Var refers to;
7097  * if not, we can use get_expr_result_tupdesc().
7098  */
7099  if (!IsA(var, Var) ||
7100  var->vartype != RECORDOID)
7101  {
7102  tupleDesc = get_expr_result_tupdesc((Node *) var, false);
7103  /* Got the tupdesc, so we can extract the field name */
7104  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7105  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7106  }
7107 
7108  /* Find appropriate nesting depth */
7109  netlevelsup = var->varlevelsup + levelsup;
7110  if (netlevelsup >= list_length(context->namespaces))
7111  elog(ERROR, "bogus varlevelsup: %d offset %d",
7112  var->varlevelsup, levelsup);
7113  dpns = (deparse_namespace *) list_nth(context->namespaces,
7114  netlevelsup);
7115 
7116  /*
7117  * Try to find the relevant RTE in this rtable. In a plan tree, it's
7118  * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig
7119  * down into the subplans, or INDEX_VAR, which is resolved similarly.
7120  *
7121  * Note: unlike get_variable and resolve_special_varno, we need not worry
7122  * about inheritance mapping: a child Var should have the same datatype as
7123  * its parent, and here we're really only interested in the Var's type.
7124  */
7125  if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
7126  {
7127  rte = rt_fetch(var->varno, dpns->rtable);
7128  attnum = var->varattno;
7129  }
7130  else if (var->varno == OUTER_VAR && dpns->outer_tlist)
7131  {
7132  TargetEntry *tle;
7133  deparse_namespace save_dpns;
7134  const char *result;
7135 
7136  tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
7137  if (!tle)
7138  elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
7139 
7140  Assert(netlevelsup == 0);
7141  push_child_plan(dpns, dpns->outer_plan, &save_dpns);
7142 
7143  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7144  levelsup, context);
7145 
7146  pop_child_plan(dpns, &save_dpns);
7147  return result;
7148  }
7149  else if (var->varno == INNER_VAR && dpns->inner_tlist)
7150  {
7151  TargetEntry *tle;
7152  deparse_namespace save_dpns;
7153  const char *result;
7154 
7155  tle = get_tle_by_resno(dpns->inner_tlist, var->varattno);
7156  if (!tle)
7157  elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
7158 
7159  Assert(netlevelsup == 0);
7160  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7161 
7162  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7163  levelsup, context);
7164 
7165  pop_child_plan(dpns, &save_dpns);
7166  return result;
7167  }
7168  else if (var->varno == INDEX_VAR && dpns->index_tlist)
7169  {
7170  TargetEntry *tle;
7171  const char *result;
7172 
7173  tle = get_tle_by_resno(dpns->index_tlist, var->varattno);
7174  if (!tle)
7175  elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
7176 
7177  Assert(netlevelsup == 0);
7178 
7179  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7180  levelsup, context);
7181 
7182  return result;
7183  }
7184  else
7185  {
7186  elog(ERROR, "bogus varno: %d", var->varno);
7187  return NULL; /* keep compiler quiet */
7188  }
7189 
7190  if (attnum == InvalidAttrNumber)
7191  {
7192  /* Var is whole-row reference to RTE, so select the right field */
7193  return get_rte_attribute_name(rte, fieldno);
7194  }
7195 
7196  /*
7197  * This part has essentially the same logic as the parser's
7198  * expandRecordVariable() function, but we are dealing with a different
7199  * representation of the input context, and we only need one field name
7200  * not a TupleDesc. Also, we need special cases for finding subquery and
7201  * CTE subplans when deparsing Plan trees.
7202  */
7203  expr = (Node *) var; /* default if we can't drill down */
7204 
7205  switch (rte->rtekind)
7206  {
7207  case RTE_RELATION:
7208  case RTE_VALUES:
7209  case RTE_NAMEDTUPLESTORE:
7210  case RTE_RESULT:
7211 
7212  /*
7213  * This case should not occur: a column of a table, values list,
7214  * or ENR shouldn't have type RECORD. Fall through and fail (most
7215  * likely) at the bottom.
7216  */
7217  break;
7218  case RTE_SUBQUERY:
7219  /* Subselect-in-FROM: examine sub-select's output expr */
7220  {
7221  if (rte->subquery)
7222  {
7224  attnum);
7225 
7226  if (ste == NULL || ste->resjunk)
7227  elog(ERROR, "subquery %s does not have attribute %d",
7228  rte->eref->aliasname, attnum);
7229  expr = (Node *) ste->expr;
7230  if (IsA(expr, Var))
7231  {
7232  /*
7233  * Recurse into the sub-select to see what its Var
7234  * refers to. We have to build an additional level of
7235  * namespace to keep in step with varlevelsup in the
7236  * subselect.
7237  */
7238  deparse_namespace mydpns;
7239  const char *result;
7240 
7241  set_deparse_for_query(&mydpns, rte->subquery,
7242  context->namespaces);
7243 
7244  context->namespaces = lcons(&mydpns,
7245  context->namespaces);
7246 
7247  result = get_name_for_var_field((Var *) expr, fieldno,
7248  0, context);
7249 
7250  context->namespaces =
7251  list_delete_first(context->namespaces);
7252 
7253  return result;
7254  }
7255  /* else fall through to inspect the expression */
7256  }
7257  else
7258  {
7259  /*
7260  * We're deparsing a Plan tree so we don't have complete
7261  * RTE entries (in particular, rte->subquery is NULL). But
7262  * the only place we'd see a Var directly referencing a
7263  * SUBQUERY RTE is in a SubqueryScan plan node, and we can
7264  * look into the child plan's tlist instead.
7265  */
7266  TargetEntry *tle;
7267  deparse_namespace save_dpns;
7268  const char *result;
7269 
7270  if (!dpns->inner_plan)
7271  elog(ERROR, "failed to find plan for subquery %s",
7272  rte->eref->aliasname);
7273  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7274  if (!tle)
7275  elog(ERROR, "bogus varattno for subquery var: %d",
7276  attnum);
7277  Assert(netlevelsup == 0);
7278  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7279 
7280  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7281  levelsup, context);
7282 
7283  pop_child_plan(dpns, &save_dpns);
7284  return result;
7285  }
7286  }
7287  break;
7288  case RTE_JOIN:
7289  /* Join RTE --- recursively inspect the alias variable */
7290  if (rte->joinaliasvars == NIL)
7291  elog(ERROR, "cannot decompile join alias var in plan tree");
7292  Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
7293  expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
7294  Assert(expr != NULL);
7295  /* we intentionally don't strip implicit coercions here */
7296  if (IsA(expr, Var))
7297  return get_name_for_var_field((Var *) expr, fieldno,
7298  var->varlevelsup + levelsup,
7299  context);
7300  /* else fall through to inspect the expression */
7301  break;
7302  case RTE_FUNCTION:
7303  case RTE_TABLEFUNC:
7304 
7305  /*
7306  * We couldn't get here unless a function is declared with one of
7307  * its result columns as RECORD, which is not allowed.
7308  */
7309  break;
7310  case RTE_CTE:
7311  /* CTE reference: examine subquery's output expr */
7312  {
7313  CommonTableExpr *cte = NULL;
7314  Index ctelevelsup;
7315  ListCell *lc;
7316 
7317  /*
7318  * Try to find the referenced CTE using the namespace stack.
7319  */
7320  ctelevelsup = rte->ctelevelsup + netlevelsup;
7321  if (ctelevelsup >= list_length(context->namespaces))
7322  lc = NULL;
7323  else
7324  {
7325  deparse_namespace *ctedpns;
7326 
7327  ctedpns = (deparse_namespace *)
7328  list_nth(context->namespaces, ctelevelsup);
7329  foreach(lc, ctedpns->ctes)
7330  {
7331  cte = (CommonTableExpr *) lfirst(lc);
7332  if (strcmp(cte->ctename, rte->ctename) == 0)
7333  break;
7334  }
7335  }
7336  if (lc != NULL)
7337  {
7338  Query *ctequery = (Query *) cte->ctequery;
7340  attnum);
7341 
7342  if (ste == NULL || ste->resjunk)
7343  elog(ERROR, "subquery %s does not have attribute %d",
7344  rte->eref->aliasname, attnum);
7345  expr = (Node *) ste->expr;
7346  if (IsA(expr, Var))
7347  {
7348  /*
7349  * Recurse into the CTE to see what its Var refers to.
7350  * We have to build an additional level of namespace
7351  * to keep in step with varlevelsup in the CTE.
7352  * Furthermore it could be an outer CTE, so we may
7353  * have to delete some levels of namespace.
7354  */
7355  List *save_nslist = context->namespaces;
7356  List *new_nslist;
7357  deparse_namespace mydpns;
7358  const char *result;
7359 
7360  set_deparse_for_query(&mydpns, ctequery,
7361  context->namespaces);
7362 
7363  new_nslist = list_copy_tail(context->namespaces,
7364  ctelevelsup);
7365  context->namespaces = lcons(&mydpns, new_nslist);
7366 
7367  result = get_name_for_var_field((Var *) expr, fieldno,
7368  0, context);
7369 
7370  context->namespaces = save_nslist;
7371 
7372  return result;
7373  }
7374  /* else fall through to inspect the expression */
7375  }
7376  else
7377  {
7378  /*
7379  * We're deparsing a Plan tree so we don't have a CTE
7380  * list. But the only place we'd see a Var directly
7381  * referencing a CTE RTE is in a CteScan plan node, and we
7382  * can look into the subplan's tlist instead.
7383  */
7384  TargetEntry *tle;
7385  deparse_namespace save_dpns;
7386  const char *result;
7387 
7388  if (!dpns->inner_plan)
7389  elog(ERROR, "failed to find plan for CTE %s",
7390  rte->eref->aliasname);
7391  tle = get_tle_by_resno(dpns->inner_tlist, attnum);
7392  if (!tle)
7393  elog(ERROR, "bogus varattno for subquery var: %d",
7394  attnum);
7395  Assert(netlevelsup == 0);
7396  push_child_plan(dpns, dpns->inner_plan, &save_dpns);
7397 
7398  result = get_name_for_var_field((Var *) tle->expr, fieldno,
7399  levelsup, context);
7400 
7401  pop_child_plan(dpns, &save_dpns);
7402  return result;
7403  }
7404  }
7405  break;
7406  }
7407 
7408  /*
7409  * We now have an expression we can't expand any more, so see if
7410  * get_expr_result_tupdesc() can do anything with it.
7411  */
7412  tupleDesc = get_expr_result_tupdesc(expr, false);
7413  /* Got the tupdesc, so we can extract the field name */
7414  Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
7415  return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname);
7416 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * joinaliasvars
Definition: parsenodes.h:1030
Index varlevelsup
Definition: primnodes.h:177
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7427
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:525
#define strVal(v)
Definition: value.h:54
AttrNumber varattno
Definition: primnodes.h:172
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4822
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1423
Definition: primnodes.h:167
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1400
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
List * colnames
Definition: primnodes.h:1024
TupleDesc get_expr_result_tupdesc(Node *expr, bool noError)
Definition: funcapi.c:429
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
Oid vartype
Definition: primnodes.h:174
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Index varno
Definition: primnodes.h:170
List * outer_tlist
Definition: ruleutils.c:174
unsigned int Index
Definition: c.h:476
static const char * get_name_for_var_field(Var *var, int fieldno, int levelsup, deparse_context *context)
Definition: ruleutils.c:7050
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:157
char * get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
List * lcons(void *datum, List *list)
Definition: list.c:454
static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4771
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
char * aliasname
Definition: primnodes.h:42
static void push_child_plan(deparse_namespace *dpns, Plan *plan, deparse_namespace *save_dpns)
Definition: ruleutils.c:4754
Expr * expr
Definition: primnodes.h:1393
static int list_length(const List *l)
Definition: pg_list.h:169
Index ctelevelsup
Definition: parsenodes.h:1057
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3589
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:974
char * ctename
Definition: parsenodes.h:1056
Query * subquery
Definition: parsenodes.h:1009
List * index_tlist
Definition: ruleutils.c: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:4801
#define elog(elevel,...)
Definition: elog.h:228
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define NameStr(name)
Definition: c.h:616
Alias * eref
Definition: parsenodes.h:1092
#define INDEX_VAR
Definition: primnodes.h:159
Definition: pg_list.h:50
#define GetCTETargetList(cte)
Definition: parsenodes.h:1444
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:158
List * list_delete_first(List *list)
Definition: list.c:861

◆ get_opclass_name()

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

Definition at line 10621 of file ruleutils.c.

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

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

10623 {
10624  HeapTuple ht_opc;
10625  Form_pg_opclass opcrec;
10626  char *opcname;
10627  char *nspname;
10628 
10629  ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
10630  if (!HeapTupleIsValid(ht_opc))
10631  elog(ERROR, "cache lookup failed for opclass %u", opclass);
10632  opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
10633 
10634  if (!OidIsValid(actual_datatype) ||
10635  GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
10636  {
10637  /* Okay, we need the opclass name. Do we need to qualify it? */
10638  opcname = NameStr(opcrec->opcname);
10639  if (OpclassIsVisible(opclass))
10640  appendStringInfo(buf, " %s", quote_identifier(opcname));
10641  else
10642  {
10643  nspname = get_namespace_name(opcrec->opcnamespace);
10644  appendStringInfo(buf, " %s.%s",
10645  quote_identifier(nspname),
10646  quote_identifier(opcname));
10647  }
10648  }
10649  ReleaseSysCache(ht_opc);
10650 }
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1939
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10772
#define OidIsValid(objectId)
Definition: c.h:645
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:3094
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:1825
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:616
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 9240 of file ruleutils.c.

References appendStringInfo(), appendStringInfoChar(), arg, generate_unaccent_rules::args, OpExpr::args, buf, deparse_context::buf, elog, ERROR, exprType(), generate_operator_name(), get_rule_expr_paren(), GETSTRUCT, HeapTupleIsValid, InvalidOid, linitial, list_length(), lsecond, ObjectIdGetDatum, OPEROID, OpExpr::opno, PRETTY_PAREN, ReleaseSysCache(), and SearchSysCache1().

Referenced by get_rule_expr().

9241 {
9242  StringInfo buf = context->buf;
9243  Oid opno = expr->opno;
9244  List *args = expr->args;
9245 
9246  if (!PRETTY_PAREN(context))
9247  appendStringInfoChar(buf, '(');
9248  if (list_length(args) == 2)
9249  {
9250  /* binary operator */
9251  Node *arg1 = (Node *) linitial(args);
9252  Node *arg2 = (Node *) lsecond(args);
9253 
9254  get_rule_expr_paren(arg1, context, true, (Node *) expr);
9255  appendStringInfo(buf, " %s ",
9257  exprType(arg1),
9258  exprType(arg2)));
9259  get_rule_expr_paren(arg2, context, true, (Node *) expr);
9260  }
9261  else
9262  {
9263  /* unary operator --- but which side? */
9264  Node *arg = (Node *) linitial(args);
9265  HeapTuple tp;
9266  Form_pg_operator optup;
9267 
9269  if (!HeapTupleIsValid(tp))
9270  elog(ERROR, "cache lookup failed for operator %u", opno);
9271  optup = (Form_pg_operator) GETSTRUCT(tp);
9272  switch (optup->oprkind)
9273  {
9274  case 'l':
9275  appendStringInfo(buf, "%s ",
9277  InvalidOid,
9278  exprType(arg)));
9279  get_rule_expr_paren(arg, context, true, (Node *) expr);
9280  break;
9281  case 'r':
9282  get_rule_expr_paren(arg, context, true, (Node *) expr);
9283  appendStringInfo(buf, " %s",
9285  exprType(arg),
9286  InvalidOid));
9287  break;
9288  default:
9289  elog(ERROR, "bogus oprkind: %d", optup->oprkind);
9290  }
9291  ReleaseSysCache(tp);
9292  }
9293  if (!PRETTY_PAREN(context))
9294  appendStringInfoChar(buf, ')');
9295 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static void get_rule_expr_paren(Node *node, deparse_context *context, bool showimplicit, Node *parentNode)
Definition: ruleutils.c:7941
Definition: nodes.h:525
unsigned int Oid
Definition: postgres_ext.h:31
#define lsecond(l)
Definition: pg_list.h:200
static char * generate_operator_name(Oid operid, Oid arg1, Oid arg2)
Definition: ruleutils.c:11103
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define linitial(l)
Definition: pg_list.h:195
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define PRETTY_PAREN(context)
Definition: ruleutils.c:99
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:169
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:228
void * arg
Oid opno
Definition: primnodes.h:502
List * args
Definition: primnodes.h:508
Definition: pg_list.h:50

◆ get_parameter()

static void get_parameter ( Param param,
deparse_context context 
)
static

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

7563 {
7564  Node *expr;
7565  deparse_namespace *dpns;
7566  ListCell *ancestor_cell;
7567 
7568  /*
7569  * If it's a PARAM_EXEC parameter, try to locate the expression from which
7570  * the parameter was computed. Note that failing to find a referent isn't
7571  * an error, since the Param might well be a subplan output rather than an
7572  * input.
7573  */
7574  expr = find_param_referent(param, context, &dpns, &ancestor_cell);
7575  if (expr)
7576  {
7577  /* Found a match, so print it */
7578  deparse_namespace save_dpns;
7579  bool save_varprefix;
7580  bool need_paren;
7581 
7582  /* Switch attention to the ancestor plan node */
7583  push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
7584 
7585  /*
7586  * Force prefixing of Vars, since they won't belong to the relation
7587  * being scanned in the original plan node.
7588  */
7589  save_varprefix = context->varprefix;
7590  context->varprefix = true;
7591 
7592  /*
7593  * A Param's expansion is typically a Var, Aggref, or upper-level
7594  * Param, which wouldn't need extra parentheses. Otherwise, insert
7595  * parens to ensure the expression looks atomic.
7596  */
7597  need_paren = !(IsA(expr, Var) ||
7598  IsA(expr, Aggref) ||
7599  IsA(expr, Param));
7600  if (need_paren)
7601  appendStringInfoChar(context->buf, '(');
7602 
7603  get_rule_expr(expr, context, false);
7604 
7605  if (need_paren)
7606  appendStringInfoChar(context->buf, ')');
7607 
7608  context->varprefix = save_varprefix;
7609 
7610  pop_ancestor_plan(dpns, &save_dpns);
7611 
7612  return;
7613  }
7614 
7615  /*
7616  * Not PARAM_EXEC, or couldn't find referent: just print $N.
7617  */
7618  appendStringInfo(context->buf, "$%d", param->paramid);
7619 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static Node * find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p)
Definition: ruleutils.c:7427
Definition: nodes.h:525
static void pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
Definition: ruleutils.c:4822
Definition: primnodes.h:167
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:7973
int paramid
Definition: primnodes.h:249
StringInfo buf
Definition: ruleutils.c:112
static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, deparse_namespace *save_dpns)
Definition: ruleutils.c:4801

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

5109 {
5110  deparse_context context;
5111  deparse_namespace dpns;
5112 
5113  /* Guard against excessively long or deeply-nested queries */
5116 
5117  /*
5118  * Before we begin to examine the query, acquire locks on referenced
5119  * relations, and fix up deleted columns in JOIN RTEs. This ensures
5120  * consistent results. Note we assume it's OK to scribble on the passed
5121  * querytree!
5122  *
5123  * We are only deparsing the query (we are not about to execute it), so we
5124  * only need AccessShareLock on the relations it mentions.
5125  */
5126  AcquireRewriteLocks(query, false, false);
5127 
5128  context.buf = buf;
5129  context.namespaces = lcons(&dpns, list_copy(parentnamespace));
5130  context.windowClause = NIL;
5131  context.windowTList = NIL;
5132  context.varprefix = (parentnamespace != NIL ||
5133  list_length(query->rtable) != 1);
5134  context.prettyFlags = prettyFlags;
5135  context.wrapColumn = wrapColumn;
5136  context.indentLevel = startIndent;
5137  context.special_exprkind = EXPR_KIND_NONE;
5138  context.appendparents = NULL;
5139 
5140  set_deparse_for_query(&dpns, query, parentnamespace);
5141 
5142  switch (query->commandType)
5143  {
5144  case CMD_SELECT:
5145  get_select_query_def(query, &context, resultDesc);
5146  break;
5147 
5148  case CMD_UPDATE:
5149  get_update_query_def(query, &context);
5150  break;
5151 
5152  case CMD_INSERT:
5153  get_insert_query_def(query, &context);
5154  break;
5155 
5156  case CMD_DELETE:
5157  get_delete_query_def(query, &context);
5158  break;
5159 
5160  case CMD_NOTHING:
5161  appendStringInfoString(buf, "NOTHING");
5162  break;
5163 
5164  case CMD_UTILITY:
5165  get_utility_query_def(query, &context);
5166  break;
5167 
5168  default:
5169  elog(ERROR, "unrecognized query command type: %d",
5170  query->commandType);
5171  break;
5172  }
5173 }
List * namespaces
Definition: ruleutils.c:113
#define NIL
Definition: pg_list.h:65
List * list_copy(const List *oldlist)
Definition: list.c:1404
static void get_insert_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6196
static void get_update_query_def(Query *query, deparse_context *context)
Definition: ruleutils.c:6409
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:6668
static void get_select_query_def(Query *query, deparse_context *context, TupleDesc resultDesc)
Definition: ruleutils.c:5303
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
void check_stack_depth(void)
Definition: postgres.c:3302
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:6617
List * windowTList
Definition: ruleutils.c:115
CmdType commandType
Definition: parsenodes.h:112
List * lcons(void *datum, List *list)
Definition: list.c:454
List * windowClause
Definition: ruleutils.c:114
static int list_length(const List *l)
Definition: pg_list.h:169
static void set_deparse_for_query(deparse_namespace *dpns, Query *query, List *parent_namespaces)
Definition: ruleutils.c:3589
Bitmapset * appendparents
Definition: ruleutils.c:122
StringInfo buf
Definition: ruleutils.c:112
#define elog(elevel,...)
Definition: elog.h:228
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99

◆ get_range_partbound_string()

char* get_range_partbound_string ( List bound_datums)

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

11414 {
11415  deparse_context context;
11417  ListCell *cell;
11418  char *sep;
11419 
11420  memset(&context, 0, sizeof(deparse_context));
11421  context.buf = buf;
11422 
11423  appendStringInfoString(buf, "(");
11424  sep = "";
11425  foreach(cell, bound_datums)
11426  {
11427  PartitionRangeDatum *datum =
11429 
11430  appendStringInfoString(buf, sep);
11431  if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
11432  appendStringInfoString(buf, "MINVALUE");
11433  else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)