1 /*------------------------------------------------------------------------- 2 * 3 * ruleutils.c 4 * Functions to convert stored expressions/querytrees back to 5 * source text 6 * 7 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group 8 * Portions Copyright (c) 1994, Regents of the University of California 9 * 10 * 11 * IDENTIFICATION 12 * src/backend/utils/adt/ruleutils.c 13 * 14 *------------------------------------------------------------------------- 15 */ 16 #include "postgres.h" 17 18 #include <ctype.h> 19 #include <unistd.h> 20 #include <fcntl.h> 21 22 #include "access/amapi.h" 23 #include "access/htup_details.h" 24 #include "access/relation.h" 25 #include "access/sysattr.h" 26 #include "access/table.h" 27 #include "catalog/dependency.h" 28 #include "catalog/indexing.h" 29 #include "catalog/pg_aggregate.h" 30 #include "catalog/pg_am.h" 31 #include "catalog/pg_authid.h" 32 #include "catalog/pg_collation.h" 33 #include "catalog/pg_constraint.h" 34 #include "catalog/pg_depend.h" 35 #include "catalog/pg_language.h" 36 #include "catalog/pg_opclass.h" 37 #include "catalog/pg_operator.h" 38 #include "catalog/pg_partitioned_table.h" 39 #include "catalog/pg_proc.h" 40 #include "catalog/pg_statistic_ext.h" 41 #include "catalog/pg_trigger.h" 42 #include "catalog/pg_type.h" 43 #include "commands/defrem.h" 44 #include "commands/tablespace.h" 45 #include "common/keywords.h" 46 #include "executor/spi.h" 47 #include "funcapi.h" 48 #include "mb/pg_wchar.h" 49 #include "miscadmin.h" 50 #include "nodes/makefuncs.h" 51 #include "nodes/nodeFuncs.h" 52 #include "optimizer/optimizer.h" 53 #include "parser/parse_node.h" 54 #include "parser/parse_agg.h" 55 #include "parser/parse_func.h" 56 #include "parser/parse_oper.h" 57 #include "parser/parser.h" 58 #include "parser/parsetree.h" 59 #include "rewrite/rewriteHandler.h" 60 #include "rewrite/rewriteManip.h" 61 #include "rewrite/rewriteSupport.h" 62 #include "utils/array.h" 63 #include "utils/builtins.h" 64 #include "utils/fmgroids.h" 65 #include "utils/guc.h" 66 #include "utils/hsearch.h" 67 #include "utils/lsyscache.h" 68 #include "utils/partcache.h" 69 #include "utils/rel.h" 70 #include "utils/ruleutils.h" 71 #include "utils/snapmgr.h" 72 #include "utils/syscache.h" 73 #include "utils/typcache.h" 74 #include "utils/varlena.h" 75 #include "utils/xml.h" 76 77 78 /* ---------- 79 * Pretty formatting constants 80 * ---------- 81 */ 82 83 /* Indent counts */ 84 #define PRETTYINDENT_STD 8 85 #define PRETTYINDENT_JOIN 4 86 #define PRETTYINDENT_VAR 4 87 88 #define PRETTYINDENT_LIMIT 40 /* wrap limit */ 89 90 /* Pretty flags */ 91 #define PRETTYFLAG_PAREN 0x0001 92 #define PRETTYFLAG_INDENT 0x0002 93 #define PRETTYFLAG_SCHEMA 0x0004 94 95 /* Default line length for pretty-print wrapping: 0 means wrap always */ 96 #define WRAP_COLUMN_DEFAULT 0 97 98 /* macros to test if pretty action needed */ 99 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN) 100 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT) 101 #define PRETTY_SCHEMA(context) ((context)->prettyFlags & PRETTYFLAG_SCHEMA) 102 103 104 /* ---------- 105 * Local data types 106 * ---------- 107 */ 108 109 /* Context info needed for invoking a recursive querytree display routine */ 110 typedef struct 111 { 112 StringInfo buf; /* output buffer to append to */ 113 List *namespaces; /* List of deparse_namespace nodes */ 114 List *windowClause; /* Current query level's WINDOW clause */ 115 List *windowTList; /* targetlist for resolving WINDOW clause */ 116 int prettyFlags; /* enabling of pretty-print functions */ 117 int wrapColumn; /* max line length, or -1 for no limit */ 118 int indentLevel; /* current indent level for prettyprint */ 119 bool varprefix; /* true to print prefixes on Vars */ 120 ParseExprKind special_exprkind; /* set only for exprkinds needing special 121 * handling */ 122 } deparse_context; 123 124 /* 125 * Each level of query context around a subtree needs a level of Var namespace. 126 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in 127 * the current context's namespaces list. 128 * 129 * The rangetable is the list of actual RTEs from the query tree, and the 130 * cte list is the list of actual CTEs. 131 * 132 * rtable_names holds the alias name to be used for each RTE (either a C 133 * string, or NULL for nameless RTEs such as unnamed joins). 134 * rtable_columns holds the column alias names to be used for each RTE. 135 * 136 * In some cases we need to make names of merged JOIN USING columns unique 137 * across the whole query, not only per-RTE. If so, unique_using is true 138 * and using_names is a list of C strings representing names already assigned 139 * to USING columns. 140 * 141 * When deparsing plan trees, there is always just a single item in the 142 * deparse_namespace list (since a plan tree never contains Vars with 143 * varlevelsup > 0). We store the PlanState node that is the immediate 144 * parent of the expression to be deparsed, as well as a list of that 145 * PlanState's ancestors. In addition, we store its outer and inner subplan 146 * state nodes, as well as their plan nodes' targetlists, and the index tlist 147 * if the current plan node might contain INDEX_VAR Vars. (These fields could 148 * be derived on-the-fly from the current PlanState, but it seems notationally 149 * clearer to set them up as separate fields.) 150 */ 151 typedef struct 152 { 153 List *rtable; /* List of RangeTblEntry nodes */ 154 List *rtable_names; /* Parallel list of names for RTEs */ 155 List *rtable_columns; /* Parallel list of deparse_columns structs */ 156 List *ctes; /* List of CommonTableExpr nodes */ 157 /* Workspace for column alias assignment: */ 158 bool unique_using; /* Are we making USING names globally unique */ 159 List *using_names; /* List of assigned names for USING columns */ 160 /* Remaining fields are used only when deparsing a Plan tree: */ 161 PlanState *planstate; /* immediate parent of current expression */ 162 List *ancestors; /* ancestors of planstate */ 163 PlanState *outer_planstate; /* outer subplan state, or NULL if none */ 164 PlanState *inner_planstate; /* inner subplan state, or NULL if none */ 165 List *outer_tlist; /* referent for OUTER_VAR Vars */ 166 List *inner_tlist; /* referent for INNER_VAR Vars */ 167 List *index_tlist; /* referent for INDEX_VAR Vars */ 168 } deparse_namespace; 169 170 /* 171 * Per-relation data about column alias names. 172 * 173 * Selecting aliases is unreasonably complicated because of the need to dump 174 * rules/views whose underlying tables may have had columns added, deleted, or 175 * renamed since the query was parsed. We must nonetheless print the rule/view 176 * in a form that can be reloaded and will produce the same results as before. 177 * 178 * For each RTE used in the query, we must assign column aliases that are 179 * unique within that RTE. SQL does not require this of the original query, 180 * but due to factors such as *-expansion we need to be able to uniquely 181 * reference every column in a decompiled query. As long as we qualify all 182 * column references, per-RTE uniqueness is sufficient for that. 183 * 184 * However, we can't ensure per-column name uniqueness for unnamed join RTEs, 185 * since they just inherit column names from their input RTEs, and we can't 186 * rename the columns at the join level. Most of the time this isn't an issue 187 * because we don't need to reference the join's output columns as such; we 188 * can reference the input columns instead. That approach can fail for merged 189 * JOIN USING columns, however, so when we have one of those in an unnamed 190 * join, we have to make that column's alias globally unique across the whole 191 * query to ensure it can be referenced unambiguously. 192 * 193 * Another problem is that a JOIN USING clause requires the columns to be 194 * merged to have the same aliases in both input RTEs, and that no other 195 * columns in those RTEs or their children conflict with the USING names. 196 * To handle that, we do USING-column alias assignment in a recursive 197 * traversal of the query's jointree. When descending through a JOIN with 198 * USING, we preassign the USING column names to the child columns, overriding 199 * other rules for column alias assignment. We also mark each RTE with a list 200 * of all USING column names selected for joins containing that RTE, so that 201 * when we assign other columns' aliases later, we can avoid conflicts. 202 * 203 * Another problem is that if a JOIN's input tables have had columns added or 204 * deleted since the query was parsed, we must generate a column alias list 205 * for the join that matches the current set of input columns --- otherwise, a 206 * change in the number of columns in the left input would throw off matching 207 * of aliases to columns of the right input. Thus, positions in the printable 208 * column alias list are not necessarily one-for-one with varattnos of the 209 * JOIN, so we need a separate new_colnames[] array for printing purposes. 210 */ 211 typedef struct 212 { 213 /* 214 * colnames is an array containing column aliases to use for columns that 215 * existed when the query was parsed. Dropped columns have NULL entries. 216 * This array can be directly indexed by varattno to get a Var's name. 217 * 218 * Non-NULL entries are guaranteed unique within the RTE, *except* when 219 * this is for an unnamed JOIN RTE. In that case we merely copy up names 220 * from the two input RTEs. 221 * 222 * During the recursive descent in set_using_names(), forcible assignment 223 * of a child RTE's column name is represented by pre-setting that element 224 * of the child's colnames array. So at that stage, NULL entries in this 225 * array just mean that no name has been preassigned, not necessarily that 226 * the column is dropped. 227 */ 228 int num_cols; /* length of colnames[] array */ 229 char **colnames; /* array of C strings and NULLs */ 230 231 /* 232 * new_colnames is an array containing column aliases to use for columns 233 * that would exist if the query was re-parsed against the current 234 * definitions of its base tables. This is what to print as the column 235 * alias list for the RTE. This array does not include dropped columns, 236 * but it will include columns added since original parsing. Indexes in 237 * it therefore have little to do with current varattno values. As above, 238 * entries are unique unless this is for an unnamed JOIN RTE. (In such an 239 * RTE, we never actually print this array, but we must compute it anyway 240 * for possible use in computing column names of upper joins.) The 241 * parallel array is_new_col marks which of these columns are new since 242 * original parsing. Entries with is_new_col false must match the 243 * non-NULL colnames entries one-for-one. 244 */ 245 int num_new_cols; /* length of new_colnames[] array */ 246 char **new_colnames; /* array of C strings */ 247 bool *is_new_col; /* array of bool flags */ 248 249 /* This flag tells whether we should actually print a column alias list */ 250 bool printaliases; 251 252 /* This list has all names used as USING names in joins above this RTE */ 253 List *parentUsing; /* names assigned to parent merged columns */ 254 255 /* 256 * If this struct is for a JOIN RTE, we fill these fields during the 257 * set_using_names() pass to describe its relationship to its child RTEs. 258 * 259 * leftattnos and rightattnos are arrays with one entry per existing 260 * output column of the join (hence, indexable by join varattno). For a 261 * simple reference to a column of the left child, leftattnos[i] is the 262 * child RTE's attno and rightattnos[i] is zero; and conversely for a 263 * column of the right child. But for merged columns produced by JOIN 264 * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero. 265 * Also, if the column has been dropped, both are zero. 266 * 267 * If it's a JOIN USING, usingNames holds the alias names selected for the 268 * merged columns (these might be different from the original USING list, 269 * if we had to modify names to achieve uniqueness). 270 */ 271 int leftrti; /* rangetable index of left child */ 272 int rightrti; /* rangetable index of right child */ 273 int *leftattnos; /* left-child varattnos of join cols, or 0 */ 274 int *rightattnos; /* right-child varattnos of join cols, or 0 */ 275 List *usingNames; /* names assigned to merged columns */ 276 } deparse_columns; 277 278 /* This macro is analogous to rt_fetch(), but for deparse_columns structs */ 279 #define deparse_columns_fetch(rangetable_index, dpns) \ 280 ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1)) 281 282 /* 283 * Entry in set_rtable_names' hash table 284 */ 285 typedef struct 286 { 287 char name[NAMEDATALEN]; /* Hash key --- must be first */ 288 int counter; /* Largest addition used so far for name */ 289 } NameHashEntry; 290 291 292 /* ---------- 293 * Global data 294 * ---------- 295 */ 296 static SPIPlanPtr plan_getrulebyoid = NULL; 297 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1"; 298 static SPIPlanPtr plan_getviewrule = NULL; 299 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2"; 300 301 /* GUC parameters */ 302 bool quote_all_identifiers = false; 303 304 305 /* ---------- 306 * Local functions 307 * 308 * Most of these functions used to use fixed-size buffers to build their 309 * results. Now, they take an (already initialized) StringInfo object 310 * as a parameter, and append their text output to its contents. 311 * ---------- 312 */ 313 static char *deparse_expression_pretty(Node *expr, List *dpcontext, 314 bool forceprefix, bool showimplicit, 315 int prettyFlags, int startIndent); 316 static char *pg_get_viewdef_worker(Oid viewoid, 317 int prettyFlags, int wrapColumn); 318 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty); 319 static int decompile_column_index_array(Datum column_index_array, Oid relId, 320 StringInfo buf); 321 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags); 322 static char *pg_get_indexdef_worker(Oid indexrelid, int colno, 323 const Oid *excludeOps, 324 bool attrsOnly, bool keysOnly, 325 bool showTblSpc, bool inherits, 326 int prettyFlags, bool missing_ok); 327 static char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok); 328 static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags, 329 bool attrsOnly, bool missing_ok); 330 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, 331 int prettyFlags, bool missing_ok); 332 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname, 333 int prettyFlags); 334 static int print_function_arguments(StringInfo buf, HeapTuple proctup, 335 bool print_table_args, bool print_defaults); 336 static void print_function_rettype(StringInfo buf, HeapTuple proctup); 337 static void print_function_trftypes(StringInfo buf, HeapTuple proctup); 338 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, 339 Bitmapset *rels_used); 340 static void set_deparse_for_query(deparse_namespace *dpns, Query *query, 341 List *parent_namespaces); 342 static void set_simple_column_names(deparse_namespace *dpns); 343 static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode); 344 static void set_using_names(deparse_namespace *dpns, Node *jtnode, 345 List *parentUsing); 346 static void set_relation_column_names(deparse_namespace *dpns, 347 RangeTblEntry *rte, 348 deparse_columns *colinfo); 349 static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, 350 deparse_columns *colinfo); 351 static bool colname_is_unique(const char *colname, deparse_namespace *dpns, 352 deparse_columns *colinfo); 353 static char *make_colname_unique(char *colname, deparse_namespace *dpns, 354 deparse_columns *colinfo); 355 static void expand_colnames_array_to(deparse_columns *colinfo, int n); 356 static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, 357 deparse_columns *colinfo); 358 static void flatten_join_using_qual(Node *qual, 359 List **leftvars, List **rightvars); 360 static char *get_rtable_name(int rtindex, deparse_context *context); 361 static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); 362 static void push_child_plan(deparse_namespace *dpns, PlanState *ps, 363 deparse_namespace *save_dpns); 364 static void pop_child_plan(deparse_namespace *dpns, 365 deparse_namespace *save_dpns); 366 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, 367 deparse_namespace *save_dpns); 368 static void pop_ancestor_plan(deparse_namespace *dpns, 369 deparse_namespace *save_dpns); 370 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, 371 int prettyFlags); 372 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, 373 int prettyFlags, int wrapColumn); 374 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, 375 TupleDesc resultDesc, 376 int prettyFlags, int wrapColumn, int startIndent); 377 static void get_values_def(List *values_lists, deparse_context *context); 378 static void get_with_clause(Query *query, deparse_context *context); 379 static void get_select_query_def(Query *query, deparse_context *context, 380 TupleDesc resultDesc); 381 static void get_insert_query_def(Query *query, deparse_context *context); 382 static void get_update_query_def(Query *query, deparse_context *context); 383 static void get_update_query_targetlist_def(Query *query, List *targetList, 384 deparse_context *context, 385 RangeTblEntry *rte); 386 static void get_delete_query_def(Query *query, deparse_context *context); 387 static void get_utility_query_def(Query *query, deparse_context *context); 388 static void get_basic_select_query(Query *query, deparse_context *context, 389 TupleDesc resultDesc); 390 static void get_target_list(List *targetList, deparse_context *context, 391 TupleDesc resultDesc); 392 static void get_setop_query(Node *setOp, Query *query, 393 deparse_context *context, 394 TupleDesc resultDesc); 395 static Node *get_rule_sortgroupclause(Index ref, List *tlist, 396 bool force_colno, 397 deparse_context *context); 398 static void get_rule_groupingset(GroupingSet *gset, List *targetlist, 399 bool omit_parens, deparse_context *context); 400 static void get_rule_orderby(List *orderList, List *targetList, 401 bool force_colno, deparse_context *context); 402 static void get_rule_windowclause(Query *query, deparse_context *context); 403 static void get_rule_windowspec(WindowClause *wc, List *targetList, 404 deparse_context *context); 405 static char *get_variable(Var *var, int levelsup, bool istoplevel, 406 deparse_context *context); 407 static void get_special_variable(Node *node, deparse_context *context, 408 void *private); 409 static void resolve_special_varno(Node *node, deparse_context *context, 410 void *private, 411 void (*callback) (Node *, deparse_context *, void *)); 412 static Node *find_param_referent(Param *param, deparse_context *context, 413 deparse_namespace **dpns_p, ListCell **ancestor_cell_p); 414 static void get_parameter(Param *param, deparse_context *context); 415 static const char *get_simple_binary_op_name(OpExpr *expr); 416 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags); 417 static void appendContextKeyword(deparse_context *context, const char *str, 418 int indentBefore, int indentAfter, int indentPlus); 419 static void removeStringInfoSpaces(StringInfo str); 420 static void get_rule_expr(Node *node, deparse_context *context, 421 bool showimplicit); 422 static void get_rule_expr_toplevel(Node *node, deparse_context *context, 423 bool showimplicit); 424 static void get_rule_expr_funccall(Node *node, deparse_context *context, 425 bool showimplicit); 426 static bool looks_like_function(Node *node); 427 static void get_oper_expr(OpExpr *expr, deparse_context *context); 428 static void get_func_expr(FuncExpr *expr, deparse_context *context, 429 bool showimplicit); 430 static void get_agg_expr(Aggref *aggref, deparse_context *context, 431 Aggref *original_aggref); 432 static void get_agg_combine_expr(Node *node, deparse_context *context, 433 void *private); 434 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context); 435 static void get_coercion_expr(Node *arg, deparse_context *context, 436 Oid resulttype, int32 resulttypmod, 437 Node *parentNode); 438 static void get_const_expr(Const *constval, deparse_context *context, 439 int showtype); 440 static void get_const_collation(Const *constval, deparse_context *context); 441 static void simple_quote_literal(StringInfo buf, const char *val); 442 static void get_sublink_expr(SubLink *sublink, deparse_context *context); 443 static void get_tablefunc(TableFunc *tf, deparse_context *context, 444 bool showimplicit); 445 static void get_from_clause(Query *query, const char *prefix, 446 deparse_context *context); 447 static void get_from_clause_item(Node *jtnode, Query *query, 448 deparse_context *context); 449 static void get_column_alias_list(deparse_columns *colinfo, 450 deparse_context *context); 451 static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, 452 deparse_columns *colinfo, 453 deparse_context *context); 454 static void get_tablesample_def(TableSampleClause *tablesample, 455 deparse_context *context); 456 static void get_opclass_name(Oid opclass, Oid actual_datatype, 457 StringInfo buf); 458 static Node *processIndirection(Node *node, deparse_context *context); 459 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context); 460 static char *get_relation_name(Oid relid); 461 static char *generate_relation_name(Oid relid, List *namespaces); 462 static char *generate_qualified_relation_name(Oid relid); 463 static char *generate_function_name(Oid funcid, int nargs, 464 List *argnames, Oid *argtypes, 465 bool has_variadic, bool *use_variadic_p, 466 ParseExprKind special_exprkind); 467 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); 468 static void add_cast_to(StringInfo buf, Oid typid); 469 static char *generate_qualified_type_name(Oid typid); 470 static text *string_to_text(char *str); 471 static char *flatten_reloptions(Oid relid); 472 473 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ") 474 475 476 /* ---------- 477 * get_ruledef - Do it all and return a text 478 * that could be used as a statement 479 * to recreate the rule 480 * ---------- 481 */ 482 Datum 483 pg_get_ruledef(PG_FUNCTION_ARGS) 484 { 485 Oid ruleoid = PG_GETARG_OID(0); 486 int prettyFlags; 487 char *res; 488 489 prettyFlags = PRETTYFLAG_INDENT; 490 491 res = pg_get_ruledef_worker(ruleoid, prettyFlags); 492 493 if (res == NULL) 494 PG_RETURN_NULL(); 495 496 PG_RETURN_TEXT_P(string_to_text(res)); 497 } 498 499 500 Datum 501 pg_get_ruledef_ext(PG_FUNCTION_ARGS) 502 { 503 Oid ruleoid = PG_GETARG_OID(0); 504 bool pretty = PG_GETARG_BOOL(1); 505 int prettyFlags; 506 char *res; 507 508 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 509 510 res = pg_get_ruledef_worker(ruleoid, prettyFlags); 511 512 if (res == NULL) 513 PG_RETURN_NULL(); 514 515 PG_RETURN_TEXT_P(string_to_text(res)); 516 } 517 518 519 static char * 520 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags) 521 { 522 Datum args[1]; 523 char nulls[1]; 524 int spirc; 525 HeapTuple ruletup; 526 TupleDesc rulettc; 527 StringInfoData buf; 528 529 /* 530 * Do this first so that string is alloc'd in outer context not SPI's. 531 */ 532 initStringInfo(&buf); 533 534 /* 535 * Connect to SPI manager 536 */ 537 if (SPI_connect() != SPI_OK_CONNECT) 538 elog(ERROR, "SPI_connect failed"); 539 540 /* 541 * On the first call prepare the plan to lookup pg_rewrite. We read 542 * pg_rewrite over the SPI manager instead of using the syscache to be 543 * checked for read access on pg_rewrite. 544 */ 545 if (plan_getrulebyoid == NULL) 546 { 547 Oid argtypes[1]; 548 SPIPlanPtr plan; 549 550 argtypes[0] = OIDOID; 551 plan = SPI_prepare(query_getrulebyoid, 1, argtypes); 552 if (plan == NULL) 553 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid); 554 SPI_keepplan(plan); 555 plan_getrulebyoid = plan; 556 } 557 558 /* 559 * Get the pg_rewrite tuple for this rule 560 */ 561 args[0] = ObjectIdGetDatum(ruleoid); 562 nulls[0] = ' '; 563 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 0); 564 if (spirc != SPI_OK_SELECT) 565 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid); 566 if (SPI_processed != 1) 567 { 568 /* 569 * There is no tuple data available here, just keep the output buffer 570 * empty. 571 */ 572 } 573 else 574 { 575 /* 576 * Get the rule's definition and put it into executor's memory 577 */ 578 ruletup = SPI_tuptable->vals[0]; 579 rulettc = SPI_tuptable->tupdesc; 580 make_ruledef(&buf, ruletup, rulettc, prettyFlags); 581 } 582 583 /* 584 * Disconnect from SPI manager 585 */ 586 if (SPI_finish() != SPI_OK_FINISH) 587 elog(ERROR, "SPI_finish failed"); 588 589 if (buf.len == 0) 590 return NULL; 591 592 return buf.data; 593 } 594 595 596 /* ---------- 597 * get_viewdef - Mainly the same thing, but we 598 * only return the SELECT part of a view 599 * ---------- 600 */ 601 Datum 602 pg_get_viewdef(PG_FUNCTION_ARGS) 603 { 604 /* By OID */ 605 Oid viewoid = PG_GETARG_OID(0); 606 int prettyFlags; 607 char *res; 608 609 prettyFlags = PRETTYFLAG_INDENT; 610 611 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT); 612 613 if (res == NULL) 614 PG_RETURN_NULL(); 615 616 PG_RETURN_TEXT_P(string_to_text(res)); 617 } 618 619 620 Datum 621 pg_get_viewdef_ext(PG_FUNCTION_ARGS) 622 { 623 /* By OID */ 624 Oid viewoid = PG_GETARG_OID(0); 625 bool pretty = PG_GETARG_BOOL(1); 626 int prettyFlags; 627 char *res; 628 629 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 630 631 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT); 632 633 if (res == NULL) 634 PG_RETURN_NULL(); 635 636 PG_RETURN_TEXT_P(string_to_text(res)); 637 } 638 639 Datum 640 pg_get_viewdef_wrap(PG_FUNCTION_ARGS) 641 { 642 /* By OID */ 643 Oid viewoid = PG_GETARG_OID(0); 644 int wrap = PG_GETARG_INT32(1); 645 int prettyFlags; 646 char *res; 647 648 /* calling this implies we want pretty printing */ 649 prettyFlags = PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA; 650 651 res = pg_get_viewdef_worker(viewoid, prettyFlags, wrap); 652 653 if (res == NULL) 654 PG_RETURN_NULL(); 655 656 PG_RETURN_TEXT_P(string_to_text(res)); 657 } 658 659 Datum 660 pg_get_viewdef_name(PG_FUNCTION_ARGS) 661 { 662 /* By qualified name */ 663 text *viewname = PG_GETARG_TEXT_PP(0); 664 int prettyFlags; 665 RangeVar *viewrel; 666 Oid viewoid; 667 char *res; 668 669 prettyFlags = PRETTYFLAG_INDENT; 670 671 /* Look up view name. Can't lock it - we might not have privileges. */ 672 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname)); 673 viewoid = RangeVarGetRelid(viewrel, NoLock, false); 674 675 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT); 676 677 if (res == NULL) 678 PG_RETURN_NULL(); 679 680 PG_RETURN_TEXT_P(string_to_text(res)); 681 } 682 683 684 Datum 685 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS) 686 { 687 /* By qualified name */ 688 text *viewname = PG_GETARG_TEXT_PP(0); 689 bool pretty = PG_GETARG_BOOL(1); 690 int prettyFlags; 691 RangeVar *viewrel; 692 Oid viewoid; 693 char *res; 694 695 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 696 697 /* Look up view name. Can't lock it - we might not have privileges. */ 698 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname)); 699 viewoid = RangeVarGetRelid(viewrel, NoLock, false); 700 701 res = pg_get_viewdef_worker(viewoid, prettyFlags, WRAP_COLUMN_DEFAULT); 702 703 if (res == NULL) 704 PG_RETURN_NULL(); 705 706 PG_RETURN_TEXT_P(string_to_text(res)); 707 } 708 709 /* 710 * Common code for by-OID and by-name variants of pg_get_viewdef 711 */ 712 static char * 713 pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn) 714 { 715 Datum args[2]; 716 char nulls[2]; 717 int spirc; 718 HeapTuple ruletup; 719 TupleDesc rulettc; 720 StringInfoData buf; 721 722 /* 723 * Do this first so that string is alloc'd in outer context not SPI's. 724 */ 725 initStringInfo(&buf); 726 727 /* 728 * Connect to SPI manager 729 */ 730 if (SPI_connect() != SPI_OK_CONNECT) 731 elog(ERROR, "SPI_connect failed"); 732 733 /* 734 * On the first call prepare the plan to lookup pg_rewrite. We read 735 * pg_rewrite over the SPI manager instead of using the syscache to be 736 * checked for read access on pg_rewrite. 737 */ 738 if (plan_getviewrule == NULL) 739 { 740 Oid argtypes[2]; 741 SPIPlanPtr plan; 742 743 argtypes[0] = OIDOID; 744 argtypes[1] = NAMEOID; 745 plan = SPI_prepare(query_getviewrule, 2, argtypes); 746 if (plan == NULL) 747 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule); 748 SPI_keepplan(plan); 749 plan_getviewrule = plan; 750 } 751 752 /* 753 * Get the pg_rewrite tuple for the view's SELECT rule 754 */ 755 args[0] = ObjectIdGetDatum(viewoid); 756 args[1] = DirectFunctionCall1(namein, CStringGetDatum(ViewSelectRuleName)); 757 nulls[0] = ' '; 758 nulls[1] = ' '; 759 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 0); 760 if (spirc != SPI_OK_SELECT) 761 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid); 762 if (SPI_processed != 1) 763 { 764 /* 765 * There is no tuple data available here, just keep the output buffer 766 * empty. 767 */ 768 } 769 else 770 { 771 /* 772 * Get the rule's definition and put it into executor's memory 773 */ 774 ruletup = SPI_tuptable->vals[0]; 775 rulettc = SPI_tuptable->tupdesc; 776 make_viewdef(&buf, ruletup, rulettc, prettyFlags, wrapColumn); 777 } 778 779 /* 780 * Disconnect from SPI manager 781 */ 782 if (SPI_finish() != SPI_OK_FINISH) 783 elog(ERROR, "SPI_finish failed"); 784 785 if (buf.len == 0) 786 return NULL; 787 788 return buf.data; 789 } 790 791 /* ---------- 792 * get_triggerdef - Get the definition of a trigger 793 * ---------- 794 */ 795 Datum 796 pg_get_triggerdef(PG_FUNCTION_ARGS) 797 { 798 Oid trigid = PG_GETARG_OID(0); 799 char *res; 800 801 res = pg_get_triggerdef_worker(trigid, false); 802 803 if (res == NULL) 804 PG_RETURN_NULL(); 805 806 PG_RETURN_TEXT_P(string_to_text(res)); 807 } 808 809 Datum 810 pg_get_triggerdef_ext(PG_FUNCTION_ARGS) 811 { 812 Oid trigid = PG_GETARG_OID(0); 813 bool pretty = PG_GETARG_BOOL(1); 814 char *res; 815 816 res = pg_get_triggerdef_worker(trigid, pretty); 817 818 if (res == NULL) 819 PG_RETURN_NULL(); 820 821 PG_RETURN_TEXT_P(string_to_text(res)); 822 } 823 824 static char * 825 pg_get_triggerdef_worker(Oid trigid, bool pretty) 826 { 827 HeapTuple ht_trig; 828 Form_pg_trigger trigrec; 829 StringInfoData buf; 830 Relation tgrel; 831 ScanKeyData skey[1]; 832 SysScanDesc tgscan; 833 int findx = 0; 834 char *tgname; 835 char *tgoldtable; 836 char *tgnewtable; 837 Oid argtypes[1]; /* dummy */ 838 Datum value; 839 bool isnull; 840 841 /* 842 * Fetch the pg_trigger tuple by the Oid of the trigger 843 */ 844 tgrel = table_open(TriggerRelationId, AccessShareLock); 845 846 ScanKeyInit(&skey[0], 847 Anum_pg_trigger_oid, 848 BTEqualStrategyNumber, F_OIDEQ, 849 ObjectIdGetDatum(trigid)); 850 851 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true, 852 NULL, 1, skey); 853 854 ht_trig = systable_getnext(tgscan); 855 856 if (!HeapTupleIsValid(ht_trig)) 857 { 858 systable_endscan(tgscan); 859 table_close(tgrel, AccessShareLock); 860 return NULL; 861 } 862 863 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig); 864 865 /* 866 * Start the trigger definition. Note that the trigger's name should never 867 * be schema-qualified, but the trigger rel's name may be. 868 */ 869 initStringInfo(&buf); 870 871 tgname = NameStr(trigrec->tgname); 872 appendStringInfo(&buf, "CREATE %sTRIGGER %s ", 873 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "", 874 quote_identifier(tgname)); 875 876 if (TRIGGER_FOR_BEFORE(trigrec->tgtype)) 877 appendStringInfoString(&buf, "BEFORE"); 878 else if (TRIGGER_FOR_AFTER(trigrec->tgtype)) 879 appendStringInfoString(&buf, "AFTER"); 880 else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype)) 881 appendStringInfoString(&buf, "INSTEAD OF"); 882 else 883 elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype); 884 885 if (TRIGGER_FOR_INSERT(trigrec->tgtype)) 886 { 887 appendStringInfoString(&buf, " INSERT"); 888 findx++; 889 } 890 if (TRIGGER_FOR_DELETE(trigrec->tgtype)) 891 { 892 if (findx > 0) 893 appendStringInfoString(&buf, " OR DELETE"); 894 else 895 appendStringInfoString(&buf, " DELETE"); 896 findx++; 897 } 898 if (TRIGGER_FOR_UPDATE(trigrec->tgtype)) 899 { 900 if (findx > 0) 901 appendStringInfoString(&buf, " OR UPDATE"); 902 else 903 appendStringInfoString(&buf, " UPDATE"); 904 findx++; 905 /* tgattr is first var-width field, so OK to access directly */ 906 if (trigrec->tgattr.dim1 > 0) 907 { 908 int i; 909 910 appendStringInfoString(&buf, " OF "); 911 for (i = 0; i < trigrec->tgattr.dim1; i++) 912 { 913 char *attname; 914 915 if (i > 0) 916 appendStringInfoString(&buf, ", "); 917 attname = get_attname(trigrec->tgrelid, 918 trigrec->tgattr.values[i], false); 919 appendStringInfoString(&buf, quote_identifier(attname)); 920 } 921 } 922 } 923 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype)) 924 { 925 if (findx > 0) 926 appendStringInfoString(&buf, " OR TRUNCATE"); 927 else 928 appendStringInfoString(&buf, " TRUNCATE"); 929 findx++; 930 } 931 932 /* 933 * In non-pretty mode, always schema-qualify the target table name for 934 * safety. In pretty mode, schema-qualify only if not visible. 935 */ 936 appendStringInfo(&buf, " ON %s ", 937 pretty ? 938 generate_relation_name(trigrec->tgrelid, NIL) : 939 generate_qualified_relation_name(trigrec->tgrelid)); 940 941 if (OidIsValid(trigrec->tgconstraint)) 942 { 943 if (OidIsValid(trigrec->tgconstrrelid)) 944 appendStringInfo(&buf, "FROM %s ", 945 generate_relation_name(trigrec->tgconstrrelid, NIL)); 946 if (!trigrec->tgdeferrable) 947 appendStringInfoString(&buf, "NOT "); 948 appendStringInfoString(&buf, "DEFERRABLE INITIALLY "); 949 if (trigrec->tginitdeferred) 950 appendStringInfoString(&buf, "DEFERRED "); 951 else 952 appendStringInfoString(&buf, "IMMEDIATE "); 953 } 954 955 value = fastgetattr(ht_trig, Anum_pg_trigger_tgoldtable, 956 tgrel->rd_att, &isnull); 957 if (!isnull) 958 tgoldtable = NameStr(*DatumGetName(value)); 959 else 960 tgoldtable = NULL; 961 value = fastgetattr(ht_trig, Anum_pg_trigger_tgnewtable, 962 tgrel->rd_att, &isnull); 963 if (!isnull) 964 tgnewtable = NameStr(*DatumGetName(value)); 965 else 966 tgnewtable = NULL; 967 if (tgoldtable != NULL || tgnewtable != NULL) 968 { 969 appendStringInfoString(&buf, "REFERENCING "); 970 if (tgoldtable != NULL) 971 appendStringInfo(&buf, "OLD TABLE AS %s ", 972 quote_identifier(tgoldtable)); 973 if (tgnewtable != NULL) 974 appendStringInfo(&buf, "NEW TABLE AS %s ", 975 quote_identifier(tgnewtable)); 976 } 977 978 if (TRIGGER_FOR_ROW(trigrec->tgtype)) 979 appendStringInfoString(&buf, "FOR EACH ROW "); 980 else 981 appendStringInfoString(&buf, "FOR EACH STATEMENT "); 982 983 /* If the trigger has a WHEN qualification, add that */ 984 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual, 985 tgrel->rd_att, &isnull); 986 if (!isnull) 987 { 988 Node *qual; 989 char relkind; 990 deparse_context context; 991 deparse_namespace dpns; 992 RangeTblEntry *oldrte; 993 RangeTblEntry *newrte; 994 995 appendStringInfoString(&buf, "WHEN ("); 996 997 qual = stringToNode(TextDatumGetCString(value)); 998 999 relkind = get_rel_relkind(trigrec->tgrelid); 1000 1001 /* Build minimal OLD and NEW RTEs for the rel */ 1002 oldrte = makeNode(RangeTblEntry); 1003 oldrte->rtekind = RTE_RELATION; 1004 oldrte->relid = trigrec->tgrelid; 1005 oldrte->relkind = relkind; 1006 oldrte->rellockmode = AccessShareLock; 1007 oldrte->alias = makeAlias("old", NIL); 1008 oldrte->eref = oldrte->alias; 1009 oldrte->lateral = false; 1010 oldrte->inh = false; 1011 oldrte->inFromCl = true; 1012 1013 newrte = makeNode(RangeTblEntry); 1014 newrte->rtekind = RTE_RELATION; 1015 newrte->relid = trigrec->tgrelid; 1016 newrte->relkind = relkind; 1017 newrte->rellockmode = AccessShareLock; 1018 newrte->alias = makeAlias("new", NIL); 1019 newrte->eref = newrte->alias; 1020 newrte->lateral = false; 1021 newrte->inh = false; 1022 newrte->inFromCl = true; 1023 1024 /* Build two-element rtable */ 1025 memset(&dpns, 0, sizeof(dpns)); 1026 dpns.rtable = list_make2(oldrte, newrte); 1027 dpns.ctes = NIL; 1028 set_rtable_names(&dpns, NIL, NULL); 1029 set_simple_column_names(&dpns); 1030 1031 /* Set up context with one-deep namespace stack */ 1032 context.buf = &buf; 1033 context.namespaces = list_make1(&dpns); 1034 context.windowClause = NIL; 1035 context.windowTList = NIL; 1036 context.varprefix = true; 1037 context.prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 1038 context.wrapColumn = WRAP_COLUMN_DEFAULT; 1039 context.indentLevel = PRETTYINDENT_STD; 1040 context.special_exprkind = EXPR_KIND_NONE; 1041 1042 get_rule_expr(qual, &context, false); 1043 1044 appendStringInfoString(&buf, ") "); 1045 } 1046 1047 appendStringInfo(&buf, "EXECUTE FUNCTION %s(", 1048 generate_function_name(trigrec->tgfoid, 0, 1049 NIL, argtypes, 1050 false, NULL, EXPR_KIND_NONE)); 1051 1052 if (trigrec->tgnargs > 0) 1053 { 1054 char *p; 1055 int i; 1056 1057 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs, 1058 tgrel->rd_att, &isnull); 1059 if (isnull) 1060 elog(ERROR, "tgargs is null for trigger %u", trigid); 1061 p = (char *) VARDATA_ANY(DatumGetByteaPP(value)); 1062 for (i = 0; i < trigrec->tgnargs; i++) 1063 { 1064 if (i > 0) 1065 appendStringInfoString(&buf, ", "); 1066 simple_quote_literal(&buf, p); 1067 /* advance p to next string embedded in tgargs */ 1068 while (*p) 1069 p++; 1070 p++; 1071 } 1072 } 1073 1074 /* We deliberately do not put semi-colon at end */ 1075 appendStringInfoChar(&buf, ')'); 1076 1077 /* Clean up */ 1078 systable_endscan(tgscan); 1079 1080 table_close(tgrel, AccessShareLock); 1081 1082 return buf.data; 1083 } 1084 1085 /* ---------- 1086 * get_indexdef - Get the definition of an index 1087 * 1088 * In the extended version, there is a colno argument as well as pretty bool. 1089 * if colno == 0, we want a complete index definition. 1090 * if colno > 0, we only want the Nth index key's variable or expression. 1091 * 1092 * Note that the SQL-function versions of this omit any info about the 1093 * index tablespace; this is intentional because pg_dump wants it that way. 1094 * However pg_get_indexdef_string() includes the index tablespace. 1095 * ---------- 1096 */ 1097 Datum 1098 pg_get_indexdef(PG_FUNCTION_ARGS) 1099 { 1100 Oid indexrelid = PG_GETARG_OID(0); 1101 int prettyFlags; 1102 char *res; 1103 1104 prettyFlags = PRETTYFLAG_INDENT; 1105 1106 res = pg_get_indexdef_worker(indexrelid, 0, NULL, 1107 false, false, 1108 false, false, 1109 prettyFlags, true); 1110 1111 if (res == NULL) 1112 PG_RETURN_NULL(); 1113 1114 PG_RETURN_TEXT_P(string_to_text(res)); 1115 } 1116 1117 Datum 1118 pg_get_indexdef_ext(PG_FUNCTION_ARGS) 1119 { 1120 Oid indexrelid = PG_GETARG_OID(0); 1121 int32 colno = PG_GETARG_INT32(1); 1122 bool pretty = PG_GETARG_BOOL(2); 1123 int prettyFlags; 1124 char *res; 1125 1126 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 1127 1128 res = pg_get_indexdef_worker(indexrelid, colno, NULL, 1129 colno != 0, false, 1130 false, false, 1131 prettyFlags, true); 1132 1133 if (res == NULL) 1134 PG_RETURN_NULL(); 1135 1136 PG_RETURN_TEXT_P(string_to_text(res)); 1137 } 1138 1139 /* 1140 * Internal version for use by ALTER TABLE. 1141 * Includes a tablespace clause in the result. 1142 * Returns a palloc'd C string; no pretty-printing. 1143 */ 1144 char * 1145 pg_get_indexdef_string(Oid indexrelid) 1146 { 1147 return pg_get_indexdef_worker(indexrelid, 0, NULL, 1148 false, false, 1149 true, true, 1150 0, false); 1151 } 1152 1153 /* Internal version that just reports the key-column definitions */ 1154 char * 1155 pg_get_indexdef_columns(Oid indexrelid, bool pretty) 1156 { 1157 int prettyFlags; 1158 1159 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 1160 1161 return pg_get_indexdef_worker(indexrelid, 0, NULL, 1162 true, true, 1163 false, false, 1164 prettyFlags, false); 1165 } 1166 1167 /* 1168 * Internal workhorse to decompile an index definition. 1169 * 1170 * This is now used for exclusion constraints as well: if excludeOps is not 1171 * NULL then it points to an array of exclusion operator OIDs. 1172 */ 1173 static char * 1174 pg_get_indexdef_worker(Oid indexrelid, int colno, 1175 const Oid *excludeOps, 1176 bool attrsOnly, bool keysOnly, 1177 bool showTblSpc, bool inherits, 1178 int prettyFlags, bool missing_ok) 1179 { 1180 /* might want a separate isConstraint parameter later */ 1181 bool isConstraint = (excludeOps != NULL); 1182 HeapTuple ht_idx; 1183 HeapTuple ht_idxrel; 1184 HeapTuple ht_am; 1185 Form_pg_index idxrec; 1186 Form_pg_class idxrelrec; 1187 Form_pg_am amrec; 1188 IndexAmRoutine *amroutine; 1189 List *indexprs; 1190 ListCell *indexpr_item; 1191 List *context; 1192 Oid indrelid; 1193 int keyno; 1194 Datum indcollDatum; 1195 Datum indclassDatum; 1196 Datum indoptionDatum; 1197 bool isnull; 1198 oidvector *indcollation; 1199 oidvector *indclass; 1200 int2vector *indoption; 1201 StringInfoData buf; 1202 char *str; 1203 char *sep; 1204 1205 /* 1206 * Fetch the pg_index tuple by the Oid of the index 1207 */ 1208 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid)); 1209 if (!HeapTupleIsValid(ht_idx)) 1210 { 1211 if (missing_ok) 1212 return NULL; 1213 elog(ERROR, "cache lookup failed for index %u", indexrelid); 1214 } 1215 idxrec = (Form_pg_index) GETSTRUCT(ht_idx); 1216 1217 indrelid = idxrec->indrelid; 1218 Assert(indexrelid == idxrec->indexrelid); 1219 1220 /* Must get indcollation, indclass, and indoption the hard way */ 1221 indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx, 1222 Anum_pg_index_indcollation, &isnull); 1223 Assert(!isnull); 1224 indcollation = (oidvector *) DatumGetPointer(indcollDatum); 1225 1226 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx, 1227 Anum_pg_index_indclass, &isnull); 1228 Assert(!isnull); 1229 indclass = (oidvector *) DatumGetPointer(indclassDatum); 1230 1231 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx, 1232 Anum_pg_index_indoption, &isnull); 1233 Assert(!isnull); 1234 indoption = (int2vector *) DatumGetPointer(indoptionDatum); 1235 1236 /* 1237 * Fetch the pg_class tuple of the index relation 1238 */ 1239 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid)); 1240 if (!HeapTupleIsValid(ht_idxrel)) 1241 elog(ERROR, "cache lookup failed for relation %u", indexrelid); 1242 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel); 1243 1244 /* 1245 * Fetch the pg_am tuple of the index' access method 1246 */ 1247 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam)); 1248 if (!HeapTupleIsValid(ht_am)) 1249 elog(ERROR, "cache lookup failed for access method %u", 1250 idxrelrec->relam); 1251 amrec = (Form_pg_am) GETSTRUCT(ht_am); 1252 1253 /* Fetch the index AM's API struct */ 1254 amroutine = GetIndexAmRoutine(amrec->amhandler); 1255 1256 /* 1257 * Get the index expressions, if any. (NOTE: we do not use the relcache 1258 * versions of the expressions and predicate, because we want to display 1259 * non-const-folded expressions.) 1260 */ 1261 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL)) 1262 { 1263 Datum exprsDatum; 1264 bool isnull; 1265 char *exprsString; 1266 1267 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx, 1268 Anum_pg_index_indexprs, &isnull); 1269 Assert(!isnull); 1270 exprsString = TextDatumGetCString(exprsDatum); 1271 indexprs = (List *) stringToNode(exprsString); 1272 pfree(exprsString); 1273 } 1274 else 1275 indexprs = NIL; 1276 1277 indexpr_item = list_head(indexprs); 1278 1279 context = deparse_context_for(get_relation_name(indrelid), indrelid); 1280 1281 /* 1282 * Start the index definition. Note that the index's name should never be 1283 * schema-qualified, but the indexed rel's name may be. 1284 */ 1285 initStringInfo(&buf); 1286 1287 if (!attrsOnly) 1288 { 1289 if (!isConstraint) 1290 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s%s USING %s (", 1291 idxrec->indisunique ? "UNIQUE " : "", 1292 quote_identifier(NameStr(idxrelrec->relname)), 1293 idxrelrec->relkind == RELKIND_PARTITIONED_INDEX 1294 && !inherits ? "ONLY " : "", 1295 (prettyFlags & PRETTYFLAG_SCHEMA) ? 1296 generate_relation_name(indrelid, NIL) : 1297 generate_qualified_relation_name(indrelid), 1298 quote_identifier(NameStr(amrec->amname))); 1299 else /* currently, must be EXCLUDE constraint */ 1300 appendStringInfo(&buf, "EXCLUDE USING %s (", 1301 quote_identifier(NameStr(amrec->amname))); 1302 } 1303 1304 /* 1305 * Report the indexed attributes 1306 */ 1307 sep = ""; 1308 for (keyno = 0; keyno < idxrec->indnatts; keyno++) 1309 { 1310 AttrNumber attnum = idxrec->indkey.values[keyno]; 1311 Oid keycoltype; 1312 Oid keycolcollation; 1313 1314 /* 1315 * Ignore non-key attributes if told to. 1316 */ 1317 if (keysOnly && keyno >= idxrec->indnkeyatts) 1318 break; 1319 1320 /* Otherwise, print INCLUDE to divide key and non-key attrs. */ 1321 if (!colno && keyno == idxrec->indnkeyatts) 1322 { 1323 appendStringInfoString(&buf, ") INCLUDE ("); 1324 sep = ""; 1325 } 1326 1327 if (!colno) 1328 appendStringInfoString(&buf, sep); 1329 sep = ", "; 1330 1331 if (attnum != 0) 1332 { 1333 /* Simple index column */ 1334 char *attname; 1335 int32 keycoltypmod; 1336 1337 attname = get_attname(indrelid, attnum, false); 1338 if (!colno || colno == keyno + 1) 1339 appendStringInfoString(&buf, quote_identifier(attname)); 1340 get_atttypetypmodcoll(indrelid, attnum, 1341 &keycoltype, &keycoltypmod, 1342 &keycolcollation); 1343 } 1344 else 1345 { 1346 /* expressional index */ 1347 Node *indexkey; 1348 1349 if (indexpr_item == NULL) 1350 elog(ERROR, "too few entries in indexprs list"); 1351 indexkey = (Node *) lfirst(indexpr_item); 1352 indexpr_item = lnext(indexpr_item); 1353 /* Deparse */ 1354 str = deparse_expression_pretty(indexkey, context, false, false, 1355 prettyFlags, 0); 1356 if (!colno || colno == keyno + 1) 1357 { 1358 /* Need parens if it's not a bare function call */ 1359 if (looks_like_function(indexkey)) 1360 appendStringInfoString(&buf, str); 1361 else 1362 appendStringInfo(&buf, "(%s)", str); 1363 } 1364 keycoltype = exprType(indexkey); 1365 keycolcollation = exprCollation(indexkey); 1366 } 1367 1368 /* Print additional decoration for (selected) key columns */ 1369 if (!attrsOnly && keyno < idxrec->indnkeyatts && 1370 (!colno || colno == keyno + 1)) 1371 { 1372 int16 opt = indoption->values[keyno]; 1373 Oid indcoll = indcollation->values[keyno]; 1374 1375 /* Add collation, if not default for column */ 1376 if (OidIsValid(indcoll) && indcoll != keycolcollation) 1377 appendStringInfo(&buf, " COLLATE %s", 1378 generate_collation_name((indcoll))); 1379 1380 /* Add the operator class name, if not default */ 1381 get_opclass_name(indclass->values[keyno], keycoltype, &buf); 1382 1383 /* Add options if relevant */ 1384 if (amroutine->amcanorder) 1385 { 1386 /* if it supports sort ordering, report DESC and NULLS opts */ 1387 if (opt & INDOPTION_DESC) 1388 { 1389 appendStringInfoString(&buf, " DESC"); 1390 /* NULLS FIRST is the default in this case */ 1391 if (!(opt & INDOPTION_NULLS_FIRST)) 1392 appendStringInfoString(&buf, " NULLS LAST"); 1393 } 1394 else 1395 { 1396 if (opt & INDOPTION_NULLS_FIRST) 1397 appendStringInfoString(&buf, " NULLS FIRST"); 1398 } 1399 } 1400 1401 /* Add the exclusion operator if relevant */ 1402 if (excludeOps != NULL) 1403 appendStringInfo(&buf, " WITH %s", 1404 generate_operator_name(excludeOps[keyno], 1405 keycoltype, 1406 keycoltype)); 1407 } 1408 } 1409 1410 if (!attrsOnly) 1411 { 1412 appendStringInfoChar(&buf, ')'); 1413 1414 /* 1415 * If it has options, append "WITH (options)" 1416 */ 1417 str = flatten_reloptions(indexrelid); 1418 if (str) 1419 { 1420 appendStringInfo(&buf, " WITH (%s)", str); 1421 pfree(str); 1422 } 1423 1424 /* 1425 * Print tablespace, but only if requested 1426 */ 1427 if (showTblSpc) 1428 { 1429 Oid tblspc; 1430 1431 tblspc = get_rel_tablespace(indexrelid); 1432 if (OidIsValid(tblspc)) 1433 { 1434 if (isConstraint) 1435 appendStringInfoString(&buf, " USING INDEX"); 1436 appendStringInfo(&buf, " TABLESPACE %s", 1437 quote_identifier(get_tablespace_name(tblspc))); 1438 } 1439 } 1440 1441 /* 1442 * If it's a partial index, decompile and append the predicate 1443 */ 1444 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL)) 1445 { 1446 Node *node; 1447 Datum predDatum; 1448 bool isnull; 1449 char *predString; 1450 1451 /* Convert text string to node tree */ 1452 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx, 1453 Anum_pg_index_indpred, &isnull); 1454 Assert(!isnull); 1455 predString = TextDatumGetCString(predDatum); 1456 node = (Node *) stringToNode(predString); 1457 pfree(predString); 1458 1459 /* Deparse */ 1460 str = deparse_expression_pretty(node, context, false, false, 1461 prettyFlags, 0); 1462 if (isConstraint) 1463 appendStringInfo(&buf, " WHERE (%s)", str); 1464 else 1465 appendStringInfo(&buf, " WHERE %s", str); 1466 } 1467 } 1468 1469 /* Clean up */ 1470 ReleaseSysCache(ht_idx); 1471 ReleaseSysCache(ht_idxrel); 1472 ReleaseSysCache(ht_am); 1473 1474 return buf.data; 1475 } 1476 1477 /* 1478 * pg_get_statisticsobjdef 1479 * Get the definition of an extended statistics object 1480 */ 1481 Datum 1482 pg_get_statisticsobjdef(PG_FUNCTION_ARGS) 1483 { 1484 Oid statextid = PG_GETARG_OID(0); 1485 char *res; 1486 1487 res = pg_get_statisticsobj_worker(statextid, true); 1488 1489 if (res == NULL) 1490 PG_RETURN_NULL(); 1491 1492 PG_RETURN_TEXT_P(string_to_text(res)); 1493 } 1494 1495 /* 1496 * Internal workhorse to decompile an extended statistics object. 1497 */ 1498 static char * 1499 pg_get_statisticsobj_worker(Oid statextid, bool missing_ok) 1500 { 1501 Form_pg_statistic_ext statextrec; 1502 HeapTuple statexttup; 1503 StringInfoData buf; 1504 int colno; 1505 char *nsp; 1506 ArrayType *arr; 1507 char *enabled; 1508 Datum datum; 1509 bool isnull; 1510 bool ndistinct_enabled; 1511 bool dependencies_enabled; 1512 bool mcv_enabled; 1513 int i; 1514 1515 statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid)); 1516 1517 if (!HeapTupleIsValid(statexttup)) 1518 { 1519 if (missing_ok) 1520 return NULL; 1521 elog(ERROR, "cache lookup failed for statistics object %u", statextid); 1522 } 1523 1524 statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup); 1525 1526 initStringInfo(&buf); 1527 1528 nsp = get_namespace_name(statextrec->stxnamespace); 1529 appendStringInfo(&buf, "CREATE STATISTICS %s", 1530 quote_qualified_identifier(nsp, 1531 NameStr(statextrec->stxname))); 1532 1533 /* 1534 * Decode the stxkind column so that we know which stats types to print. 1535 */ 1536 datum = SysCacheGetAttr(STATEXTOID, statexttup, 1537 Anum_pg_statistic_ext_stxkind, &isnull); 1538 Assert(!isnull); 1539 arr = DatumGetArrayTypeP(datum); 1540 if (ARR_NDIM(arr) != 1 || 1541 ARR_HASNULL(arr) || 1542 ARR_ELEMTYPE(arr) != CHAROID) 1543 elog(ERROR, "stxkind is not a 1-D char array"); 1544 enabled = (char *) ARR_DATA_PTR(arr); 1545 1546 ndistinct_enabled = false; 1547 dependencies_enabled = false; 1548 mcv_enabled = false; 1549 1550 for (i = 0; i < ARR_DIMS(arr)[0]; i++) 1551 { 1552 if (enabled[i] == STATS_EXT_NDISTINCT) 1553 ndistinct_enabled = true; 1554 if (enabled[i] == STATS_EXT_DEPENDENCIES) 1555 dependencies_enabled = true; 1556 if (enabled[i] == STATS_EXT_MCV) 1557 mcv_enabled = true; 1558 } 1559 1560 /* 1561 * If any option is disabled, then we'll need to append the types clause 1562 * to show which options are enabled. We omit the types clause on purpose 1563 * when all options are enabled, so a pg_dump/pg_restore will create all 1564 * statistics types on a newer postgres version, if the statistics had all 1565 * options enabled on the original version. 1566 */ 1567 if (!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) 1568 { 1569 bool gotone = false; 1570 1571 appendStringInfoString(&buf, " ("); 1572 1573 if (ndistinct_enabled) 1574 { 1575 appendStringInfoString(&buf, "ndistinct"); 1576 gotone = true; 1577 } 1578 1579 if (dependencies_enabled) 1580 { 1581 appendStringInfo(&buf, "%sdependencies", gotone ? ", " : ""); 1582 gotone = true; 1583 } 1584 1585 if (mcv_enabled) 1586 appendStringInfo(&buf, "%smcv", gotone ? ", " : ""); 1587 1588 appendStringInfoChar(&buf, ')'); 1589 } 1590 1591 appendStringInfoString(&buf, " ON "); 1592 1593 for (colno = 0; colno < statextrec->stxkeys.dim1; colno++) 1594 { 1595 AttrNumber attnum = statextrec->stxkeys.values[colno]; 1596 char *attname; 1597 1598 if (colno > 0) 1599 appendStringInfoString(&buf, ", "); 1600 1601 attname = get_attname(statextrec->stxrelid, attnum, false); 1602 1603 appendStringInfoString(&buf, quote_identifier(attname)); 1604 } 1605 1606 appendStringInfo(&buf, " FROM %s", 1607 generate_relation_name(statextrec->stxrelid, NIL)); 1608 1609 ReleaseSysCache(statexttup); 1610 1611 return buf.data; 1612 } 1613 1614 /* 1615 * pg_get_partkeydef 1616 * 1617 * Returns the partition key specification, ie, the following: 1618 * 1619 * PARTITION BY { RANGE | LIST | HASH } (column opt_collation opt_opclass [, ...]) 1620 */ 1621 Datum 1622 pg_get_partkeydef(PG_FUNCTION_ARGS) 1623 { 1624 Oid relid = PG_GETARG_OID(0); 1625 char *res; 1626 1627 res = pg_get_partkeydef_worker(relid, PRETTYFLAG_INDENT, false, true); 1628 1629 if (res == NULL) 1630 PG_RETURN_NULL(); 1631 1632 PG_RETURN_TEXT_P(string_to_text(res)); 1633 } 1634 1635 /* Internal version that just reports the column definitions */ 1636 char * 1637 pg_get_partkeydef_columns(Oid relid, bool pretty) 1638 { 1639 int prettyFlags; 1640 1641 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 1642 1643 return pg_get_partkeydef_worker(relid, prettyFlags, true, false); 1644 } 1645 1646 /* 1647 * Internal workhorse to decompile a partition key definition. 1648 */ 1649 static char * 1650 pg_get_partkeydef_worker(Oid relid, int prettyFlags, 1651 bool attrsOnly, bool missing_ok) 1652 { 1653 Form_pg_partitioned_table form; 1654 HeapTuple tuple; 1655 oidvector *partclass; 1656 oidvector *partcollation; 1657 List *partexprs; 1658 ListCell *partexpr_item; 1659 List *context; 1660 Datum datum; 1661 bool isnull; 1662 StringInfoData buf; 1663 int keyno; 1664 char *str; 1665 char *sep; 1666 1667 tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid)); 1668 if (!HeapTupleIsValid(tuple)) 1669 { 1670 if (missing_ok) 1671 return NULL; 1672 elog(ERROR, "cache lookup failed for partition key of %u", relid); 1673 } 1674 1675 form = (Form_pg_partitioned_table) GETSTRUCT(tuple); 1676 1677 Assert(form->partrelid == relid); 1678 1679 /* Must get partclass and partcollation the hard way */ 1680 datum = SysCacheGetAttr(PARTRELID, tuple, 1681 Anum_pg_partitioned_table_partclass, &isnull); 1682 Assert(!isnull); 1683 partclass = (oidvector *) DatumGetPointer(datum); 1684 1685 datum = SysCacheGetAttr(PARTRELID, tuple, 1686 Anum_pg_partitioned_table_partcollation, &isnull); 1687 Assert(!isnull); 1688 partcollation = (oidvector *) DatumGetPointer(datum); 1689 1690 1691 /* 1692 * Get the expressions, if any. (NOTE: we do not use the relcache 1693 * versions of the expressions, because we want to display 1694 * non-const-folded expressions.) 1695 */ 1696 if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprs, NULL)) 1697 { 1698 Datum exprsDatum; 1699 bool isnull; 1700 char *exprsString; 1701 1702 exprsDatum = SysCacheGetAttr(PARTRELID, tuple, 1703 Anum_pg_partitioned_table_partexprs, &isnull); 1704 Assert(!isnull); 1705 exprsString = TextDatumGetCString(exprsDatum); 1706 partexprs = (List *) stringToNode(exprsString); 1707 1708 if (!IsA(partexprs, List)) 1709 elog(ERROR, "unexpected node type found in partexprs: %d", 1710 (int) nodeTag(partexprs)); 1711 1712 pfree(exprsString); 1713 } 1714 else 1715 partexprs = NIL; 1716 1717 partexpr_item = list_head(partexprs); 1718 context = deparse_context_for(get_relation_name(relid), relid); 1719 1720 initStringInfo(&buf); 1721 1722 switch (form->partstrat) 1723 { 1724 case PARTITION_STRATEGY_HASH: 1725 if (!attrsOnly) 1726 appendStringInfo(&buf, "HASH"); 1727 break; 1728 case PARTITION_STRATEGY_LIST: 1729 if (!attrsOnly) 1730 appendStringInfoString(&buf, "LIST"); 1731 break; 1732 case PARTITION_STRATEGY_RANGE: 1733 if (!attrsOnly) 1734 appendStringInfoString(&buf, "RANGE"); 1735 break; 1736 default: 1737 elog(ERROR, "unexpected partition strategy: %d", 1738 (int) form->partstrat); 1739 } 1740 1741 if (!attrsOnly) 1742 appendStringInfoString(&buf, " ("); 1743 sep = ""; 1744 for (keyno = 0; keyno < form->partnatts; keyno++) 1745 { 1746 AttrNumber attnum = form->partattrs.values[keyno]; 1747 Oid keycoltype; 1748 Oid keycolcollation; 1749 Oid partcoll; 1750 1751 appendStringInfoString(&buf, sep); 1752 sep = ", "; 1753 if (attnum != 0) 1754 { 1755 /* Simple attribute reference */ 1756 char *attname; 1757 int32 keycoltypmod; 1758 1759 attname = get_attname(relid, attnum, false); 1760 appendStringInfoString(&buf, quote_identifier(attname)); 1761 get_atttypetypmodcoll(relid, attnum, 1762 &keycoltype, &keycoltypmod, 1763 &keycolcollation); 1764 } 1765 else 1766 { 1767 /* Expression */ 1768 Node *partkey; 1769 1770 if (partexpr_item == NULL) 1771 elog(ERROR, "too few entries in partexprs list"); 1772 partkey = (Node *) lfirst(partexpr_item); 1773 partexpr_item = lnext(partexpr_item); 1774 1775 /* Deparse */ 1776 str = deparse_expression_pretty(partkey, context, false, false, 1777 prettyFlags, 0); 1778 /* Need parens if it's not a bare function call */ 1779 if (looks_like_function(partkey)) 1780 appendStringInfoString(&buf, str); 1781 else 1782 appendStringInfo(&buf, "(%s)", str); 1783 1784 keycoltype = exprType(partkey); 1785 keycolcollation = exprCollation(partkey); 1786 } 1787 1788 /* Add collation, if not default for column */ 1789 partcoll = partcollation->values[keyno]; 1790 if (!attrsOnly && OidIsValid(partcoll) && partcoll != keycolcollation) 1791 appendStringInfo(&buf, " COLLATE %s", 1792 generate_collation_name((partcoll))); 1793 1794 /* Add the operator class name, if not default */ 1795 if (!attrsOnly) 1796 get_opclass_name(partclass->values[keyno], keycoltype, &buf); 1797 } 1798 1799 if (!attrsOnly) 1800 appendStringInfoChar(&buf, ')'); 1801 1802 /* Clean up */ 1803 ReleaseSysCache(tuple); 1804 1805 return buf.data; 1806 } 1807 1808 /* 1809 * pg_get_partition_constraintdef 1810 * 1811 * Returns partition constraint expression as a string for the input relation 1812 */ 1813 Datum 1814 pg_get_partition_constraintdef(PG_FUNCTION_ARGS) 1815 { 1816 Oid relationId = PG_GETARG_OID(0); 1817 Expr *constr_expr; 1818 int prettyFlags; 1819 List *context; 1820 char *consrc; 1821 1822 constr_expr = get_partition_qual_relid(relationId); 1823 1824 /* Quick exit if no partition constraint */ 1825 if (constr_expr == NULL) 1826 PG_RETURN_NULL(); 1827 1828 /* 1829 * Deparse and return the constraint expression. 1830 */ 1831 prettyFlags = PRETTYFLAG_INDENT; 1832 context = deparse_context_for(get_relation_name(relationId), relationId); 1833 consrc = deparse_expression_pretty((Node *) constr_expr, context, false, 1834 false, prettyFlags, 0); 1835 1836 PG_RETURN_TEXT_P(string_to_text(consrc)); 1837 } 1838 1839 /* 1840 * pg_get_partconstrdef_string 1841 * 1842 * Returns the partition constraint as a C-string for the input relation, with 1843 * the given alias. No pretty-printing. 1844 */ 1845 char * 1846 pg_get_partconstrdef_string(Oid partitionId, char *aliasname) 1847 { 1848 Expr *constr_expr; 1849 List *context; 1850 1851 constr_expr = get_partition_qual_relid(partitionId); 1852 context = deparse_context_for(aliasname, partitionId); 1853 1854 return deparse_expression((Node *) constr_expr, context, true, false); 1855 } 1856 1857 /* 1858 * pg_get_constraintdef 1859 * 1860 * Returns the definition for the constraint, ie, everything that needs to 1861 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>". 1862 */ 1863 Datum 1864 pg_get_constraintdef(PG_FUNCTION_ARGS) 1865 { 1866 Oid constraintId = PG_GETARG_OID(0); 1867 int prettyFlags; 1868 char *res; 1869 1870 prettyFlags = PRETTYFLAG_INDENT; 1871 1872 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true); 1873 1874 if (res == NULL) 1875 PG_RETURN_NULL(); 1876 1877 PG_RETURN_TEXT_P(string_to_text(res)); 1878 } 1879 1880 Datum 1881 pg_get_constraintdef_ext(PG_FUNCTION_ARGS) 1882 { 1883 Oid constraintId = PG_GETARG_OID(0); 1884 bool pretty = PG_GETARG_BOOL(1); 1885 int prettyFlags; 1886 char *res; 1887 1888 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 1889 1890 res = pg_get_constraintdef_worker(constraintId, false, prettyFlags, true); 1891 1892 if (res == NULL) 1893 PG_RETURN_NULL(); 1894 1895 PG_RETURN_TEXT_P(string_to_text(res)); 1896 } 1897 1898 /* 1899 * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command 1900 */ 1901 char * 1902 pg_get_constraintdef_command(Oid constraintId) 1903 { 1904 return pg_get_constraintdef_worker(constraintId, true, 0, false); 1905 } 1906 1907 /* 1908 * As of 9.4, we now use an MVCC snapshot for this. 1909 */ 1910 static char * 1911 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, 1912 int prettyFlags, bool missing_ok) 1913 { 1914 HeapTuple tup; 1915 Form_pg_constraint conForm; 1916 StringInfoData buf; 1917 SysScanDesc scandesc; 1918 ScanKeyData scankey[1]; 1919 Snapshot snapshot = RegisterSnapshot(GetTransactionSnapshot()); 1920 Relation relation = table_open(ConstraintRelationId, AccessShareLock); 1921 1922 ScanKeyInit(&scankey[0], 1923 Anum_pg_constraint_oid, 1924 BTEqualStrategyNumber, F_OIDEQ, 1925 ObjectIdGetDatum(constraintId)); 1926 1927 scandesc = systable_beginscan(relation, 1928 ConstraintOidIndexId, 1929 true, 1930 snapshot, 1931 1, 1932 scankey); 1933 1934 /* 1935 * We later use the tuple with SysCacheGetAttr() as if we had obtained it 1936 * via SearchSysCache, which works fine. 1937 */ 1938 tup = systable_getnext(scandesc); 1939 1940 UnregisterSnapshot(snapshot); 1941 1942 if (!HeapTupleIsValid(tup)) 1943 { 1944 if (missing_ok) 1945 { 1946 systable_endscan(scandesc); 1947 table_close(relation, AccessShareLock); 1948 return NULL; 1949 } 1950 elog(ERROR, "could not find tuple for constraint %u", constraintId); 1951 } 1952 1953 conForm = (Form_pg_constraint) GETSTRUCT(tup); 1954 1955 initStringInfo(&buf); 1956 1957 if (fullCommand) 1958 { 1959 if (OidIsValid(conForm->conrelid)) 1960 { 1961 /* 1962 * Currently, callers want ALTER TABLE (without ONLY) for CHECK 1963 * constraints, and other types of constraints don't inherit 1964 * anyway so it doesn't matter whether we say ONLY or not. Someday 1965 * we might need to let callers specify whether to put ONLY in the 1966 * command. 1967 */ 1968 appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ", 1969 generate_qualified_relation_name(conForm->conrelid), 1970 quote_identifier(NameStr(conForm->conname))); 1971 } 1972 else 1973 { 1974 /* Must be a domain constraint */ 1975 Assert(OidIsValid(conForm->contypid)); 1976 appendStringInfo(&buf, "ALTER DOMAIN %s ADD CONSTRAINT %s ", 1977 generate_qualified_type_name(conForm->contypid), 1978 quote_identifier(NameStr(conForm->conname))); 1979 } 1980 } 1981 1982 switch (conForm->contype) 1983 { 1984 case CONSTRAINT_FOREIGN: 1985 { 1986 Datum val; 1987 bool isnull; 1988 const char *string; 1989 1990 /* Start off the constraint definition */ 1991 appendStringInfoString(&buf, "FOREIGN KEY ("); 1992 1993 /* Fetch and build referencing-column list */ 1994 val = SysCacheGetAttr(CONSTROID, tup, 1995 Anum_pg_constraint_conkey, &isnull); 1996 if (isnull) 1997 elog(ERROR, "null conkey for constraint %u", 1998 constraintId); 1999 2000 decompile_column_index_array(val, conForm->conrelid, &buf); 2001 2002 /* add foreign relation name */ 2003 appendStringInfo(&buf, ") REFERENCES %s(", 2004 generate_relation_name(conForm->confrelid, 2005 NIL)); 2006 2007 /* Fetch and build referenced-column list */ 2008 val = SysCacheGetAttr(CONSTROID, tup, 2009 Anum_pg_constraint_confkey, &isnull); 2010 if (isnull) 2011 elog(ERROR, "null confkey for constraint %u", 2012 constraintId); 2013 2014 decompile_column_index_array(val, conForm->confrelid, &buf); 2015 2016 appendStringInfoChar(&buf, ')'); 2017 2018 /* Add match type */ 2019 switch (conForm->confmatchtype) 2020 { 2021 case FKCONSTR_MATCH_FULL: 2022 string = " MATCH FULL"; 2023 break; 2024 case FKCONSTR_MATCH_PARTIAL: 2025 string = " MATCH PARTIAL"; 2026 break; 2027 case FKCONSTR_MATCH_SIMPLE: 2028 string = ""; 2029 break; 2030 default: 2031 elog(ERROR, "unrecognized confmatchtype: %d", 2032 conForm->confmatchtype); 2033 string = ""; /* keep compiler quiet */ 2034 break; 2035 } 2036 appendStringInfoString(&buf, string); 2037 2038 /* Add ON UPDATE and ON DELETE clauses, if needed */ 2039 switch (conForm->confupdtype) 2040 { 2041 case FKCONSTR_ACTION_NOACTION: 2042 string = NULL; /* suppress default */ 2043 break; 2044 case FKCONSTR_ACTION_RESTRICT: 2045 string = "RESTRICT"; 2046 break; 2047 case FKCONSTR_ACTION_CASCADE: 2048 string = "CASCADE"; 2049 break; 2050 case FKCONSTR_ACTION_SETNULL: 2051 string = "SET NULL"; 2052 break; 2053 case FKCONSTR_ACTION_SETDEFAULT: 2054 string = "SET DEFAULT"; 2055 break; 2056 default: 2057 elog(ERROR, "unrecognized confupdtype: %d", 2058 conForm->confupdtype); 2059 string = NULL; /* keep compiler quiet */ 2060 break; 2061 } 2062 if (string) 2063 appendStringInfo(&buf, " ON UPDATE %s", string); 2064 2065 switch (conForm->confdeltype) 2066 { 2067 case FKCONSTR_ACTION_NOACTION: 2068 string = NULL; /* suppress default */ 2069 break; 2070 case FKCONSTR_ACTION_RESTRICT: 2071 string = "RESTRICT"; 2072 break; 2073 case FKCONSTR_ACTION_CASCADE: 2074 string = "CASCADE"; 2075 break; 2076 case FKCONSTR_ACTION_SETNULL: 2077 string = "SET NULL"; 2078 break; 2079 case FKCONSTR_ACTION_SETDEFAULT: 2080 string = "SET DEFAULT"; 2081 break; 2082 default: 2083 elog(ERROR, "unrecognized confdeltype: %d", 2084 conForm->confdeltype); 2085 string = NULL; /* keep compiler quiet */ 2086 break; 2087 } 2088 if (string) 2089 appendStringInfo(&buf, " ON DELETE %s", string); 2090 2091 break; 2092 } 2093 case CONSTRAINT_PRIMARY: 2094 case CONSTRAINT_UNIQUE: 2095 { 2096 Datum val; 2097 bool isnull; 2098 Oid indexId; 2099 int keyatts; 2100 HeapTuple indtup; 2101 2102 /* Start off the constraint definition */ 2103 if (conForm->contype == CONSTRAINT_PRIMARY) 2104 appendStringInfoString(&buf, "PRIMARY KEY ("); 2105 else 2106 appendStringInfoString(&buf, "UNIQUE ("); 2107 2108 /* Fetch and build target column list */ 2109 val = SysCacheGetAttr(CONSTROID, tup, 2110 Anum_pg_constraint_conkey, &isnull); 2111 if (isnull) 2112 elog(ERROR, "null conkey for constraint %u", 2113 constraintId); 2114 2115 keyatts = decompile_column_index_array(val, conForm->conrelid, &buf); 2116 2117 appendStringInfoChar(&buf, ')'); 2118 2119 indexId = get_constraint_index(constraintId); 2120 2121 /* Build including column list (from pg_index.indkeys) */ 2122 indtup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId)); 2123 if (!HeapTupleIsValid(indtup)) 2124 elog(ERROR, "cache lookup failed for index %u", indexId); 2125 val = SysCacheGetAttr(INDEXRELID, indtup, 2126 Anum_pg_index_indnatts, &isnull); 2127 if (isnull) 2128 elog(ERROR, "null indnatts for index %u", indexId); 2129 if (DatumGetInt32(val) > keyatts) 2130 { 2131 Datum cols; 2132 Datum *keys; 2133 int nKeys; 2134 int j; 2135 2136 appendStringInfoString(&buf, " INCLUDE ("); 2137 2138 cols = SysCacheGetAttr(INDEXRELID, indtup, 2139 Anum_pg_index_indkey, &isnull); 2140 if (isnull) 2141 elog(ERROR, "null indkey for index %u", indexId); 2142 2143 deconstruct_array(DatumGetArrayTypeP(cols), 2144 INT2OID, 2, true, 's', 2145 &keys, NULL, &nKeys); 2146 2147 for (j = keyatts; j < nKeys; j++) 2148 { 2149 char *colName; 2150 2151 colName = get_attname(conForm->conrelid, 2152 DatumGetInt16(keys[j]), false); 2153 if (j > keyatts) 2154 appendStringInfoString(&buf, ", "); 2155 appendStringInfoString(&buf, quote_identifier(colName)); 2156 } 2157 2158 appendStringInfoChar(&buf, ')'); 2159 } 2160 ReleaseSysCache(indtup); 2161 2162 /* XXX why do we only print these bits if fullCommand? */ 2163 if (fullCommand && OidIsValid(indexId)) 2164 { 2165 char *options = flatten_reloptions(indexId); 2166 Oid tblspc; 2167 2168 if (options) 2169 { 2170 appendStringInfo(&buf, " WITH (%s)", options); 2171 pfree(options); 2172 } 2173 2174 /* 2175 * Print the tablespace, unless it's the database default. 2176 * This is to help ALTER TABLE usage of this facility, 2177 * which needs this behavior to recreate exact catalog 2178 * state. 2179 */ 2180 tblspc = get_rel_tablespace(indexId); 2181 if (OidIsValid(tblspc)) 2182 appendStringInfo(&buf, " USING INDEX TABLESPACE %s", 2183 quote_identifier(get_tablespace_name(tblspc))); 2184 } 2185 2186 break; 2187 } 2188 case CONSTRAINT_CHECK: 2189 { 2190 Datum val; 2191 bool isnull; 2192 char *conbin; 2193 char *consrc; 2194 Node *expr; 2195 List *context; 2196 2197 /* Fetch constraint expression in parsetree form */ 2198 val = SysCacheGetAttr(CONSTROID, tup, 2199 Anum_pg_constraint_conbin, &isnull); 2200 if (isnull) 2201 elog(ERROR, "null conbin for constraint %u", 2202 constraintId); 2203 2204 conbin = TextDatumGetCString(val); 2205 expr = stringToNode(conbin); 2206 2207 /* Set up deparsing context for Var nodes in constraint */ 2208 if (conForm->conrelid != InvalidOid) 2209 { 2210 /* relation constraint */ 2211 context = deparse_context_for(get_relation_name(conForm->conrelid), 2212 conForm->conrelid); 2213 } 2214 else 2215 { 2216 /* domain constraint --- can't have Vars */ 2217 context = NIL; 2218 } 2219 2220 consrc = deparse_expression_pretty(expr, context, false, false, 2221 prettyFlags, 0); 2222 2223 /* 2224 * Now emit the constraint definition, adding NO INHERIT if 2225 * necessary. 2226 * 2227 * There are cases where the constraint expression will be 2228 * fully parenthesized and we don't need the outer parens ... 2229 * but there are other cases where we do need 'em. Be 2230 * conservative for now. 2231 * 2232 * Note that simply checking for leading '(' and trailing ')' 2233 * would NOT be good enough, consider "(x > 0) AND (y > 0)". 2234 */ 2235 appendStringInfo(&buf, "CHECK (%s)%s", 2236 consrc, 2237 conForm->connoinherit ? " NO INHERIT" : ""); 2238 break; 2239 } 2240 case CONSTRAINT_TRIGGER: 2241 2242 /* 2243 * There isn't an ALTER TABLE syntax for creating a user-defined 2244 * constraint trigger, but it seems better to print something than 2245 * throw an error; if we throw error then this function couldn't 2246 * safely be applied to all rows of pg_constraint. 2247 */ 2248 appendStringInfoString(&buf, "TRIGGER"); 2249 break; 2250 case CONSTRAINT_EXCLUSION: 2251 { 2252 Oid indexOid = conForm->conindid; 2253 Datum val; 2254 bool isnull; 2255 Datum *elems; 2256 int nElems; 2257 int i; 2258 Oid *operators; 2259 2260 /* Extract operator OIDs from the pg_constraint tuple */ 2261 val = SysCacheGetAttr(CONSTROID, tup, 2262 Anum_pg_constraint_conexclop, 2263 &isnull); 2264 if (isnull) 2265 elog(ERROR, "null conexclop for constraint %u", 2266 constraintId); 2267 2268 deconstruct_array(DatumGetArrayTypeP(val), 2269 OIDOID, sizeof(Oid), true, 'i', 2270 &elems, NULL, &nElems); 2271 2272 operators = (Oid *) palloc(nElems * sizeof(Oid)); 2273 for (i = 0; i < nElems; i++) 2274 operators[i] = DatumGetObjectId(elems[i]); 2275 2276 /* pg_get_indexdef_worker does the rest */ 2277 /* suppress tablespace because pg_dump wants it that way */ 2278 appendStringInfoString(&buf, 2279 pg_get_indexdef_worker(indexOid, 2280 0, 2281 operators, 2282 false, 2283 false, 2284 false, 2285 false, 2286 prettyFlags, 2287 false)); 2288 break; 2289 } 2290 default: 2291 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype); 2292 break; 2293 } 2294 2295 if (conForm->condeferrable) 2296 appendStringInfoString(&buf, " DEFERRABLE"); 2297 if (conForm->condeferred) 2298 appendStringInfoString(&buf, " INITIALLY DEFERRED"); 2299 if (!conForm->convalidated) 2300 appendStringInfoString(&buf, " NOT VALID"); 2301 2302 /* Cleanup */ 2303 systable_endscan(scandesc); 2304 table_close(relation, AccessShareLock); 2305 2306 return buf.data; 2307 } 2308 2309 2310 /* 2311 * Convert an int16[] Datum into a comma-separated list of column names 2312 * for the indicated relation; append the list to buf. Returns the number 2313 * of keys. 2314 */ 2315 static int 2316 decompile_column_index_array(Datum column_index_array, Oid relId, 2317 StringInfo buf) 2318 { 2319 Datum *keys; 2320 int nKeys; 2321 int j; 2322 2323 /* Extract data from array of int16 */ 2324 deconstruct_array(DatumGetArrayTypeP(column_index_array), 2325 INT2OID, 2, true, 's', 2326 &keys, NULL, &nKeys); 2327 2328 for (j = 0; j < nKeys; j++) 2329 { 2330 char *colName; 2331 2332 colName = get_attname(relId, DatumGetInt16(keys[j]), false); 2333 2334 if (j == 0) 2335 appendStringInfoString(buf, quote_identifier(colName)); 2336 else 2337 appendStringInfo(buf, ", %s", quote_identifier(colName)); 2338 } 2339 2340 return nKeys; 2341 } 2342 2343 2344 /* ---------- 2345 * get_expr - Decompile an expression tree 2346 * 2347 * Input: an expression tree in nodeToString form, and a relation OID 2348 * 2349 * Output: reverse-listed expression 2350 * 2351 * Currently, the expression can only refer to a single relation, namely 2352 * the one specified by the second parameter. This is sufficient for 2353 * partial indexes, column default expressions, etc. We also support 2354 * Var-free expressions, for which the OID can be InvalidOid. 2355 * ---------- 2356 */ 2357 Datum 2358 pg_get_expr(PG_FUNCTION_ARGS) 2359 { 2360 text *expr = PG_GETARG_TEXT_PP(0); 2361 Oid relid = PG_GETARG_OID(1); 2362 int prettyFlags; 2363 char *relname; 2364 2365 prettyFlags = PRETTYFLAG_INDENT; 2366 2367 if (OidIsValid(relid)) 2368 { 2369 /* Get the name for the relation */ 2370 relname = get_rel_name(relid); 2371 2372 /* 2373 * If the OID isn't actually valid, don't throw an error, just return 2374 * NULL. This is a bit questionable, but it's what we've done 2375 * historically, and it can help avoid unwanted failures when 2376 * examining catalog entries for just-deleted relations. 2377 */ 2378 if (relname == NULL) 2379 PG_RETURN_NULL(); 2380 } 2381 else 2382 relname = NULL; 2383 2384 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags)); 2385 } 2386 2387 Datum 2388 pg_get_expr_ext(PG_FUNCTION_ARGS) 2389 { 2390 text *expr = PG_GETARG_TEXT_PP(0); 2391 Oid relid = PG_GETARG_OID(1); 2392 bool pretty = PG_GETARG_BOOL(2); 2393 int prettyFlags; 2394 char *relname; 2395 2396 prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) : PRETTYFLAG_INDENT; 2397 2398 if (OidIsValid(relid)) 2399 { 2400 /* Get the name for the relation */ 2401 relname = get_rel_name(relid); 2402 /* See notes above */ 2403 if (relname == NULL) 2404 PG_RETURN_NULL(); 2405 } 2406 else 2407 relname = NULL; 2408 2409 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags)); 2410 } 2411 2412 static text * 2413 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags) 2414 { 2415 Node *node; 2416 List *context; 2417 char *exprstr; 2418 char *str; 2419 2420 /* Convert input TEXT object to C string */ 2421 exprstr = text_to_cstring(expr); 2422 2423 /* Convert expression to node tree */ 2424 node = (Node *) stringToNode(exprstr); 2425 2426 pfree(exprstr); 2427 2428 /* Prepare deparse context if needed */ 2429 if (OidIsValid(relid)) 2430 context = deparse_context_for(relname, relid); 2431 else 2432 context = NIL; 2433 2434 /* Deparse */ 2435 str = deparse_expression_pretty(node, context, false, false, 2436 prettyFlags, 0); 2437 2438 return string_to_text(str); 2439 } 2440 2441 2442 /* ---------- 2443 * get_userbyid - Get a user name by roleid and 2444 * fallback to 'unknown (OID=n)' 2445 * ---------- 2446 */ 2447 Datum 2448 pg_get_userbyid(PG_FUNCTION_ARGS) 2449 { 2450 Oid roleid = PG_GETARG_OID(0); 2451 Name result; 2452 HeapTuple roletup; 2453 Form_pg_authid role_rec; 2454 2455 /* 2456 * Allocate space for the result 2457 */ 2458 result = (Name) palloc(NAMEDATALEN); 2459 memset(NameStr(*result), 0, NAMEDATALEN); 2460 2461 /* 2462 * Get the pg_authid entry and print the result 2463 */ 2464 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid)); 2465 if (HeapTupleIsValid(roletup)) 2466 { 2467 role_rec = (Form_pg_authid) GETSTRUCT(roletup); 2468 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN); 2469 ReleaseSysCache(roletup); 2470 } 2471 else 2472 sprintf(NameStr(*result), "unknown (OID=%u)", roleid); 2473 2474 PG_RETURN_NAME(result); 2475 } 2476 2477 2478 /* 2479 * pg_get_serial_sequence 2480 * Get the name of the sequence used by an identity or serial column, 2481 * formatted suitably for passing to setval, nextval or currval. 2482 * First parameter is not treated as double-quoted, second parameter 2483 * is --- see documentation for reason. 2484 */ 2485 Datum 2486 pg_get_serial_sequence(PG_FUNCTION_ARGS) 2487 { 2488 text *tablename = PG_GETARG_TEXT_PP(0); 2489 text *columnname = PG_GETARG_TEXT_PP(1); 2490 RangeVar *tablerv; 2491 Oid tableOid; 2492 char *column; 2493 AttrNumber attnum; 2494 Oid sequenceId = InvalidOid; 2495 Relation depRel; 2496 ScanKeyData key[3]; 2497 SysScanDesc scan; 2498 HeapTuple tup; 2499 2500 /* Look up table name. Can't lock it - we might not have privileges. */ 2501 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename)); 2502 tableOid = RangeVarGetRelid(tablerv, NoLock, false); 2503 2504 /* Get the number of the column */ 2505 column = text_to_cstring(columnname); 2506 2507 attnum = get_attnum(tableOid, column); 2508 if (attnum == InvalidAttrNumber) 2509 ereport(ERROR, 2510 (errcode(ERRCODE_UNDEFINED_COLUMN), 2511 errmsg("column \"%s\" of relation \"%s\" does not exist", 2512 column, tablerv->relname))); 2513 2514 /* Search the dependency table for the dependent sequence */ 2515 depRel = table_open(DependRelationId, AccessShareLock); 2516 2517 ScanKeyInit(&key[0], 2518 Anum_pg_depend_refclassid, 2519 BTEqualStrategyNumber, F_OIDEQ, 2520 ObjectIdGetDatum(RelationRelationId)); 2521 ScanKeyInit(&key[1], 2522 Anum_pg_depend_refobjid, 2523 BTEqualStrategyNumber, F_OIDEQ, 2524 ObjectIdGetDatum(tableOid)); 2525 ScanKeyInit(&key[2], 2526 Anum_pg_depend_refobjsubid, 2527 BTEqualStrategyNumber, F_INT4EQ, 2528 Int32GetDatum(attnum)); 2529 2530 scan = systable_beginscan(depRel, DependReferenceIndexId, true, 2531 NULL, 3, key); 2532 2533 while (HeapTupleIsValid(tup = systable_getnext(scan))) 2534 { 2535 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup); 2536 2537 /* 2538 * Look for an auto dependency (serial column) or internal dependency 2539 * (identity column) of a sequence on a column. (We need the relkind 2540 * test because indexes can also have auto dependencies on columns.) 2541 */ 2542 if (deprec->classid == RelationRelationId && 2543 deprec->objsubid == 0 && 2544 (deprec->deptype == DEPENDENCY_AUTO || 2545 deprec->deptype == DEPENDENCY_INTERNAL) && 2546 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE) 2547 { 2548 sequenceId = deprec->objid; 2549 break; 2550 } 2551 } 2552 2553 systable_endscan(scan); 2554 table_close(depRel, AccessShareLock); 2555 2556 if (OidIsValid(sequenceId)) 2557 { 2558 char *result; 2559 2560 result = generate_qualified_relation_name(sequenceId); 2561 2562 PG_RETURN_TEXT_P(string_to_text(result)); 2563 } 2564 2565 PG_RETURN_NULL(); 2566 } 2567 2568 2569 /* 2570 * pg_get_functiondef 2571 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for 2572 * the specified function. 2573 * 2574 * Note: if you change the output format of this function, be careful not 2575 * to break psql's rules (in \ef and \sf) for identifying the start of the 2576 * function body. To wit: the function body starts on a line that begins 2577 * with "AS ", and no preceding line will look like that. 2578 */ 2579 Datum 2580 pg_get_functiondef(PG_FUNCTION_ARGS) 2581 { 2582 Oid funcid = PG_GETARG_OID(0); 2583 StringInfoData buf; 2584 StringInfoData dq; 2585 HeapTuple proctup; 2586 Form_pg_proc proc; 2587 bool isfunction; 2588 Datum tmp; 2589 bool isnull; 2590 const char *prosrc; 2591 const char *name; 2592 const char *nsp; 2593 float4 procost; 2594 int oldlen; 2595 2596 initStringInfo(&buf); 2597 2598 /* Look up the function */ 2599 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 2600 if (!HeapTupleIsValid(proctup)) 2601 PG_RETURN_NULL(); 2602 2603 proc = (Form_pg_proc) GETSTRUCT(proctup); 2604 name = NameStr(proc->proname); 2605 2606 if (proc->prokind == PROKIND_AGGREGATE) 2607 ereport(ERROR, 2608 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 2609 errmsg("\"%s\" is an aggregate function", name))); 2610 2611 isfunction = (proc->prokind != PROKIND_PROCEDURE); 2612 2613 /* 2614 * We always qualify the function name, to ensure the right function gets 2615 * replaced. 2616 */ 2617 nsp = get_namespace_name(proc->pronamespace); 2618 appendStringInfo(&buf, "CREATE OR REPLACE %s %s(", 2619 isfunction ? "FUNCTION" : "PROCEDURE", 2620 quote_qualified_identifier(nsp, name)); 2621 (void) print_function_arguments(&buf, proctup, false, true); 2622 appendStringInfoString(&buf, ")\n"); 2623 if (isfunction) 2624 { 2625 appendStringInfoString(&buf, " RETURNS "); 2626 print_function_rettype(&buf, proctup); 2627 appendStringInfoChar(&buf, '\n'); 2628 } 2629 2630 print_function_trftypes(&buf, proctup); 2631 2632 appendStringInfo(&buf, " LANGUAGE %s\n", 2633 quote_identifier(get_language_name(proc->prolang, false))); 2634 2635 /* Emit some miscellaneous options on one line */ 2636 oldlen = buf.len; 2637 2638 if (proc->prokind == PROKIND_WINDOW) 2639 appendStringInfoString(&buf, " WINDOW"); 2640 switch (proc->provolatile) 2641 { 2642 case PROVOLATILE_IMMUTABLE: 2643 appendStringInfoString(&buf, " IMMUTABLE"); 2644 break; 2645 case PROVOLATILE_STABLE: 2646 appendStringInfoString(&buf, " STABLE"); 2647 break; 2648 case PROVOLATILE_VOLATILE: 2649 break; 2650 } 2651 2652 switch (proc->proparallel) 2653 { 2654 case PROPARALLEL_SAFE: 2655 appendStringInfoString(&buf, " PARALLEL SAFE"); 2656 break; 2657 case PROPARALLEL_RESTRICTED: 2658 appendStringInfoString(&buf, " PARALLEL RESTRICTED"); 2659 break; 2660 case PROPARALLEL_UNSAFE: 2661 break; 2662 } 2663 2664 if (proc->proisstrict) 2665 appendStringInfoString(&buf, " STRICT"); 2666 if (proc->prosecdef) 2667 appendStringInfoString(&buf, " SECURITY DEFINER"); 2668 if (proc->proleakproof) 2669 appendStringInfoString(&buf, " LEAKPROOF"); 2670 2671 /* This code for the default cost and rows should match functioncmds.c */ 2672 if (proc->prolang == INTERNALlanguageId || 2673 proc->prolang == ClanguageId) 2674 procost = 1; 2675 else 2676 procost = 100; 2677 if (proc->procost != procost) 2678 appendStringInfo(&buf, " COST %g", proc->procost); 2679 2680 if (proc->prorows > 0 && proc->prorows != 1000) 2681 appendStringInfo(&buf, " ROWS %g", proc->prorows); 2682 2683 if (proc->prosupport) 2684 { 2685 Oid argtypes[1]; 2686 2687 /* 2688 * We should qualify the support function's name if it wouldn't be 2689 * resolved by lookup in the current search path. 2690 */ 2691 argtypes[0] = INTERNALOID; 2692 appendStringInfo(&buf, " SUPPORT %s", 2693 generate_function_name(proc->prosupport, 1, 2694 NIL, argtypes, 2695 false, NULL, EXPR_KIND_NONE)); 2696 } 2697 2698 if (oldlen != buf.len) 2699 appendStringInfoChar(&buf, '\n'); 2700 2701 /* Emit any proconfig options, one per line */ 2702 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull); 2703 if (!isnull) 2704 { 2705 ArrayType *a = DatumGetArrayTypeP(tmp); 2706 int i; 2707 2708 Assert(ARR_ELEMTYPE(a) == TEXTOID); 2709 Assert(ARR_NDIM(a) == 1); 2710 Assert(ARR_LBOUND(a)[0] == 1); 2711 2712 for (i = 1; i <= ARR_DIMS(a)[0]; i++) 2713 { 2714 Datum d; 2715 2716 d = array_ref(a, 1, &i, 2717 -1 /* varlenarray */ , 2718 -1 /* TEXT's typlen */ , 2719 false /* TEXT's typbyval */ , 2720 'i' /* TEXT's typalign */ , 2721 &isnull); 2722 if (!isnull) 2723 { 2724 char *configitem = TextDatumGetCString(d); 2725 char *pos; 2726 2727 pos = strchr(configitem, '='); 2728 if (pos == NULL) 2729 continue; 2730 *pos++ = '\0'; 2731 2732 appendStringInfo(&buf, " SET %s TO ", 2733 quote_identifier(configitem)); 2734 2735 /* 2736 * Variables that are marked GUC_LIST_QUOTE were already fully 2737 * quoted by flatten_set_variable_args() before they were put 2738 * into the proconfig array. However, because the quoting 2739 * rules used there aren't exactly like SQL's, we have to 2740 * break the list value apart and then quote the elements as 2741 * string literals. (The elements may be double-quoted as-is, 2742 * but we can't just feed them to the SQL parser; it would do 2743 * the wrong thing with elements that are zero-length or 2744 * longer than NAMEDATALEN.) 2745 * 2746 * Variables that are not so marked should just be emitted as 2747 * simple string literals. If the variable is not known to 2748 * guc.c, we'll do that; this makes it unsafe to use 2749 * GUC_LIST_QUOTE for extension variables. 2750 */ 2751 if (GetConfigOptionFlags(configitem, true) & GUC_LIST_QUOTE) 2752 { 2753 List *namelist; 2754 ListCell *lc; 2755 2756 /* Parse string into list of identifiers */ 2757 if (!SplitGUCList(pos, ',', &namelist)) 2758 { 2759 /* this shouldn't fail really */ 2760 elog(ERROR, "invalid list syntax in proconfig item"); 2761 } 2762 foreach(lc, namelist) 2763 { 2764 char *curname = (char *) lfirst(lc); 2765 2766 simple_quote_literal(&buf, curname); 2767 if (lnext(lc)) 2768 appendStringInfoString(&buf, ", "); 2769 } 2770 } 2771 else 2772 simple_quote_literal(&buf, pos); 2773 appendStringInfoChar(&buf, '\n'); 2774 } 2775 } 2776 } 2777 2778 /* And finally the function definition ... */ 2779 appendStringInfoString(&buf, "AS "); 2780 2781 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull); 2782 if (!isnull) 2783 { 2784 simple_quote_literal(&buf, TextDatumGetCString(tmp)); 2785 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */ 2786 } 2787 2788 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull); 2789 if (isnull) 2790 elog(ERROR, "null prosrc"); 2791 prosrc = TextDatumGetCString(tmp); 2792 2793 /* 2794 * We always use dollar quoting. Figure out a suitable delimiter. 2795 * 2796 * Since the user is likely to be editing the function body string, we 2797 * shouldn't use a short delimiter that he might easily create a conflict 2798 * with. Hence prefer "$function$"/"$procedure$", but extend if needed. 2799 */ 2800 initStringInfo(&dq); 2801 appendStringInfoChar(&dq, '$'); 2802 appendStringInfoString(&dq, (isfunction ? "function" : "procedure")); 2803 while (strstr(prosrc, dq.data) != NULL) 2804 appendStringInfoChar(&dq, 'x'); 2805 appendStringInfoChar(&dq, '$'); 2806 2807 appendStringInfoString(&buf, dq.data); 2808 appendStringInfoString(&buf, prosrc); 2809 appendStringInfoString(&buf, dq.data); 2810 2811 appendStringInfoChar(&buf, '\n'); 2812 2813 ReleaseSysCache(proctup); 2814 2815 PG_RETURN_TEXT_P(string_to_text(buf.data)); 2816 } 2817 2818 /* 2819 * pg_get_function_arguments 2820 * Get a nicely-formatted list of arguments for a function. 2821 * This is everything that would go between the parentheses in 2822 * CREATE FUNCTION. 2823 */ 2824 Datum 2825 pg_get_function_arguments(PG_FUNCTION_ARGS) 2826 { 2827 Oid funcid = PG_GETARG_OID(0); 2828 StringInfoData buf; 2829 HeapTuple proctup; 2830 2831 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 2832 if (!HeapTupleIsValid(proctup)) 2833 PG_RETURN_NULL(); 2834 2835 initStringInfo(&buf); 2836 2837 (void) print_function_arguments(&buf, proctup, false, true); 2838 2839 ReleaseSysCache(proctup); 2840 2841 PG_RETURN_TEXT_P(string_to_text(buf.data)); 2842 } 2843 2844 /* 2845 * pg_get_function_identity_arguments 2846 * Get a formatted list of arguments for a function. 2847 * This is everything that would go between the parentheses in 2848 * ALTER FUNCTION, etc. In particular, don't print defaults. 2849 */ 2850 Datum 2851 pg_get_function_identity_arguments(PG_FUNCTION_ARGS) 2852 { 2853 Oid funcid = PG_GETARG_OID(0); 2854 StringInfoData buf; 2855 HeapTuple proctup; 2856 2857 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 2858 if (!HeapTupleIsValid(proctup)) 2859 PG_RETURN_NULL(); 2860 2861 initStringInfo(&buf); 2862 2863 (void) print_function_arguments(&buf, proctup, false, false); 2864 2865 ReleaseSysCache(proctup); 2866 2867 PG_RETURN_TEXT_P(string_to_text(buf.data)); 2868 } 2869 2870 /* 2871 * pg_get_function_result 2872 * Get a nicely-formatted version of the result type of a function. 2873 * This is what would appear after RETURNS in CREATE FUNCTION. 2874 */ 2875 Datum 2876 pg_get_function_result(PG_FUNCTION_ARGS) 2877 { 2878 Oid funcid = PG_GETARG_OID(0); 2879 StringInfoData buf; 2880 HeapTuple proctup; 2881 2882 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 2883 if (!HeapTupleIsValid(proctup)) 2884 PG_RETURN_NULL(); 2885 2886 if (((Form_pg_proc) GETSTRUCT(proctup))->prokind == PROKIND_PROCEDURE) 2887 { 2888 ReleaseSysCache(proctup); 2889 PG_RETURN_NULL(); 2890 } 2891 2892 initStringInfo(&buf); 2893 2894 print_function_rettype(&buf, proctup); 2895 2896 ReleaseSysCache(proctup); 2897 2898 PG_RETURN_TEXT_P(string_to_text(buf.data)); 2899 } 2900 2901 /* 2902 * Guts of pg_get_function_result: append the function's return type 2903 * to the specified buffer. 2904 */ 2905 static void 2906 print_function_rettype(StringInfo buf, HeapTuple proctup) 2907 { 2908 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup); 2909 int ntabargs = 0; 2910 StringInfoData rbuf; 2911 2912 initStringInfo(&rbuf); 2913 2914 if (proc->proretset) 2915 { 2916 /* It might be a table function; try to print the arguments */ 2917 appendStringInfoString(&rbuf, "TABLE("); 2918 ntabargs = print_function_arguments(&rbuf, proctup, true, false); 2919 if (ntabargs > 0) 2920 appendStringInfoChar(&rbuf, ')'); 2921 else 2922 resetStringInfo(&rbuf); 2923 } 2924 2925 if (ntabargs == 0) 2926 { 2927 /* Not a table function, so do the normal thing */ 2928 if (proc->proretset) 2929 appendStringInfoString(&rbuf, "SETOF "); 2930 appendStringInfoString(&rbuf, format_type_be(proc->prorettype)); 2931 } 2932 2933 appendStringInfoString(buf, rbuf.data); 2934 } 2935 2936 /* 2937 * Common code for pg_get_function_arguments and pg_get_function_result: 2938 * append the desired subset of arguments to buf. We print only TABLE 2939 * arguments when print_table_args is true, and all the others when it's false. 2940 * We print argument defaults only if print_defaults is true. 2941 * Function return value is the number of arguments printed. 2942 */ 2943 static int 2944 print_function_arguments(StringInfo buf, HeapTuple proctup, 2945 bool print_table_args, bool print_defaults) 2946 { 2947 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup); 2948 int numargs; 2949 Oid *argtypes; 2950 char **argnames; 2951 char *argmodes; 2952 int insertorderbyat = -1; 2953 int argsprinted; 2954 int inputargno; 2955 int nlackdefaults; 2956 ListCell *nextargdefault = NULL; 2957 int i; 2958 2959 numargs = get_func_arg_info(proctup, 2960 &argtypes, &argnames, &argmodes); 2961 2962 nlackdefaults = numargs; 2963 if (print_defaults && proc->pronargdefaults > 0) 2964 { 2965 Datum proargdefaults; 2966 bool isnull; 2967 2968 proargdefaults = SysCacheGetAttr(PROCOID, proctup, 2969 Anum_pg_proc_proargdefaults, 2970 &isnull); 2971 if (!isnull) 2972 { 2973 char *str; 2974 List *argdefaults; 2975 2976 str = TextDatumGetCString(proargdefaults); 2977 argdefaults = castNode(List, stringToNode(str)); 2978 pfree(str); 2979 nextargdefault = list_head(argdefaults); 2980 /* nlackdefaults counts only *input* arguments lacking defaults */ 2981 nlackdefaults = proc->pronargs - list_length(argdefaults); 2982 } 2983 } 2984 2985 /* Check for special treatment of ordered-set aggregates */ 2986 if (proc->prokind == PROKIND_AGGREGATE) 2987 { 2988 HeapTuple aggtup; 2989 Form_pg_aggregate agg; 2990 2991 aggtup = SearchSysCache1(AGGFNOID, proc->oid); 2992 if (!HeapTupleIsValid(aggtup)) 2993 elog(ERROR, "cache lookup failed for aggregate %u", 2994 proc->oid); 2995 agg = (Form_pg_aggregate) GETSTRUCT(aggtup); 2996 if (AGGKIND_IS_ORDERED_SET(agg->aggkind)) 2997 insertorderbyat = agg->aggnumdirectargs; 2998 ReleaseSysCache(aggtup); 2999 } 3000 3001 argsprinted = 0; 3002 inputargno = 0; 3003 for (i = 0; i < numargs; i++) 3004 { 3005 Oid argtype = argtypes[i]; 3006 char *argname = argnames ? argnames[i] : NULL; 3007 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN; 3008 const char *modename; 3009 bool isinput; 3010 3011 switch (argmode) 3012 { 3013 case PROARGMODE_IN: 3014 modename = ""; 3015 isinput = true; 3016 break; 3017 case PROARGMODE_INOUT: 3018 modename = "INOUT "; 3019 isinput = true; 3020 break; 3021 case PROARGMODE_OUT: 3022 modename = "OUT "; 3023 isinput = false; 3024 break; 3025 case PROARGMODE_VARIADIC: 3026 modename = "VARIADIC "; 3027 isinput = true; 3028 break; 3029 case PROARGMODE_TABLE: 3030 modename = ""; 3031 isinput = false; 3032 break; 3033 default: 3034 elog(ERROR, "invalid parameter mode '%c'", argmode); 3035 modename = NULL; /* keep compiler quiet */ 3036 isinput = false; 3037 break; 3038 } 3039 if (isinput) 3040 inputargno++; /* this is a 1-based counter */ 3041 3042 if (print_table_args != (argmode == PROARGMODE_TABLE)) 3043 continue; 3044 3045 if (argsprinted == insertorderbyat) 3046 { 3047 if (argsprinted) 3048 appendStringInfoChar(buf, ' '); 3049 appendStringInfoString(buf, "ORDER BY "); 3050 } 3051 else if (argsprinted) 3052 appendStringInfoString(buf, ", "); 3053 3054 appendStringInfoString(buf, modename); 3055 if (argname && argname[0]) 3056 appendStringInfo(buf, "%s ", quote_identifier(argname)); 3057 appendStringInfoString(buf, format_type_be(argtype)); 3058 if (print_defaults && isinput && inputargno > nlackdefaults) 3059 { 3060 Node *expr; 3061 3062 Assert(nextargdefault != NULL); 3063 expr = (Node *) lfirst(nextargdefault); 3064 nextargdefault = lnext(nextargdefault); 3065 3066 appendStringInfo(buf, " DEFAULT %s", 3067 deparse_expression(expr, NIL, false, false)); 3068 } 3069 argsprinted++; 3070 3071 /* nasty hack: print the last arg twice for variadic ordered-set agg */ 3072 if (argsprinted == insertorderbyat && i == numargs - 1) 3073 { 3074 i--; 3075 /* aggs shouldn't have defaults anyway, but just to be sure ... */ 3076 print_defaults = false; 3077 } 3078 } 3079 3080 return argsprinted; 3081 } 3082 3083 static bool 3084 is_input_argument(int nth, const char *argmodes) 3085 { 3086 return (!argmodes 3087 || argmodes[nth] == PROARGMODE_IN 3088 || argmodes[nth] == PROARGMODE_INOUT 3089 || argmodes[nth] == PROARGMODE_VARIADIC); 3090 } 3091 3092 /* 3093 * Append used transformed types to specified buffer 3094 */ 3095 static void 3096 print_function_trftypes(StringInfo buf, HeapTuple proctup) 3097 { 3098 Oid *trftypes; 3099 int ntypes; 3100 3101 ntypes = get_func_trftypes(proctup, &trftypes); 3102 if (ntypes > 0) 3103 { 3104 int i; 3105 3106 appendStringInfoString(buf, " TRANSFORM "); 3107 for (i = 0; i < ntypes; i++) 3108 { 3109 if (i != 0) 3110 appendStringInfoString(buf, ", "); 3111 appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i])); 3112 } 3113 appendStringInfoChar(buf, '\n'); 3114 } 3115 } 3116 3117 /* 3118 * Get textual representation of a function argument's default value. The 3119 * second argument of this function is the argument number among all arguments 3120 * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's 3121 * how information_schema.sql uses it. 3122 */ 3123 Datum 3124 pg_get_function_arg_default(PG_FUNCTION_ARGS) 3125 { 3126 Oid funcid = PG_GETARG_OID(0); 3127 int32 nth_arg = PG_GETARG_INT32(1); 3128 HeapTuple proctup; 3129 Form_pg_proc proc; 3130 int numargs; 3131 Oid *argtypes; 3132 char **argnames; 3133 char *argmodes; 3134 int i; 3135 List *argdefaults; 3136 Node *node; 3137 char *str; 3138 int nth_inputarg; 3139 Datum proargdefaults; 3140 bool isnull; 3141 int nth_default; 3142 3143 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 3144 if (!HeapTupleIsValid(proctup)) 3145 PG_RETURN_NULL(); 3146 3147 numargs = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes); 3148 if (nth_arg < 1 || nth_arg > numargs || !is_input_argument(nth_arg - 1, argmodes)) 3149 { 3150 ReleaseSysCache(proctup); 3151 PG_RETURN_NULL(); 3152 } 3153 3154 nth_inputarg = 0; 3155 for (i = 0; i < nth_arg; i++) 3156 if (is_input_argument(i, argmodes)) 3157 nth_inputarg++; 3158 3159 proargdefaults = SysCacheGetAttr(PROCOID, proctup, 3160 Anum_pg_proc_proargdefaults, 3161 &isnull); 3162 if (isnull) 3163 { 3164 ReleaseSysCache(proctup); 3165 PG_RETURN_NULL(); 3166 } 3167 3168 str = TextDatumGetCString(proargdefaults); 3169 argdefaults = castNode(List, stringToNode(str)); 3170 pfree(str); 3171 3172 proc = (Form_pg_proc) GETSTRUCT(proctup); 3173 3174 /* 3175 * Calculate index into proargdefaults: proargdefaults corresponds to the 3176 * last N input arguments, where N = pronargdefaults. 3177 */ 3178 nth_default = nth_inputarg - 1 - (proc->pronargs - proc->pronargdefaults); 3179 3180 if (nth_default < 0 || nth_default >= list_length(argdefaults)) 3181 { 3182 ReleaseSysCache(proctup); 3183 PG_RETURN_NULL(); 3184 } 3185 node = list_nth(argdefaults, nth_default); 3186 str = deparse_expression(node, NIL, false, false); 3187 3188 ReleaseSysCache(proctup); 3189 3190 PG_RETURN_TEXT_P(string_to_text(str)); 3191 } 3192 3193 3194 /* 3195 * deparse_expression - General utility for deparsing expressions 3196 * 3197 * calls deparse_expression_pretty with all prettyPrinting disabled 3198 */ 3199 char * 3200 deparse_expression(Node *expr, List *dpcontext, 3201 bool forceprefix, bool showimplicit) 3202 { 3203 return deparse_expression_pretty(expr, dpcontext, forceprefix, 3204 showimplicit, 0, 0); 3205 } 3206 3207 /* ---------- 3208 * deparse_expression_pretty - General utility for deparsing expressions 3209 * 3210 * expr is the node tree to be deparsed. It must be a transformed expression 3211 * tree (ie, not the raw output of gram.y). 3212 * 3213 * dpcontext is a list of deparse_namespace nodes representing the context 3214 * for interpreting Vars in the node tree. It can be NIL if no Vars are 3215 * expected. 3216 * 3217 * forceprefix is true to force all Vars to be prefixed with their table names. 3218 * 3219 * showimplicit is true to force all implicit casts to be shown explicitly. 3220 * 3221 * Tries to pretty up the output according to prettyFlags and startIndent. 3222 * 3223 * The result is a palloc'd string. 3224 * ---------- 3225 */ 3226 static char * 3227 deparse_expression_pretty(Node *expr, List *dpcontext, 3228 bool forceprefix, bool showimplicit, 3229 int prettyFlags, int startIndent) 3230 { 3231 StringInfoData buf; 3232 deparse_context context; 3233 3234 initStringInfo(&buf); 3235 context.buf = &buf; 3236 context.namespaces = dpcontext; 3237 context.windowClause = NIL; 3238 context.windowTList = NIL; 3239 context.varprefix = forceprefix; 3240 context.prettyFlags = prettyFlags; 3241 context.wrapColumn = WRAP_COLUMN_DEFAULT; 3242 context.indentLevel = startIndent; 3243 context.special_exprkind = EXPR_KIND_NONE; 3244 3245 get_rule_expr(expr, &context, showimplicit); 3246 3247 return buf.data; 3248 } 3249 3250 /* ---------- 3251 * deparse_context_for - Build deparse context for a single relation 3252 * 3253 * Given the reference name (alias) and OID of a relation, build deparsing 3254 * context for an expression referencing only that relation (as varno 1, 3255 * varlevelsup 0). This is sufficient for many uses of deparse_expression. 3256 * ---------- 3257 */ 3258 List * 3259 deparse_context_for(const char *aliasname, Oid relid) 3260 { 3261 deparse_namespace *dpns; 3262 RangeTblEntry *rte; 3263 3264 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace)); 3265 3266 /* Build a minimal RTE for the rel */ 3267 rte = makeNode(RangeTblEntry); 3268 rte->rtekind = RTE_RELATION; 3269 rte->relid = relid; 3270 rte->relkind = RELKIND_RELATION; /* no need for exactness here */ 3271 rte->rellockmode = AccessShareLock; 3272 rte->alias = makeAlias(aliasname, NIL); 3273 rte->eref = rte->alias; 3274 rte->lateral = false; 3275 rte->inh = false; 3276 rte->inFromCl = true; 3277 3278 /* Build one-element rtable */ 3279 dpns->rtable = list_make1(rte); 3280 dpns->ctes = NIL; 3281 set_rtable_names(dpns, NIL, NULL); 3282 set_simple_column_names(dpns); 3283 3284 /* Return a one-deep namespace stack */ 3285 return list_make1(dpns); 3286 } 3287 3288 /* 3289 * deparse_context_for_plan_rtable - Build deparse context for a plan's rtable 3290 * 3291 * When deparsing an expression in a Plan tree, we use the plan's rangetable 3292 * to resolve names of simple Vars. The initialization of column names for 3293 * this is rather expensive if the rangetable is large, and it'll be the same 3294 * for every expression in the Plan tree; so we do it just once and re-use 3295 * the result of this function for each expression. (Note that the result 3296 * is not usable until set_deparse_context_planstate() is applied to it.) 3297 * 3298 * In addition to the plan's rangetable list, pass the per-RTE alias names 3299 * assigned by a previous call to select_rtable_names_for_explain. 3300 */ 3301 List * 3302 deparse_context_for_plan_rtable(List *rtable, List *rtable_names) 3303 { 3304 deparse_namespace *dpns; 3305 3306 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace)); 3307 3308 /* Initialize fields that stay the same across the whole plan tree */ 3309 dpns->rtable = rtable; 3310 dpns->rtable_names = rtable_names; 3311 dpns->ctes = NIL; 3312 3313 /* 3314 * Set up column name aliases. We will get rather bogus results for join 3315 * RTEs, but that doesn't matter because plan trees don't contain any join 3316 * alias Vars. 3317 */ 3318 set_simple_column_names(dpns); 3319 3320 /* Return a one-deep namespace stack */ 3321 return list_make1(dpns); 3322 } 3323 3324 /* 3325 * set_deparse_context_planstate - Specify Plan node containing expression 3326 * 3327 * When deparsing an expression in a Plan tree, we might have to resolve 3328 * OUTER_VAR, INNER_VAR, or INDEX_VAR references. To do this, the caller must 3329 * provide the parent PlanState node. Then OUTER_VAR and INNER_VAR references 3330 * can be resolved by drilling down into the left and right child plans. 3331 * Similarly, INDEX_VAR references can be resolved by reference to the 3332 * indextlist given in a parent IndexOnlyScan node, or to the scan tlist in 3333 * ForeignScan and CustomScan nodes. (Note that we don't currently support 3334 * deparsing of indexquals in regular IndexScan or BitmapIndexScan nodes; 3335 * for those, we can only deparse the indexqualorig fields, which won't 3336 * contain INDEX_VAR Vars.) 3337 * 3338 * Note: planstate really ought to be declared as "PlanState *", but we use 3339 * "Node *" to avoid having to include execnodes.h in ruleutils.h. 3340 * 3341 * The ancestors list is a list of the PlanState's parent PlanStates, the 3342 * most-closely-nested first. This is needed to resolve PARAM_EXEC Params. 3343 * Note we assume that all the PlanStates share the same rtable. 3344 * 3345 * Once this function has been called, deparse_expression() can be called on 3346 * subsidiary expression(s) of the specified PlanState node. To deparse 3347 * expressions of a different Plan node in the same Plan tree, re-call this 3348 * function to identify the new parent Plan node. 3349 * 3350 * The result is the same List passed in; this is a notational convenience. 3351 */ 3352 List * 3353 set_deparse_context_planstate(List *dpcontext, 3354 Node *planstate, List *ancestors) 3355 { 3356 deparse_namespace *dpns; 3357 3358 /* Should always have one-entry namespace list for Plan deparsing */ 3359 Assert(list_length(dpcontext) == 1); 3360 dpns = (deparse_namespace *) linitial(dpcontext); 3361 3362 /* Set our attention on the specific plan node passed in */ 3363 set_deparse_planstate(dpns, (PlanState *) planstate); 3364 dpns->ancestors = ancestors; 3365 3366 return dpcontext; 3367 } 3368 3369 /* 3370 * select_rtable_names_for_explain - Select RTE aliases for EXPLAIN 3371 * 3372 * Determine the relation aliases we'll use during an EXPLAIN operation. 3373 * This is just a frontend to set_rtable_names. We have to expose the aliases 3374 * to EXPLAIN because EXPLAIN needs to know the right alias names to print. 3375 */ 3376 List * 3377 select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used) 3378 { 3379 deparse_namespace dpns; 3380 3381 memset(&dpns, 0, sizeof(dpns)); 3382 dpns.rtable = rtable; 3383 dpns.ctes = NIL; 3384 set_rtable_names(&dpns, NIL, rels_used); 3385 /* We needn't bother computing column aliases yet */ 3386 3387 return dpns.rtable_names; 3388 } 3389 3390 /* 3391 * set_rtable_names: select RTE aliases to be used in printing a query 3392 * 3393 * We fill in dpns->rtable_names with a list of names that is one-for-one with 3394 * the already-filled dpns->rtable list. Each RTE name is unique among those 3395 * in the new namespace plus any ancestor namespaces listed in 3396 * parent_namespaces. 3397 * 3398 * If rels_used isn't NULL, only RTE indexes listed in it are given aliases. 3399 * 3400 * Note that this function is only concerned with relation names, not column 3401 * names. 3402 */ 3403 static void 3404 set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, 3405 Bitmapset *rels_used) 3406 { 3407 HASHCTL hash_ctl; 3408 HTAB *names_hash; 3409 NameHashEntry *hentry; 3410 bool found; 3411 int rtindex; 3412 ListCell *lc; 3413 3414 dpns->rtable_names = NIL; 3415 /* nothing more to do if empty rtable */ 3416 if (dpns->rtable == NIL) 3417 return; 3418 3419 /* 3420 * We use a hash table to hold known names, so that this process is O(N) 3421 * not O(N^2) for N names. 3422 */ 3423 MemSet(&hash_ctl, 0, sizeof(hash_ctl)); 3424 hash_ctl.keysize = NAMEDATALEN; 3425 hash_ctl.entrysize = sizeof(NameHashEntry); 3426 hash_ctl.hcxt = CurrentMemoryContext; 3427 names_hash = hash_create("set_rtable_names names", 3428 list_length(dpns->rtable), 3429 &hash_ctl, 3430 HASH_ELEM | HASH_CONTEXT); 3431 /* Preload the hash table with names appearing in parent_namespaces */ 3432 foreach(lc, parent_namespaces) 3433 { 3434 deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc); 3435 ListCell *lc2; 3436 3437 foreach(lc2, olddpns->rtable_names) 3438 { 3439 char *oldname = (char *) lfirst(lc2); 3440 3441 if (oldname == NULL) 3442 continue; 3443 hentry = (NameHashEntry *) hash_search(names_hash, 3444 oldname, 3445 HASH_ENTER, 3446 &found); 3447 /* we do not complain about duplicate names in parent namespaces */ 3448 hentry->counter = 0; 3449 } 3450 } 3451 3452 /* Now we can scan the rtable */ 3453 rtindex = 1; 3454 foreach(lc, dpns->rtable) 3455 { 3456 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); 3457 char *refname; 3458 3459 /* Just in case this takes an unreasonable amount of time ... */ 3460 CHECK_FOR_INTERRUPTS(); 3461 3462 if (rels_used && !bms_is_member(rtindex, rels_used)) 3463 { 3464 /* Ignore unreferenced RTE */ 3465 refname = NULL; 3466 } 3467 else if (rte->alias) 3468 { 3469 /* If RTE has a user-defined alias, prefer that */ 3470 refname = rte->alias->aliasname; 3471 } 3472 else if (rte->rtekind == RTE_RELATION) 3473 { 3474 /* Use the current actual name of the relation */ 3475 refname = get_rel_name(rte->relid); 3476 } 3477 else if (rte->rtekind == RTE_JOIN) 3478 { 3479 /* Unnamed join has no refname */ 3480 refname = NULL; 3481 } 3482 else 3483 { 3484 /* Otherwise use whatever the parser assigned */ 3485 refname = rte->eref->aliasname; 3486 } 3487 3488 /* 3489 * If the selected name isn't unique, append digits to make it so, and 3490 * make a new hash entry for it once we've got a unique name. For a 3491 * very long input name, we might have to truncate to stay within 3492 * NAMEDATALEN. 3493 */ 3494 if (refname) 3495 { 3496 hentry = (NameHashEntry *) hash_search(names_hash, 3497 refname, 3498 HASH_ENTER, 3499 &found); 3500 if (found) 3501 { 3502 /* Name already in use, must choose a new one */ 3503 int refnamelen = strlen(refname); 3504 char *modname = (char *) palloc(refnamelen + 16); 3505 NameHashEntry *hentry2; 3506 3507 do 3508 { 3509 hentry->counter++; 3510 for (;;) 3511 { 3512 /* 3513 * We avoid using %.*s here because it can misbehave 3514 * if the data is not valid in what libc thinks is the 3515 * prevailing encoding. 3516 */ 3517 memcpy(modname, refname, refnamelen); 3518 sprintf(modname + refnamelen, "_%d", hentry->counter); 3519 if (strlen(modname) < NAMEDATALEN) 3520 break; 3521 /* drop chars from refname to keep all the digits */ 3522 refnamelen = pg_mbcliplen(refname, refnamelen, 3523 refnamelen - 1); 3524 } 3525 hentry2 = (NameHashEntry *) hash_search(names_hash, 3526 modname, 3527 HASH_ENTER, 3528 &found); 3529 } while (found); 3530 hentry2->counter = 0; /* init new hash entry */ 3531 refname = modname; 3532 } 3533 else 3534 { 3535 /* Name not previously used, need only initialize hentry */ 3536 hentry->counter = 0; 3537 } 3538 } 3539 3540 dpns->rtable_names = lappend(dpns->rtable_names, refname); 3541 rtindex++; 3542 } 3543 3544 hash_destroy(names_hash); 3545 } 3546 3547 /* 3548 * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree 3549 * 3550 * For convenience, this is defined to initialize the deparse_namespace struct 3551 * from scratch. 3552 */ 3553 static void 3554 set_deparse_for_query(deparse_namespace *dpns, Query *query, 3555 List *parent_namespaces) 3556 { 3557 ListCell *lc; 3558 ListCell *lc2; 3559 3560 /* Initialize *dpns and fill rtable/ctes links */ 3561 memset(dpns, 0, sizeof(deparse_namespace)); 3562 dpns->rtable = query->rtable; 3563 dpns->ctes = query->cteList; 3564 3565 /* Assign a unique relation alias to each RTE */ 3566 set_rtable_names(dpns, parent_namespaces, NULL); 3567 3568 /* Initialize dpns->rtable_columns to contain zeroed structs */ 3569 dpns->rtable_columns = NIL; 3570 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable)) 3571 dpns->rtable_columns = lappend(dpns->rtable_columns, 3572 palloc0(sizeof(deparse_columns))); 3573 3574 /* If it's a utility query, it won't have a jointree */ 3575 if (query->jointree) 3576 { 3577 /* Detect whether global uniqueness of USING names is needed */ 3578 dpns->unique_using = 3579 has_dangerous_join_using(dpns, (Node *) query->jointree); 3580 3581 /* 3582 * Select names for columns merged by USING, via a recursive pass over 3583 * the query jointree. 3584 */ 3585 set_using_names(dpns, (Node *) query->jointree, NIL); 3586 } 3587 3588 /* 3589 * Now assign remaining column aliases for each RTE. We do this in a 3590 * linear scan of the rtable, so as to process RTEs whether or not they 3591 * are in the jointree (we mustn't miss NEW.*, INSERT target relations, 3592 * etc). JOIN RTEs must be processed after their children, but this is 3593 * okay because they appear later in the rtable list than their children 3594 * (cf Asserts in identify_join_columns()). 3595 */ 3596 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns) 3597 { 3598 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); 3599 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2); 3600 3601 if (rte->rtekind == RTE_JOIN) 3602 set_join_column_names(dpns, rte, colinfo); 3603 else 3604 set_relation_column_names(dpns, rte, colinfo); 3605 } 3606 } 3607 3608 /* 3609 * set_simple_column_names: fill in column aliases for non-query situations 3610 * 3611 * This handles EXPLAIN and cases where we only have relation RTEs. Without 3612 * a join tree, we can't do anything smart about join RTEs, but we don't 3613 * need to (note that EXPLAIN should never see join alias Vars anyway). 3614 * If we do hit a join RTE we'll just process it like a non-table base RTE. 3615 */ 3616 static void 3617 set_simple_column_names(deparse_namespace *dpns) 3618 { 3619 ListCell *lc; 3620 ListCell *lc2; 3621 3622 /* Initialize dpns->rtable_columns to contain zeroed structs */ 3623 dpns->rtable_columns = NIL; 3624 while (list_length(dpns->rtable_columns) < list_length(dpns->rtable)) 3625 dpns->rtable_columns = lappend(dpns->rtable_columns, 3626 palloc0(sizeof(deparse_columns))); 3627 3628 /* Assign unique column aliases within each RTE */ 3629 forboth(lc, dpns->rtable, lc2, dpns->rtable_columns) 3630 { 3631 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); 3632 deparse_columns *colinfo = (deparse_columns *) lfirst(lc2); 3633 3634 set_relation_column_names(dpns, rte, colinfo); 3635 } 3636 } 3637 3638 /* 3639 * has_dangerous_join_using: search jointree for unnamed JOIN USING 3640 * 3641 * Merged columns of a JOIN USING may act differently from either of the input 3642 * columns, either because they are merged with COALESCE (in a FULL JOIN) or 3643 * because an implicit coercion of the underlying input column is required. 3644 * In such a case the column must be referenced as a column of the JOIN not as 3645 * a column of either input. And this is problematic if the join is unnamed 3646 * (alias-less): we cannot qualify the column's name with an RTE name, since 3647 * there is none. (Forcibly assigning an alias to the join is not a solution, 3648 * since that will prevent legal references to tables below the join.) 3649 * To ensure that every column in the query is unambiguously referenceable, 3650 * we must assign such merged columns names that are globally unique across 3651 * the whole query, aliasing other columns out of the way as necessary. 3652 * 3653 * Because the ensuing re-aliasing is fairly damaging to the readability of 3654 * the query, we don't do this unless we have to. So, we must pre-scan 3655 * the join tree to see if we have to, before starting set_using_names(). 3656 */ 3657 static bool 3658 has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode) 3659 { 3660 if (IsA(jtnode, RangeTblRef)) 3661 { 3662 /* nothing to do here */ 3663 } 3664 else if (IsA(jtnode, FromExpr)) 3665 { 3666 FromExpr *f = (FromExpr *) jtnode; 3667 ListCell *lc; 3668 3669 foreach(lc, f->fromlist) 3670 { 3671 if (has_dangerous_join_using(dpns, (Node *) lfirst(lc))) 3672 return true; 3673 } 3674 } 3675 else if (IsA(jtnode, JoinExpr)) 3676 { 3677 JoinExpr *j = (JoinExpr *) jtnode; 3678 3679 /* Is it an unnamed JOIN with USING? */ 3680 if (j->alias == NULL && j->usingClause) 3681 { 3682 /* 3683 * Yes, so check each join alias var to see if any of them are not 3684 * simple references to underlying columns. If so, we have a 3685 * dangerous situation and must pick unique aliases. 3686 */ 3687 RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable); 3688 ListCell *lc; 3689 3690 foreach(lc, jrte->joinaliasvars) 3691 { 3692 Var *aliasvar = (Var *) lfirst(lc); 3693 3694 if (aliasvar != NULL && !IsA(aliasvar, Var)) 3695 return true; 3696 } 3697 } 3698 3699 /* Nope, but inspect children */ 3700 if (has_dangerous_join_using(dpns, j->larg)) 3701 return true; 3702 if (has_dangerous_join_using(dpns, j->rarg)) 3703 return true; 3704 } 3705 else 3706 elog(ERROR, "unrecognized node type: %d", 3707 (int) nodeTag(jtnode)); 3708 return false; 3709 } 3710 3711 /* 3712 * set_using_names: select column aliases to be used for merged USING columns 3713 * 3714 * We do this during a recursive descent of the query jointree. 3715 * dpns->unique_using must already be set to determine the global strategy. 3716 * 3717 * Column alias info is saved in the dpns->rtable_columns list, which is 3718 * assumed to be filled with pre-zeroed deparse_columns structs. 3719 * 3720 * parentUsing is a list of all USING aliases assigned in parent joins of 3721 * the current jointree node. (The passed-in list must not be modified.) 3722 */ 3723 static void 3724 set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing) 3725 { 3726 if (IsA(jtnode, RangeTblRef)) 3727 { 3728 /* nothing to do now */ 3729 } 3730 else if (IsA(jtnode, FromExpr)) 3731 { 3732 FromExpr *f = (FromExpr *) jtnode; 3733 ListCell *lc; 3734 3735 foreach(lc, f->fromlist) 3736 set_using_names(dpns, (Node *) lfirst(lc), parentUsing); 3737 } 3738 else if (IsA(jtnode, JoinExpr)) 3739 { 3740 JoinExpr *j = (JoinExpr *) jtnode; 3741 RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable); 3742 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); 3743 int *leftattnos; 3744 int *rightattnos; 3745 deparse_columns *leftcolinfo; 3746 deparse_columns *rightcolinfo; 3747 int i; 3748 ListCell *lc; 3749 3750 /* Get info about the shape of the join */ 3751 identify_join_columns(j, rte, colinfo); 3752 leftattnos = colinfo->leftattnos; 3753 rightattnos = colinfo->rightattnos; 3754 3755 /* Look up the not-yet-filled-in child deparse_columns structs */ 3756 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); 3757 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); 3758 3759 /* 3760 * If this join is unnamed, then we cannot substitute new aliases at 3761 * this level, so any name requirements pushed down to here must be 3762 * pushed down again to the children. 3763 */ 3764 if (rte->alias == NULL) 3765 { 3766 for (i = 0; i < colinfo->num_cols; i++) 3767 { 3768 char *colname = colinfo->colnames[i]; 3769 3770 if (colname == NULL) 3771 continue; 3772 3773 /* Push down to left column, unless it's a system column */ 3774 if (leftattnos[i] > 0) 3775 { 3776 expand_colnames_array_to(leftcolinfo, leftattnos[i]); 3777 leftcolinfo->colnames[leftattnos[i] - 1] = colname; 3778 } 3779 3780 /* Same on the righthand side */ 3781 if (rightattnos[i] > 0) 3782 { 3783 expand_colnames_array_to(rightcolinfo, rightattnos[i]); 3784 rightcolinfo->colnames[rightattnos[i] - 1] = colname; 3785 } 3786 } 3787 } 3788 3789 /* 3790 * If there's a USING clause, select the USING column names and push 3791 * those names down to the children. We have two strategies: 3792 * 3793 * If dpns->unique_using is true, we force all USING names to be 3794 * unique across the whole query level. In principle we'd only need 3795 * the names of dangerous USING columns to be globally unique, but to 3796 * safely assign all USING names in a single pass, we have to enforce 3797 * the same uniqueness rule for all of them. However, if a USING 3798 * column's name has been pushed down from the parent, we should use 3799 * it as-is rather than making a uniqueness adjustment. This is 3800 * necessary when we're at an unnamed join, and it creates no risk of 3801 * ambiguity. Also, if there's a user-written output alias for a 3802 * merged column, we prefer to use that rather than the input name; 3803 * this simplifies the logic and seems likely to lead to less aliasing 3804 * overall. 3805 * 3806 * If dpns->unique_using is false, we only need USING names to be 3807 * unique within their own join RTE. We still need to honor 3808 * pushed-down names, though. 3809 * 3810 * Though significantly different in results, these two strategies are 3811 * implemented by the same code, with only the difference of whether 3812 * to put assigned names into dpns->using_names. 3813 */ 3814 if (j->usingClause) 3815 { 3816 /* Copy the input parentUsing list so we don't modify it */ 3817 parentUsing = list_copy(parentUsing); 3818 3819 /* USING names must correspond to the first join output columns */ 3820 expand_colnames_array_to(colinfo, list_length(j->usingClause)); 3821 i = 0; 3822 foreach(lc, j->usingClause) 3823 { 3824 char *colname = strVal(lfirst(lc)); 3825 3826 /* Assert it's a merged column */ 3827 Assert(leftattnos[i] != 0 && rightattnos[i] != 0); 3828 3829 /* Adopt passed-down name if any, else select unique name */ 3830 if (colinfo->colnames[i] != NULL) 3831 colname = colinfo->colnames[i]; 3832 else 3833 { 3834 /* Prefer user-written output alias if any */ 3835 if (rte->alias && i < list_length(rte->alias->colnames)) 3836 colname = strVal(list_nth(rte->alias->colnames, i)); 3837 /* Make it appropriately unique */ 3838 colname = make_colname_unique(colname, dpns, colinfo); 3839 if (dpns->unique_using) 3840 dpns->using_names = lappend(dpns->using_names, 3841 colname); 3842 /* Save it as output column name, too */ 3843 colinfo->colnames[i] = colname; 3844 } 3845 3846 /* Remember selected names for use later */ 3847 colinfo->usingNames = lappend(colinfo->usingNames, colname); 3848 parentUsing = lappend(parentUsing, colname); 3849 3850 /* Push down to left column, unless it's a system column */ 3851 if (leftattnos[i] > 0) 3852 { 3853 expand_colnames_array_to(leftcolinfo, leftattnos[i]); 3854 leftcolinfo->colnames[leftattnos[i] - 1] = colname; 3855 } 3856 3857 /* Same on the righthand side */ 3858 if (rightattnos[i] > 0) 3859 { 3860 expand_colnames_array_to(rightcolinfo, rightattnos[i]); 3861 rightcolinfo->colnames[rightattnos[i] - 1] = colname; 3862 } 3863 3864 i++; 3865 } 3866 } 3867 3868 /* Mark child deparse_columns structs with correct parentUsing info */ 3869 leftcolinfo->parentUsing = parentUsing; 3870 rightcolinfo->parentUsing = parentUsing; 3871 3872 /* Now recursively assign USING column names in children */ 3873 set_using_names(dpns, j->larg, parentUsing); 3874 set_using_names(dpns, j->rarg, parentUsing); 3875 } 3876 else 3877 elog(ERROR, "unrecognized node type: %d", 3878 (int) nodeTag(jtnode)); 3879 } 3880 3881 /* 3882 * set_relation_column_names: select column aliases for a non-join RTE 3883 * 3884 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. 3885 * If any colnames entries are already filled in, those override local 3886 * choices. 3887 */ 3888 static void 3889 set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, 3890 deparse_columns *colinfo) 3891 { 3892 int ncolumns; 3893 char **real_colnames; 3894 bool changed_any; 3895 int noldcolumns; 3896 int i; 3897 int j; 3898 3899 /* 3900 * Extract the RTE's "real" column names. This is comparable to 3901 * get_rte_attribute_name, except that it's important to disregard dropped 3902 * columns. We put NULL into the array for a dropped column. 3903 */ 3904 if (rte->rtekind == RTE_RELATION) 3905 { 3906 /* Relation --- look to the system catalogs for up-to-date info */ 3907 Relation rel; 3908 TupleDesc tupdesc; 3909 3910 rel = relation_open(rte->relid, AccessShareLock); 3911 tupdesc = RelationGetDescr(rel); 3912 3913 ncolumns = tupdesc->natts; 3914 real_colnames = (char **) palloc(ncolumns * sizeof(char *)); 3915 3916 for (i = 0; i < ncolumns; i++) 3917 { 3918 Form_pg_attribute attr = TupleDescAttr(tupdesc, i); 3919 3920 if (attr->attisdropped) 3921 real_colnames[i] = NULL; 3922 else 3923 real_colnames[i] = pstrdup(NameStr(attr->attname)); 3924 } 3925 relation_close(rel, AccessShareLock); 3926 } 3927 else 3928 { 3929 /* Otherwise use the column names from eref */ 3930 ListCell *lc; 3931 3932 ncolumns = list_length(rte->eref->colnames); 3933 real_colnames = (char **) palloc(ncolumns * sizeof(char *)); 3934 3935 i = 0; 3936 foreach(lc, rte->eref->colnames) 3937 { 3938 /* 3939 * If the column name shown in eref is an empty string, then it's 3940 * a column that was dropped at the time of parsing the query, so 3941 * treat it as dropped. 3942 */ 3943 char *cname = strVal(lfirst(lc)); 3944 3945 if (cname[0] == '\0') 3946 cname = NULL; 3947 real_colnames[i] = cname; 3948 i++; 3949 } 3950 } 3951 3952 /* 3953 * Ensure colinfo->colnames has a slot for each column. (It could be long 3954 * enough already, if we pushed down a name for the last column.) Note: 3955 * it's possible that there are now more columns than there were when the 3956 * query was parsed, ie colnames could be longer than rte->eref->colnames. 3957 * We must assign unique aliases to the new columns too, else there could 3958 * be unresolved conflicts when the view/rule is reloaded. 3959 */ 3960 expand_colnames_array_to(colinfo, ncolumns); 3961 Assert(colinfo->num_cols == ncolumns); 3962 3963 /* 3964 * Make sufficiently large new_colnames and is_new_col arrays, too. 3965 * 3966 * Note: because we leave colinfo->num_new_cols zero until after the loop, 3967 * colname_is_unique will not consult that array, which is fine because it 3968 * would only be duplicate effort. 3969 */ 3970 colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *)); 3971 colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool)); 3972 3973 /* 3974 * Scan the columns, select a unique alias for each one, and store it in 3975 * colinfo->colnames and colinfo->new_colnames. The former array has NULL 3976 * entries for dropped columns, the latter omits them. Also mark 3977 * new_colnames entries as to whether they are new since parse time; this 3978 * is the case for entries beyond the length of rte->eref->colnames. 3979 */ 3980 noldcolumns = list_length(rte->eref->colnames); 3981 changed_any = false; 3982 j = 0; 3983 for (i = 0; i < ncolumns; i++) 3984 { 3985 char *real_colname = real_colnames[i]; 3986 char *colname = colinfo->colnames[i]; 3987 3988 /* Skip dropped columns */ 3989 if (real_colname == NULL) 3990 { 3991 Assert(colname == NULL); /* colnames[i] is already NULL */ 3992 continue; 3993 } 3994 3995 /* If alias already assigned, that's what to use */ 3996 if (colname == NULL) 3997 { 3998 /* If user wrote an alias, prefer that over real column name */ 3999 if (rte->alias && i < list_length(rte->alias->colnames)) 4000 colname = strVal(list_nth(rte->alias->colnames, i)); 4001 else 4002 colname = real_colname; 4003 4004 /* Unique-ify and insert into colinfo */ 4005 colname = make_colname_unique(colname, dpns, colinfo); 4006 4007 colinfo->colnames[i] = colname; 4008 } 4009 4010 /* Put names of non-dropped columns in new_colnames[] too */ 4011 colinfo->new_colnames[j] = colname; 4012 /* And mark them as new or not */ 4013 colinfo->is_new_col[j] = (i >= noldcolumns); 4014 j++; 4015 4016 /* Remember if any assigned aliases differ from "real" name */ 4017 if (!changed_any && strcmp(colname, real_colname) != 0) 4018 changed_any = true; 4019 } 4020 4021 /* 4022 * Set correct length for new_colnames[] array. (Note: if columns have 4023 * been added, colinfo->num_cols includes them, which is not really quite 4024 * right but is harmless, since any new columns must be at the end where 4025 * they won't affect varattnos of pre-existing columns.) 4026 */ 4027 colinfo->num_new_cols = j; 4028 4029 /* 4030 * For a relation RTE, we need only print the alias column names if any 4031 * are different from the underlying "real" names. For a function RTE, 4032 * always emit a complete column alias list; this is to protect against 4033 * possible instability of the default column names (eg, from altering 4034 * parameter names). For tablefunc RTEs, we never print aliases, because 4035 * the column names are part of the clause itself. For other RTE types, 4036 * print if we changed anything OR if there were user-written column 4037 * aliases (since the latter would be part of the underlying "reality"). 4038 */ 4039 if (rte->rtekind == RTE_RELATION) 4040 colinfo->printaliases = changed_any; 4041 else if (rte->rtekind == RTE_FUNCTION) 4042 colinfo->printaliases = true; 4043 else if (rte->rtekind == RTE_TABLEFUNC) 4044 colinfo->printaliases = false; 4045 else if (rte->alias && rte->alias->colnames != NIL) 4046 colinfo->printaliases = true; 4047 else 4048 colinfo->printaliases = changed_any; 4049 } 4050 4051 /* 4052 * set_join_column_names: select column aliases for a join RTE 4053 * 4054 * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. 4055 * If any colnames entries are already filled in, those override local 4056 * choices. Also, names for USING columns were already chosen by 4057 * set_using_names(). We further expect that column alias selection has been 4058 * completed for both input RTEs. 4059 */ 4060 static void 4061 set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, 4062 deparse_columns *colinfo) 4063 { 4064 deparse_columns *leftcolinfo; 4065 deparse_columns *rightcolinfo; 4066 bool changed_any; 4067 int noldcolumns; 4068 int nnewcolumns; 4069 Bitmapset *leftmerged = NULL; 4070 Bitmapset *rightmerged = NULL; 4071 int i; 4072 int j; 4073 int ic; 4074 int jc; 4075 4076 /* Look up the previously-filled-in child deparse_columns structs */ 4077 leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); 4078 rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); 4079 4080 /* 4081 * Ensure colinfo->colnames has a slot for each column. (It could be long 4082 * enough already, if we pushed down a name for the last column.) Note: 4083 * it's possible that one or both inputs now have more columns than there 4084 * were when the query was parsed, but we'll deal with that below. We 4085 * only need entries in colnames for pre-existing columns. 4086 */ 4087 noldcolumns = list_length(rte->eref->colnames); 4088 expand_colnames_array_to(colinfo, noldcolumns); 4089 Assert(colinfo->num_cols == noldcolumns); 4090 4091 /* 4092 * Scan the join output columns, select an alias for each one, and store 4093 * it in colinfo->colnames. If there are USING columns, set_using_names() 4094 * already selected their names, so we can start the loop at the first 4095 * non-merged column. 4096 */ 4097 changed_any = false; 4098 for (i = list_length(colinfo->usingNames); i < noldcolumns; i++) 4099 { 4100 char *colname = colinfo->colnames[i]; 4101 char *real_colname; 4102 4103 /* Ignore dropped column (only possible for non-merged column) */ 4104 if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0) 4105 { 4106 Assert(colname == NULL); 4107 continue; 4108 } 4109 4110 /* Get the child column name */ 4111 if (colinfo->leftattnos[i] > 0) 4112 real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1]; 4113 else if (colinfo->rightattnos[i] > 0) 4114 real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1]; 4115 else 4116 { 4117 /* We're joining system columns --- use eref name */ 4118 real_colname = strVal(list_nth(rte->eref->colnames, i)); 4119 } 4120 Assert(real_colname != NULL); 4121 4122 /* In an unnamed join, just report child column names as-is */ 4123 if (rte->alias == NULL) 4124 { 4125 colinfo->colnames[i] = real_colname; 4126 continue; 4127 } 4128 4129 /* If alias already assigned, that's what to use */ 4130 if (colname == NULL) 4131 { 4132 /* If user wrote an alias, prefer that over real column name */ 4133 if (rte->alias && i < list_length(rte->alias->colnames)) 4134 colname = strVal(list_nth(rte->alias->colnames, i)); 4135 else 4136 colname = real_colname; 4137 4138 /* Unique-ify and insert into colinfo */ 4139 colname = make_colname_unique(colname, dpns, colinfo); 4140 4141 colinfo->colnames[i] = colname; 4142 } 4143 4144 /* Remember if any assigned aliases differ from "real" name */ 4145 if (!changed_any && strcmp(colname, real_colname) != 0) 4146 changed_any = true; 4147 } 4148 4149 /* 4150 * Calculate number of columns the join would have if it were re-parsed 4151 * now, and create storage for the new_colnames and is_new_col arrays. 4152 * 4153 * Note: colname_is_unique will be consulting new_colnames[] during the 4154 * loops below, so its not-yet-filled entries must be zeroes. 4155 */ 4156 nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols - 4157 list_length(colinfo->usingNames); 4158 colinfo->num_new_cols = nnewcolumns; 4159 colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *)); 4160 colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool)); 4161 4162 /* 4163 * Generating the new_colnames array is a bit tricky since any new columns 4164 * added since parse time must be inserted in the right places. This code 4165 * must match the parser, which will order a join's columns as merged 4166 * columns first (in USING-clause order), then non-merged columns from the 4167 * left input (in attnum order), then non-merged columns from the right 4168 * input (ditto). If one of the inputs is itself a join, its columns will 4169 * be ordered according to the same rule, which means newly-added columns 4170 * might not be at the end. We can figure out what's what by consulting 4171 * the leftattnos and rightattnos arrays plus the input is_new_col arrays. 4172 * 4173 * In these loops, i indexes leftattnos/rightattnos (so it's join varattno 4174 * less one), j indexes new_colnames/is_new_col, and ic/jc have similar 4175 * meanings for the current child RTE. 4176 */ 4177 4178 /* Handle merged columns; they are first and can't be new */ 4179 i = j = 0; 4180 while (i < noldcolumns && 4181 colinfo->leftattnos[i] != 0 && 4182 colinfo->rightattnos[i] != 0) 4183 { 4184 /* column name is already determined and known unique */ 4185 colinfo->new_colnames[j] = colinfo->colnames[i]; 4186 colinfo->is_new_col[j] = false; 4187 4188 /* build bitmapsets of child attnums of merged columns */ 4189 if (colinfo->leftattnos[i] > 0) 4190 leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]); 4191 if (colinfo->rightattnos[i] > 0) 4192 rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]); 4193 4194 i++, j++; 4195 } 4196 4197 /* Handle non-merged left-child columns */ 4198 ic = 0; 4199 for (jc = 0; jc < leftcolinfo->num_new_cols; jc++) 4200 { 4201 char *child_colname = leftcolinfo->new_colnames[jc]; 4202 4203 if (!leftcolinfo->is_new_col[jc]) 4204 { 4205 /* Advance ic to next non-dropped old column of left child */ 4206 while (ic < leftcolinfo->num_cols && 4207 leftcolinfo->colnames[ic] == NULL) 4208 ic++; 4209 Assert(ic < leftcolinfo->num_cols); 4210 ic++; 4211 /* If it is a merged column, we already processed it */ 4212 if (bms_is_member(ic, leftmerged)) 4213 continue; 4214 /* Else, advance i to the corresponding existing join column */ 4215 while (i < colinfo->num_cols && 4216 colinfo->colnames[i] == NULL) 4217 i++; 4218 Assert(i < colinfo->num_cols); 4219 Assert(ic == colinfo->leftattnos[i]); 4220 /* Use the already-assigned name of this column */ 4221 colinfo->new_colnames[j] = colinfo->colnames[i]; 4222 i++; 4223 } 4224 else 4225 { 4226 /* 4227 * Unique-ify the new child column name and assign, unless we're 4228 * in an unnamed join, in which case just copy 4229 */ 4230 if (rte->alias != NULL) 4231 { 4232 colinfo->new_colnames[j] = 4233 make_colname_unique(child_colname, dpns, colinfo); 4234 if (!changed_any && 4235 strcmp(colinfo->new_colnames[j], child_colname) != 0) 4236 changed_any = true; 4237 } 4238 else 4239 colinfo->new_colnames[j] = child_colname; 4240 } 4241 4242 colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc]; 4243 j++; 4244 } 4245 4246 /* Handle non-merged right-child columns in exactly the same way */ 4247 ic = 0; 4248 for (jc = 0; jc < rightcolinfo->num_new_cols; jc++) 4249 { 4250 char *child_colname = rightcolinfo->new_colnames[jc]; 4251 4252 if (!rightcolinfo->is_new_col[jc]) 4253 { 4254 /* Advance ic to next non-dropped old column of right child */ 4255 while (ic < rightcolinfo->num_cols && 4256 rightcolinfo->colnames[ic] == NULL) 4257 ic++; 4258 Assert(ic < rightcolinfo->num_cols); 4259 ic++; 4260 /* If it is a merged column, we already processed it */ 4261 if (bms_is_member(ic, rightmerged)) 4262 continue; 4263 /* Else, advance i to the corresponding existing join column */ 4264 while (i < colinfo->num_cols && 4265 colinfo->colnames[i] == NULL) 4266 i++; 4267 Assert(i < colinfo->num_cols); 4268 Assert(ic == colinfo->rightattnos[i]); 4269 /* Use the already-assigned name of this column */ 4270 colinfo->new_colnames[j] = colinfo->colnames[i]; 4271 i++; 4272 } 4273 else 4274 { 4275 /* 4276 * Unique-ify the new child column name and assign, unless we're 4277 * in an unnamed join, in which case just copy 4278 */ 4279 if (rte->alias != NULL) 4280 { 4281 colinfo->new_colnames[j] = 4282 make_colname_unique(child_colname, dpns, colinfo); 4283 if (!changed_any && 4284 strcmp(colinfo->new_colnames[j], child_colname) != 0) 4285 changed_any = true; 4286 } 4287 else 4288 colinfo->new_colnames[j] = child_colname; 4289 } 4290 4291 colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc]; 4292 j++; 4293 } 4294 4295 /* Assert we processed the right number of columns */ 4296 #ifdef USE_ASSERT_CHECKING 4297 while (i < colinfo->num_cols && colinfo->colnames[i] == NULL) 4298 i++; 4299 Assert(i == colinfo->num_cols); 4300 Assert(j == nnewcolumns); 4301 #endif 4302 4303 /* 4304 * For a named join, print column aliases if we changed any from the child 4305 * names. Unnamed joins cannot print aliases. 4306 */ 4307 if (rte->alias != NULL) 4308 colinfo->printaliases = changed_any; 4309 else 4310 colinfo->printaliases = false; 4311 } 4312 4313 /* 4314 * colname_is_unique: is colname distinct from already-chosen column names? 4315 * 4316 * dpns is query-wide info, colinfo is for the column's RTE 4317 */ 4318 static bool 4319 colname_is_unique(const char *colname, deparse_namespace *dpns, 4320 deparse_columns *colinfo) 4321 { 4322 int i; 4323 ListCell *lc; 4324 4325 /* Check against already-assigned column aliases within RTE */ 4326 for (i = 0; i < colinfo->num_cols; i++) 4327 { 4328 char *oldname = colinfo->colnames[i]; 4329 4330 if (oldname && strcmp(oldname, colname) == 0) 4331 return false; 4332 } 4333 4334 /* 4335 * If we're building a new_colnames array, check that too (this will be 4336 * partially but not completely redundant with the previous checks) 4337 */ 4338 for (i = 0; i < colinfo->num_new_cols; i++) 4339 { 4340 char *oldname = colinfo->new_colnames[i]; 4341 4342 if (oldname && strcmp(oldname, colname) == 0) 4343 return false; 4344 } 4345 4346 /* Also check against USING-column names that must be globally unique */ 4347 foreach(lc, dpns->using_names) 4348 { 4349 char *oldname = (char *) lfirst(lc); 4350 4351 if (strcmp(oldname, colname) == 0) 4352 return false; 4353 } 4354 4355 /* Also check against names already assigned for parent-join USING cols */ 4356 foreach(lc, colinfo->parentUsing) 4357 { 4358 char *oldname = (char *) lfirst(lc); 4359 4360 if (strcmp(oldname, colname) == 0) 4361 return false; 4362 } 4363 4364 return true; 4365 } 4366 4367 /* 4368 * make_colname_unique: modify colname if necessary to make it unique 4369 * 4370 * dpns is query-wide info, colinfo is for the column's RTE 4371 */ 4372 static char * 4373 make_colname_unique(char *colname, deparse_namespace *dpns, 4374 deparse_columns *colinfo) 4375 { 4376 /* 4377 * If the selected name isn't unique, append digits to make it so. For a 4378 * very long input name, we might have to truncate to stay within 4379 * NAMEDATALEN. 4380 */ 4381 if (!colname_is_unique(colname, dpns, colinfo)) 4382 { 4383 int colnamelen = strlen(colname); 4384 char *modname = (char *) palloc(colnamelen + 16); 4385 int i = 0; 4386 4387 do 4388 { 4389 i++; 4390 for (;;) 4391 { 4392 /* 4393 * We avoid using %.*s here because it can misbehave if the 4394 * data is not valid in what libc thinks is the prevailing 4395 * encoding. 4396 */ 4397 memcpy(modname, colname, colnamelen); 4398 sprintf(modname + colnamelen, "_%d", i); 4399 if (strlen(modname) < NAMEDATALEN) 4400 break; 4401 /* drop chars from colname to keep all the digits */ 4402 colnamelen = pg_mbcliplen(colname, colnamelen, 4403 colnamelen - 1); 4404 } 4405 } while (!colname_is_unique(modname, dpns, colinfo)); 4406 colname = modname; 4407 } 4408 return colname; 4409 } 4410 4411 /* 4412 * expand_colnames_array_to: make colinfo->colnames at least n items long 4413 * 4414 * Any added array entries are initialized to zero. 4415 */ 4416 static void 4417 expand_colnames_array_to(deparse_columns *colinfo, int n) 4418 { 4419 if (n > colinfo->num_cols) 4420 { 4421 if (colinfo->colnames == NULL) 4422 colinfo->colnames = (char **) palloc0(n * sizeof(char *)); 4423 else 4424 { 4425 colinfo->colnames = (char **) repalloc(colinfo->colnames, 4426 n * sizeof(char *)); 4427 memset(colinfo->colnames + colinfo->num_cols, 0, 4428 (n - colinfo->num_cols) * sizeof(char *)); 4429 } 4430 colinfo->num_cols = n; 4431 } 4432 } 4433 4434 /* 4435 * identify_join_columns: figure out where columns of a join come from 4436 * 4437 * Fills the join-specific fields of the colinfo struct, except for 4438 * usingNames which is filled later. 4439 */ 4440 static void 4441 identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, 4442 deparse_columns *colinfo) 4443 { 4444 int numjoincols; 4445 int i; 4446 ListCell *lc; 4447 4448 /* Extract left/right child RT indexes */ 4449 if (IsA(j->larg, RangeTblRef)) 4450 colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex; 4451 else if (IsA(j->larg, JoinExpr)) 4452 colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex; 4453 else 4454 elog(ERROR, "unrecognized node type in jointree: %d", 4455 (int) nodeTag(j->larg)); 4456 if (IsA(j->rarg, RangeTblRef)) 4457 colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex; 4458 else if (IsA(j->rarg, JoinExpr)) 4459 colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex; 4460 else 4461 elog(ERROR, "unrecognized node type in jointree: %d", 4462 (int) nodeTag(j->rarg)); 4463 4464 /* Assert children will be processed earlier than join in second pass */ 4465 Assert(colinfo->leftrti < j->rtindex); 4466 Assert(colinfo->rightrti < j->rtindex); 4467 4468 /* Initialize result arrays with zeroes */ 4469 numjoincols = list_length(jrte->joinaliasvars); 4470 Assert(numjoincols == list_length(jrte->eref->colnames)); 4471 colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int)); 4472 colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int)); 4473 4474 /* Scan the joinaliasvars list to identify simple column references */ 4475 i = 0; 4476 foreach(lc, jrte->joinaliasvars) 4477 { 4478 Var *aliasvar = (Var *) lfirst(lc); 4479 4480 /* get rid of any implicit coercion above the Var */ 4481 aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar); 4482 4483 if (aliasvar == NULL) 4484 { 4485 /* It's a dropped column; nothing to do here */ 4486 } 4487 else if (IsA(aliasvar, Var)) 4488 { 4489 Assert(aliasvar->varlevelsup == 0); 4490 Assert(aliasvar->varattno != 0); 4491 if (aliasvar->varno == colinfo->leftrti) 4492 colinfo->leftattnos[i] = aliasvar->varattno; 4493 else if (aliasvar->varno == colinfo->rightrti) 4494 colinfo->rightattnos[i] = aliasvar->varattno; 4495 else 4496 elog(ERROR, "unexpected varno %d in JOIN RTE", 4497 aliasvar->varno); 4498 } 4499 else if (IsA(aliasvar, CoalesceExpr)) 4500 { 4501 /* 4502 * It's a merged column in FULL JOIN USING. Ignore it for now and 4503 * let the code below identify the merged columns. 4504 */ 4505 } 4506 else 4507 elog(ERROR, "unrecognized node type in join alias vars: %d", 4508 (int) nodeTag(aliasvar)); 4509 4510 i++; 4511 } 4512 4513 /* 4514 * If there's a USING clause, deconstruct the join quals to identify the 4515 * merged columns. This is a tad painful but if we cannot rely on the 4516 * column names, there is no other representation of which columns were 4517 * joined by USING. (Unless the join type is FULL, we can't tell from the 4518 * joinaliasvars list which columns are merged.) Note: we assume that the 4519 * merged columns are the first output column(s) of the join. 4520 */ 4521 if (j->usingClause) 4522 { 4523 List *leftvars = NIL; 4524 List *rightvars = NIL; 4525 ListCell *lc2; 4526 4527 /* Extract left- and right-side Vars from the qual expression */ 4528 flatten_join_using_qual(j->quals, &leftvars, &rightvars); 4529 Assert(list_length(leftvars) == list_length(j->usingClause)); 4530 Assert(list_length(rightvars) == list_length(j->usingClause)); 4531 4532 /* Mark the output columns accordingly */ 4533 i = 0; 4534 forboth(lc, leftvars, lc2, rightvars) 4535 { 4536 Var *leftvar = (Var *) lfirst(lc); 4537 Var *rightvar = (Var *) lfirst(lc2); 4538 4539 Assert(leftvar->varlevelsup == 0); 4540 Assert(leftvar->varattno != 0); 4541 if (leftvar->varno != colinfo->leftrti) 4542 elog(ERROR, "unexpected varno %d in JOIN USING qual", 4543 leftvar->varno); 4544 colinfo->leftattnos[i] = leftvar->varattno; 4545 4546 Assert(rightvar->varlevelsup == 0); 4547 Assert(rightvar->varattno != 0); 4548 if (rightvar->varno != colinfo->rightrti) 4549 elog(ERROR, "unexpected varno %d in JOIN USING qual", 4550 rightvar->varno); 4551 colinfo->rightattnos[i] = rightvar->varattno; 4552 4553 i++; 4554 } 4555 } 4556 } 4557 4558 /* 4559 * flatten_join_using_qual: extract Vars being joined from a JOIN/USING qual 4560 * 4561 * We assume that transformJoinUsingClause won't have produced anything except 4562 * AND nodes, equality operator nodes, and possibly implicit coercions, and 4563 * that the AND node inputs match left-to-right with the original USING list. 4564 * 4565 * Caller must initialize the result lists to NIL. 4566 */ 4567 static void 4568 flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars) 4569 { 4570 if (IsA(qual, BoolExpr)) 4571 { 4572 /* Handle AND nodes by recursion */ 4573 BoolExpr *b = (BoolExpr *) qual; 4574 ListCell *lc; 4575 4576 Assert(b->boolop == AND_EXPR); 4577 foreach(lc, b->args) 4578 { 4579 flatten_join_using_qual((Node *) lfirst(lc), 4580 leftvars, rightvars); 4581 } 4582 } 4583 else if (IsA(qual, OpExpr)) 4584 { 4585 /* Otherwise we should have an equality operator */ 4586 OpExpr *op = (OpExpr *) qual; 4587 Var *var; 4588 4589 if (list_length(op->args) != 2) 4590 elog(ERROR, "unexpected unary operator in JOIN/USING qual"); 4591 /* Arguments should be Vars with perhaps implicit coercions */ 4592 var = (Var *) strip_implicit_coercions((Node *) linitial(op->args)); 4593 if (!IsA(var, Var)) 4594 elog(ERROR, "unexpected node type in JOIN/USING qual: %d", 4595 (int) nodeTag(var)); 4596 *leftvars = lappend(*leftvars, var); 4597 var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args)); 4598 if (!IsA(var, Var)) 4599 elog(ERROR, "unexpected node type in JOIN/USING qual: %d", 4600 (int) nodeTag(var)); 4601 *rightvars = lappend(*rightvars, var); 4602 } 4603 else 4604 { 4605 /* Perhaps we have an implicit coercion to boolean? */ 4606 Node *q = strip_implicit_coercions(qual); 4607 4608 if (q != qual) 4609 flatten_join_using_qual(q, leftvars, rightvars); 4610 else 4611 elog(ERROR, "unexpected node type in JOIN/USING qual: %d", 4612 (int) nodeTag(qual)); 4613 } 4614 } 4615 4616 /* 4617 * get_rtable_name: convenience function to get a previously assigned RTE alias 4618 * 4619 * The RTE must belong to the topmost namespace level in "context". 4620 */ 4621 static char * 4622 get_rtable_name(int rtindex, deparse_context *context) 4623 { 4624 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); 4625 4626 Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names)); 4627 return (char *) list_nth(dpns->rtable_names, rtindex - 1); 4628 } 4629 4630 /* 4631 * set_deparse_planstate: set up deparse_namespace to parse subexpressions 4632 * of a given PlanState node 4633 * 4634 * This sets the planstate, outer_planstate, inner_planstate, outer_tlist, 4635 * inner_tlist, and index_tlist fields. Caller is responsible for adjusting 4636 * the ancestors list if necessary. Note that the rtable and ctes fields do 4637 * not need to change when shifting attention to different plan nodes in a 4638 * single plan tree. 4639 */ 4640 static void 4641 set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) 4642 { 4643 dpns->planstate = ps; 4644 4645 /* 4646 * We special-case Append and MergeAppend to pretend that the first child 4647 * plan is the OUTER referent; we have to interpret OUTER Vars in their 4648 * tlists according to one of the children, and the first one is the most 4649 * natural choice. Likewise special-case ModifyTable to pretend that the 4650 * first child plan is the OUTER referent; this is to support RETURNING 4651 * lists containing references to non-target relations. 4652 */ 4653 if (IsA(ps, AppendState)) 4654 dpns->outer_planstate = ((AppendState *) ps)->appendplans[0]; 4655 else if (IsA(ps, MergeAppendState)) 4656 dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0]; 4657 else if (IsA(ps, ModifyTableState)) 4658 dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0]; 4659 else 4660 dpns->outer_planstate = outerPlanState(ps); 4661 4662 if (dpns->outer_planstate) 4663 dpns->outer_tlist = dpns->outer_planstate->plan->targetlist; 4664 else 4665 dpns->outer_tlist = NIL; 4666 4667 /* 4668 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't 4669 * use OUTER because that could someday conflict with the normal meaning.) 4670 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent. 4671 * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the 4672 * excluded expression's tlist. (Similar to the SubqueryScan we don't want 4673 * to reuse OUTER, it's used for RETURNING in some modify table cases, 4674 * although not INSERT .. CONFLICT). 4675 */ 4676 if (IsA(ps, SubqueryScanState)) 4677 dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan; 4678 else if (IsA(ps, CteScanState)) 4679 dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate; 4680 else if (IsA(ps, ModifyTableState)) 4681 dpns->inner_planstate = ps; 4682 else 4683 dpns->inner_planstate = innerPlanState(ps); 4684 4685 if (IsA(ps, ModifyTableState)) 4686 dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist; 4687 else if (dpns->inner_planstate) 4688 dpns->inner_tlist = dpns->inner_planstate->plan->targetlist; 4689 else 4690 dpns->inner_tlist = NIL; 4691 4692 /* Set up referent for INDEX_VAR Vars, if needed */ 4693 if (IsA(ps->plan, IndexOnlyScan)) 4694 dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist; 4695 else if (IsA(ps->plan, ForeignScan)) 4696 dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist; 4697 else if (IsA(ps->plan, CustomScan)) 4698 dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist; 4699 else 4700 dpns->index_tlist = NIL; 4701 } 4702 4703 /* 4704 * push_child_plan: temporarily transfer deparsing attention to a child plan 4705 * 4706 * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the 4707 * deparse context in case the referenced expression itself uses 4708 * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid 4709 * affecting levelsup issues (although in a Plan tree there really shouldn't 4710 * be any). 4711 * 4712 * Caller must provide a local deparse_namespace variable to save the 4713 * previous state for pop_child_plan. 4714 */ 4715 static void 4716 push_child_plan(deparse_namespace *dpns, PlanState *ps, 4717 deparse_namespace *save_dpns) 4718 { 4719 /* Save state for restoration later */ 4720 *save_dpns = *dpns; 4721 4722 /* Link current plan node into ancestors list */ 4723 dpns->ancestors = lcons(dpns->planstate, dpns->ancestors); 4724 4725 /* Set attention on selected child */ 4726 set_deparse_planstate(dpns, ps); 4727 } 4728 4729 /* 4730 * pop_child_plan: undo the effects of push_child_plan 4731 */ 4732 static void 4733 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) 4734 { 4735 List *ancestors; 4736 4737 /* Get rid of ancestors list cell added by push_child_plan */ 4738 ancestors = list_delete_first(dpns->ancestors); 4739 4740 /* Restore fields changed by push_child_plan */ 4741 *dpns = *save_dpns; 4742 4743 /* Make sure dpns->ancestors is right (may be unnecessary) */ 4744 dpns->ancestors = ancestors; 4745 } 4746 4747 /* 4748 * push_ancestor_plan: temporarily transfer deparsing attention to an 4749 * ancestor plan 4750 * 4751 * When expanding a Param reference, we must adjust the deparse context 4752 * to match the plan node that contains the expression being printed; 4753 * otherwise we'd fail if that expression itself contains a Param or 4754 * OUTER_VAR/INNER_VAR/INDEX_VAR variable. 4755 * 4756 * The target ancestor is conveniently identified by the ListCell holding it 4757 * in dpns->ancestors. 4758 * 4759 * Caller must provide a local deparse_namespace variable to save the 4760 * previous state for pop_ancestor_plan. 4761 */ 4762 static void 4763 push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, 4764 deparse_namespace *save_dpns) 4765 { 4766 PlanState *ps = (PlanState *) lfirst(ancestor_cell); 4767 List *ancestors; 4768 4769 /* Save state for restoration later */ 4770 *save_dpns = *dpns; 4771 4772 /* Build a new ancestor list with just this node's ancestors */ 4773 ancestors = NIL; 4774 while ((ancestor_cell = lnext(ancestor_cell)) != NULL) 4775 ancestors = lappend(ancestors, lfirst(ancestor_cell)); 4776 dpns->ancestors = ancestors; 4777 4778 /* Set attention on selected ancestor */ 4779 set_deparse_planstate(dpns, ps); 4780 } 4781 4782 /* 4783 * pop_ancestor_plan: undo the effects of push_ancestor_plan 4784 */ 4785 static void 4786 pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) 4787 { 4788 /* Free the ancestor list made in push_ancestor_plan */ 4789 list_free(dpns->ancestors); 4790 4791 /* Restore fields changed by push_ancestor_plan */ 4792 *dpns = *save_dpns; 4793 } 4794 4795 4796 /* ---------- 4797 * make_ruledef - reconstruct the CREATE RULE command 4798 * for a given pg_rewrite tuple 4799 * ---------- 4800 */ 4801 static void 4802 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, 4803 int prettyFlags) 4804 { 4805 char *rulename; 4806 char ev_type; 4807 Oid ev_class; 4808 bool is_instead; 4809 char *ev_qual; 4810 char *ev_action; 4811 List *actions = NIL; 4812 Relation ev_relation; 4813 TupleDesc viewResultDesc = NULL; 4814 int fno; 4815 Datum dat; 4816 bool isnull; 4817 4818 /* 4819 * Get the attribute values from the rules tuple 4820 */ 4821 fno = SPI_fnumber(rulettc, "rulename"); 4822 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 4823 Assert(!isnull); 4824 rulename = NameStr(*(DatumGetName(dat))); 4825 4826 fno = SPI_fnumber(rulettc, "ev_type"); 4827 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 4828 Assert(!isnull); 4829 ev_type = DatumGetChar(dat); 4830 4831 fno = SPI_fnumber(rulettc, "ev_class"); 4832 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 4833 Assert(!isnull); 4834 ev_class = DatumGetObjectId(dat); 4835 4836 fno = SPI_fnumber(rulettc, "is_instead"); 4837 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 4838 Assert(!isnull); 4839 is_instead = DatumGetBool(dat); 4840 4841 /* these could be nulls */ 4842 fno = SPI_fnumber(rulettc, "ev_qual"); 4843 ev_qual = SPI_getvalue(ruletup, rulettc, fno); 4844 4845 fno = SPI_fnumber(rulettc, "ev_action"); 4846 ev_action = SPI_getvalue(ruletup, rulettc, fno); 4847 if (ev_action != NULL) 4848 actions = (List *) stringToNode(ev_action); 4849 4850 ev_relation = table_open(ev_class, AccessShareLock); 4851 4852 /* 4853 * Build the rules definition text 4854 */ 4855 appendStringInfo(buf, "CREATE RULE %s AS", 4856 quote_identifier(rulename)); 4857 4858 if (prettyFlags & PRETTYFLAG_INDENT) 4859 appendStringInfoString(buf, "\n ON "); 4860 else 4861 appendStringInfoString(buf, " ON "); 4862 4863 /* The event the rule is fired for */ 4864 switch (ev_type) 4865 { 4866 case '1': 4867 appendStringInfoString(buf, "SELECT"); 4868 viewResultDesc = RelationGetDescr(ev_relation); 4869 break; 4870 4871 case '2': 4872 appendStringInfoString(buf, "UPDATE"); 4873 break; 4874 4875 case '3': 4876 appendStringInfoString(buf, "INSERT"); 4877 break; 4878 4879 case '4': 4880 appendStringInfoString(buf, "DELETE"); 4881 break; 4882 4883 default: 4884 ereport(ERROR, 4885 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 4886 errmsg("rule \"%s\" has unsupported event type %d", 4887 rulename, ev_type))); 4888 break; 4889 } 4890 4891 /* The relation the rule is fired on */ 4892 appendStringInfo(buf, " TO %s", 4893 (prettyFlags & PRETTYFLAG_SCHEMA) ? 4894 generate_relation_name(ev_class, NIL) : 4895 generate_qualified_relation_name(ev_class)); 4896 4897 /* If the rule has an event qualification, add it */ 4898 if (ev_qual == NULL) 4899 ev_qual = ""; 4900 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0) 4901 { 4902 Node *qual; 4903 Query *query; 4904 deparse_context context; 4905 deparse_namespace dpns; 4906 4907 if (prettyFlags & PRETTYFLAG_INDENT) 4908 appendStringInfoString(buf, "\n "); 4909 appendStringInfoString(buf, " WHERE "); 4910 4911 qual = stringToNode(ev_qual); 4912 4913 /* 4914 * We need to make a context for recognizing any Vars in the qual 4915 * (which can only be references to OLD and NEW). Use the rtable of 4916 * the first query in the action list for this purpose. 4917 */ 4918 query = (Query *) linitial(actions); 4919 4920 /* 4921 * If the action is INSERT...SELECT, OLD/NEW have been pushed down 4922 * into the SELECT, and that's what we need to look at. (Ugly kluge 4923 * ... try to fix this when we redesign querytrees.) 4924 */ 4925 query = getInsertSelectQuery(query, NULL); 4926 4927 /* Must acquire locks right away; see notes in get_query_def() */ 4928 AcquireRewriteLocks(query, false, false); 4929 4930 context.buf = buf; 4931 context.namespaces = list_make1(&dpns); 4932 context.windowClause = NIL; 4933 context.windowTList = NIL; 4934 context.varprefix = (list_length(query->rtable) != 1); 4935 context.prettyFlags = prettyFlags; 4936 context.wrapColumn = WRAP_COLUMN_DEFAULT; 4937 context.indentLevel = PRETTYINDENT_STD; 4938 context.special_exprkind = EXPR_KIND_NONE; 4939 4940 set_deparse_for_query(&dpns, query, NIL); 4941 4942 get_rule_expr(qual, &context, false); 4943 } 4944 4945 appendStringInfoString(buf, " DO "); 4946 4947 /* The INSTEAD keyword (if so) */ 4948 if (is_instead) 4949 appendStringInfoString(buf, "INSTEAD "); 4950 4951 /* Finally the rules actions */ 4952 if (list_length(actions) > 1) 4953 { 4954 ListCell *action; 4955 Query *query; 4956 4957 appendStringInfoChar(buf, '('); 4958 foreach(action, actions) 4959 { 4960 query = (Query *) lfirst(action); 4961 get_query_def(query, buf, NIL, viewResultDesc, 4962 prettyFlags, WRAP_COLUMN_DEFAULT, 0); 4963 if (prettyFlags) 4964 appendStringInfoString(buf, ";\n"); 4965 else 4966 appendStringInfoString(buf, "; "); 4967 } 4968 appendStringInfoString(buf, ");"); 4969 } 4970 else if (list_length(actions) == 0) 4971 { 4972 appendStringInfoString(buf, "NOTHING;"); 4973 } 4974 else 4975 { 4976 Query *query; 4977 4978 query = (Query *) linitial(actions); 4979 get_query_def(query, buf, NIL, viewResultDesc, 4980 prettyFlags, WRAP_COLUMN_DEFAULT, 0); 4981 appendStringInfoChar(buf, ';'); 4982 } 4983 4984 table_close(ev_relation, AccessShareLock); 4985 } 4986 4987 4988 /* ---------- 4989 * make_viewdef - reconstruct the SELECT part of a 4990 * view rewrite rule 4991 * ---------- 4992 */ 4993 static void 4994 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, 4995 int prettyFlags, int wrapColumn) 4996 { 4997 Query *query; 4998 char ev_type; 4999 Oid ev_class; 5000 bool is_instead; 5001 char *ev_qual; 5002 char *ev_action; 5003 List *actions = NIL; 5004 Relation ev_relation; 5005 int fno; 5006 Datum dat; 5007 bool isnull; 5008 5009 /* 5010 * Get the attribute values from the rules tuple 5011 */ 5012 fno = SPI_fnumber(rulettc, "ev_type"); 5013 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 5014 Assert(!isnull); 5015 ev_type = DatumGetChar(dat); 5016 5017 fno = SPI_fnumber(rulettc, "ev_class"); 5018 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 5019 Assert(!isnull); 5020 ev_class = DatumGetObjectId(dat); 5021 5022 fno = SPI_fnumber(rulettc, "is_instead"); 5023 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull); 5024 Assert(!isnull); 5025 is_instead = DatumGetBool(dat); 5026 5027 /* these could be nulls */ 5028 fno = SPI_fnumber(rulettc, "ev_qual"); 5029 ev_qual = SPI_getvalue(ruletup, rulettc, fno); 5030 5031 fno = SPI_fnumber(rulettc, "ev_action"); 5032 ev_action = SPI_getvalue(ruletup, rulettc, fno); 5033 if (ev_action != NULL) 5034 actions = (List *) stringToNode(ev_action); 5035 5036 if (list_length(actions) != 1) 5037 { 5038 /* keep output buffer empty and leave */ 5039 return; 5040 } 5041 5042 query = (Query *) linitial(actions); 5043 5044 if (ev_type != '1' || !is_instead || 5045 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT) 5046 { 5047 /* keep output buffer empty and leave */ 5048 return; 5049 } 5050 5051 ev_relation = table_open(ev_class, AccessShareLock); 5052 5053 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation), 5054 prettyFlags, wrapColumn, 0); 5055 appendStringInfoChar(buf, ';'); 5056 5057 table_close(ev_relation, AccessShareLock); 5058 } 5059 5060 5061 /* ---------- 5062 * get_query_def - Parse back one query parsetree 5063 * 5064 * If resultDesc is not NULL, then it is the output tuple descriptor for 5065 * the view represented by a SELECT query. 5066 * ---------- 5067 */ 5068 static void 5069 get_query_def(Query *query, StringInfo buf, List *parentnamespace, 5070 TupleDesc resultDesc, 5071 int prettyFlags, int wrapColumn, int startIndent) 5072 { 5073 deparse_context context; 5074 deparse_namespace dpns; 5075 5076 /* Guard against excessively long or deeply-nested queries */ 5077 CHECK_FOR_INTERRUPTS(); 5078 check_stack_depth(); 5079 5080 /* 5081 * Before we begin to examine the query, acquire locks on referenced 5082 * relations, and fix up deleted columns in JOIN RTEs. This ensures 5083 * consistent results. Note we assume it's OK to scribble on the passed 5084 * querytree! 5085 * 5086 * We are only deparsing the query (we are not about to execute it), so we 5087 * only need AccessShareLock on the relations it mentions. 5088 */ 5089 AcquireRewriteLocks(query, false, false); 5090 5091 context.buf = buf; 5092 context.namespaces = lcons(&dpns, list_copy(parentnamespace)); 5093 context.windowClause = NIL; 5094 context.windowTList = NIL; 5095 context.varprefix = (parentnamespace != NIL || 5096 list_length(query->rtable) != 1); 5097 context.prettyFlags = prettyFlags; 5098 context.wrapColumn = wrapColumn; 5099 context.indentLevel = startIndent; 5100 context.special_exprkind = EXPR_KIND_NONE; 5101 5102 set_deparse_for_query(&dpns, query, parentnamespace); 5103 5104 switch (query->commandType) 5105 { 5106 case CMD_SELECT: 5107 get_select_query_def(query, &context, resultDesc); 5108 break; 5109 5110 case CMD_UPDATE: 5111 get_update_query_def(query, &context); 5112 break; 5113 5114 case CMD_INSERT: 5115 get_insert_query_def(query, &context); 5116 break; 5117 5118 case CMD_DELETE: 5119 get_delete_query_def(query, &context); 5120 break; 5121 5122 case CMD_NOTHING: 5123 appendStringInfoString(buf, "NOTHING"); 5124 break; 5125 5126 case CMD_UTILITY: 5127 get_utility_query_def(query, &context); 5128 break; 5129 5130 default: 5131 elog(ERROR, "unrecognized query command type: %d", 5132 query->commandType); 5133 break; 5134 } 5135 } 5136 5137 /* ---------- 5138 * get_values_def - Parse back a VALUES list 5139 * ---------- 5140 */ 5141 static void 5142 get_values_def(List *values_lists, deparse_context *context) 5143 { 5144 StringInfo buf = context->buf; 5145 bool first_list = true; 5146 ListCell *vtl; 5147 5148 appendStringInfoString(buf, "VALUES "); 5149 5150 foreach(vtl, values_lists) 5151 { 5152 List *sublist = (List *) lfirst(vtl); 5153 bool first_col = true; 5154 ListCell *lc; 5155 5156 if (first_list) 5157 first_list = false; 5158 else 5159 appendStringInfoString(buf, ", "); 5160 5161 appendStringInfoChar(buf, '('); 5162 foreach(lc, sublist) 5163 { 5164 Node *col = (Node *) lfirst(lc); 5165 5166 if (first_col) 5167 first_col = false; 5168 else 5169 appendStringInfoChar(buf, ','); 5170 5171 /* 5172 * Print the value. Whole-row Vars need special treatment. 5173 */ 5174 get_rule_expr_toplevel(col, context, false); 5175 } 5176 appendStringInfoChar(buf, ')'); 5177 } 5178 } 5179 5180 /* ---------- 5181 * get_with_clause - Parse back a WITH clause 5182 * ---------- 5183 */ 5184 static void 5185 get_with_clause(Query *query, deparse_context *context) 5186 { 5187 StringInfo buf = context->buf; 5188 const char *sep; 5189 ListCell *l; 5190 5191 if (query->cteList == NIL) 5192 return; 5193 5194 if (PRETTY_INDENT(context)) 5195 { 5196 context->indentLevel += PRETTYINDENT_STD; 5197 appendStringInfoChar(buf, ' '); 5198 } 5199 5200 if (query->hasRecursive) 5201 sep = "WITH RECURSIVE "; 5202 else 5203 sep = "WITH "; 5204 foreach(l, query->cteList) 5205 { 5206 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l); 5207 5208 appendStringInfoString(buf, sep); 5209 appendStringInfoString(buf, quote_identifier(cte->ctename)); 5210 if (cte->aliascolnames) 5211 { 5212 bool first = true; 5213 ListCell *col; 5214 5215 appendStringInfoChar(buf, '('); 5216 foreach(col, cte->aliascolnames) 5217 { 5218 if (first) 5219 first = false; 5220 else 5221 appendStringInfoString(buf, ", "); 5222 appendStringInfoString(buf, 5223 quote_identifier(strVal(lfirst(col)))); 5224 } 5225 appendStringInfoChar(buf, ')'); 5226 } 5227 appendStringInfoString(buf, " AS "); 5228 switch (cte->ctematerialized) 5229 { 5230 case CTEMaterializeDefault: 5231 break; 5232 case CTEMaterializeAlways: 5233 appendStringInfoString(buf, "MATERIALIZED "); 5234 break; 5235 case CTEMaterializeNever: 5236 appendStringInfoString(buf, "NOT MATERIALIZED "); 5237 break; 5238 } 5239 appendStringInfoChar(buf, '('); 5240 if (PRETTY_INDENT(context)) 5241 appendContextKeyword(context, "", 0, 0, 0); 5242 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL, 5243 context->prettyFlags, context->wrapColumn, 5244 context->indentLevel); 5245 if (PRETTY_INDENT(context)) 5246 appendContextKeyword(context, "", 0, 0, 0); 5247 appendStringInfoChar(buf, ')'); 5248 sep = ", "; 5249 } 5250 5251 if (PRETTY_INDENT(context)) 5252 { 5253 context->indentLevel -= PRETTYINDENT_STD; 5254 appendContextKeyword(context, "", 0, 0, 0); 5255 } 5256 else 5257 appendStringInfoChar(buf, ' '); 5258 } 5259 5260 /* ---------- 5261 * get_select_query_def - Parse back a SELECT parsetree 5262 * ---------- 5263 */ 5264 static void 5265 get_select_query_def(Query *query, deparse_context *context, 5266 TupleDesc resultDesc) 5267 { 5268 StringInfo buf = context->buf; 5269 List *save_windowclause; 5270 List *save_windowtlist; 5271 bool force_colno; 5272 ListCell *l; 5273 5274 /* Insert the WITH clause if given */ 5275 get_with_clause(query, context); 5276 5277 /* Set up context for possible window functions */ 5278 save_windowclause = context->windowClause; 5279 context->windowClause = query->windowClause; 5280 save_windowtlist = context->windowTList; 5281 context->windowTList = query->targetList; 5282 5283 /* 5284 * If the Query node has a setOperations tree, then it's the top level of 5285 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT 5286 * fields are interesting in the top query itself. 5287 */ 5288 if (query->setOperations) 5289 { 5290 get_setop_query(query->setOperations, query, context, resultDesc); 5291 /* ORDER BY clauses must be simple in this case */ 5292 force_colno = true; 5293 } 5294 else 5295 { 5296 get_basic_select_query(query, context, resultDesc); 5297 force_colno = false; 5298 } 5299 5300 /* Add the ORDER BY clause if given */ 5301 if (query->sortClause != NIL) 5302 { 5303 appendContextKeyword(context, " ORDER BY ", 5304 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 5305 get_rule_orderby(query->sortClause, query->targetList, 5306 force_colno, context); 5307 } 5308 5309 /* Add the LIMIT clause if given */ 5310 if (query->limitOffset != NULL) 5311 { 5312 appendContextKeyword(context, " OFFSET ", 5313 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5314 get_rule_expr(query->limitOffset, context, false); 5315 } 5316 if (query->limitCount != NULL) 5317 { 5318 appendContextKeyword(context, " LIMIT ", 5319 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5320 if (IsA(query->limitCount, Const) && 5321 ((Const *) query->limitCount)->constisnull) 5322 appendStringInfoString(buf, "ALL"); 5323 else 5324 get_rule_expr(query->limitCount, context, false); 5325 } 5326 5327 /* Add FOR [KEY] UPDATE/SHARE clauses if present */ 5328 if (query->hasForUpdate) 5329 { 5330 foreach(l, query->rowMarks) 5331 { 5332 RowMarkClause *rc = (RowMarkClause *) lfirst(l); 5333 5334 /* don't print implicit clauses */ 5335 if (rc->pushedDown) 5336 continue; 5337 5338 switch (rc->strength) 5339 { 5340 case LCS_NONE: 5341 /* we intentionally throw an error for LCS_NONE */ 5342 elog(ERROR, "unrecognized LockClauseStrength %d", 5343 (int) rc->strength); 5344 break; 5345 case LCS_FORKEYSHARE: 5346 appendContextKeyword(context, " FOR KEY SHARE", 5347 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5348 break; 5349 case LCS_FORSHARE: 5350 appendContextKeyword(context, " FOR SHARE", 5351 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5352 break; 5353 case LCS_FORNOKEYUPDATE: 5354 appendContextKeyword(context, " FOR NO KEY UPDATE", 5355 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5356 break; 5357 case LCS_FORUPDATE: 5358 appendContextKeyword(context, " FOR UPDATE", 5359 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5360 break; 5361 } 5362 5363 appendStringInfo(buf, " OF %s", 5364 quote_identifier(get_rtable_name(rc->rti, 5365 context))); 5366 if (rc->waitPolicy == LockWaitError) 5367 appendStringInfoString(buf, " NOWAIT"); 5368 else if (rc->waitPolicy == LockWaitSkip) 5369 appendStringInfoString(buf, " SKIP LOCKED"); 5370 } 5371 } 5372 5373 context->windowClause = save_windowclause; 5374 context->windowTList = save_windowtlist; 5375 } 5376 5377 /* 5378 * Detect whether query looks like SELECT ... FROM VALUES(), 5379 * with no need to rename the output columns of the VALUES RTE. 5380 * If so, return the VALUES RTE. Otherwise return NULL. 5381 */ 5382 static RangeTblEntry * 5383 get_simple_values_rte(Query *query, TupleDesc resultDesc) 5384 { 5385 RangeTblEntry *result = NULL; 5386 ListCell *lc; 5387 5388 /* 5389 * We want to detect a match even if the Query also contains OLD or NEW 5390 * rule RTEs. So the idea is to scan the rtable and see if there is only 5391 * one inFromCl RTE that is a VALUES RTE. 5392 */ 5393 foreach(lc, query->rtable) 5394 { 5395 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); 5396 5397 if (rte->rtekind == RTE_VALUES && rte->inFromCl) 5398 { 5399 if (result) 5400 return NULL; /* multiple VALUES (probably not possible) */ 5401 result = rte; 5402 } 5403 else if (rte->rtekind == RTE_RELATION && !rte->inFromCl) 5404 continue; /* ignore rule entries */ 5405 else 5406 return NULL; /* something else -> not simple VALUES */ 5407 } 5408 5409 /* 5410 * We don't need to check the targetlist in any great detail, because 5411 * parser/analyze.c will never generate a "bare" VALUES RTE --- they only 5412 * appear inside auto-generated sub-queries with very restricted 5413 * structure. However, DefineView might have modified the tlist by 5414 * injecting new column aliases, or we might have some other column 5415 * aliases forced by a resultDesc. We can only simplify if the RTE's 5416 * column names match the names that get_target_list() would select. 5417 */ 5418 if (result) 5419 { 5420 ListCell *lcn; 5421 int colno; 5422 5423 if (list_length(query->targetList) != list_length(result->eref->colnames)) 5424 return NULL; /* this probably cannot happen */ 5425 colno = 0; 5426 forboth(lc, query->targetList, lcn, result->eref->colnames) 5427 { 5428 TargetEntry *tle = (TargetEntry *) lfirst(lc); 5429 char *cname = strVal(lfirst(lcn)); 5430 char *colname; 5431 5432 if (tle->resjunk) 5433 return NULL; /* this probably cannot happen */ 5434 5435 /* compute name that get_target_list would use for column */ 5436 colno++; 5437 if (resultDesc && colno <= resultDesc->natts) 5438 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); 5439 else 5440 colname = tle->resname; 5441 5442 /* does it match the VALUES RTE? */ 5443 if (colname == NULL || strcmp(colname, cname) != 0) 5444 return NULL; /* column name has been changed */ 5445 } 5446 } 5447 5448 return result; 5449 } 5450 5451 static void 5452 get_basic_select_query(Query *query, deparse_context *context, 5453 TupleDesc resultDesc) 5454 { 5455 StringInfo buf = context->buf; 5456 RangeTblEntry *values_rte; 5457 char *sep; 5458 ListCell *l; 5459 5460 if (PRETTY_INDENT(context)) 5461 { 5462 context->indentLevel += PRETTYINDENT_STD; 5463 appendStringInfoChar(buf, ' '); 5464 } 5465 5466 /* 5467 * If the query looks like SELECT * FROM (VALUES ...), then print just the 5468 * VALUES part. This reverses what transformValuesClause() did at parse 5469 * time. 5470 */ 5471 values_rte = get_simple_values_rte(query, resultDesc); 5472 if (values_rte) 5473 { 5474 get_values_def(values_rte->values_lists, context); 5475 return; 5476 } 5477 5478 /* 5479 * Build up the query string - first we say SELECT 5480 */ 5481 appendStringInfoString(buf, "SELECT"); 5482 5483 /* Add the DISTINCT clause if given */ 5484 if (query->distinctClause != NIL) 5485 { 5486 if (query->hasDistinctOn) 5487 { 5488 appendStringInfoString(buf, " DISTINCT ON ("); 5489 sep = ""; 5490 foreach(l, query->distinctClause) 5491 { 5492 SortGroupClause *srt = (SortGroupClause *) lfirst(l); 5493 5494 appendStringInfoString(buf, sep); 5495 get_rule_sortgroupclause(srt->tleSortGroupRef, query->targetList, 5496 false, context); 5497 sep = ", "; 5498 } 5499 appendStringInfoChar(buf, ')'); 5500 } 5501 else 5502 appendStringInfoString(buf, " DISTINCT"); 5503 } 5504 5505 /* Then we tell what to select (the targetlist) */ 5506 get_target_list(query->targetList, context, resultDesc); 5507 5508 /* Add the FROM clause if needed */ 5509 get_from_clause(query, " FROM ", context); 5510 5511 /* Add the WHERE clause if given */ 5512 if (query->jointree->quals != NULL) 5513 { 5514 appendContextKeyword(context, " WHERE ", 5515 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 5516 get_rule_expr(query->jointree->quals, context, false); 5517 } 5518 5519 /* Add the GROUP BY clause if given */ 5520 if (query->groupClause != NULL || query->groupingSets != NULL) 5521 { 5522 ParseExprKind save_exprkind; 5523 5524 appendContextKeyword(context, " GROUP BY ", 5525 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 5526 5527 save_exprkind = context->special_exprkind; 5528 context->special_exprkind = EXPR_KIND_GROUP_BY; 5529 5530 if (query->groupingSets == NIL) 5531 { 5532 sep = ""; 5533 foreach(l, query->groupClause) 5534 { 5535 SortGroupClause *grp = (SortGroupClause *) lfirst(l); 5536 5537 appendStringInfoString(buf, sep); 5538 get_rule_sortgroupclause(grp->tleSortGroupRef, query->targetList, 5539 false, context); 5540 sep = ", "; 5541 } 5542 } 5543 else 5544 { 5545 sep = ""; 5546 foreach(l, query->groupingSets) 5547 { 5548 GroupingSet *grp = lfirst(l); 5549 5550 appendStringInfoString(buf, sep); 5551 get_rule_groupingset(grp, query->targetList, true, context); 5552 sep = ", "; 5553 } 5554 } 5555 5556 context->special_exprkind = save_exprkind; 5557 } 5558 5559 /* Add the HAVING clause if given */ 5560 if (query->havingQual != NULL) 5561 { 5562 appendContextKeyword(context, " HAVING ", 5563 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); 5564 get_rule_expr(query->havingQual, context, false); 5565 } 5566 5567 /* Add the WINDOW clause if needed */ 5568 if (query->windowClause != NIL) 5569 get_rule_windowclause(query, context); 5570 } 5571 5572 /* ---------- 5573 * get_target_list - Parse back a SELECT target list 5574 * 5575 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE. 5576 * ---------- 5577 */ 5578 static void 5579 get_target_list(List *targetList, deparse_context *context, 5580 TupleDesc resultDesc) 5581 { 5582 StringInfo buf = context->buf; 5583 StringInfoData targetbuf; 5584 bool last_was_multiline = false; 5585 char *sep; 5586 int colno; 5587 ListCell *l; 5588 5589 /* we use targetbuf to hold each TLE's text temporarily */ 5590 initStringInfo(&targetbuf); 5591 5592 sep = " "; 5593 colno = 0; 5594 foreach(l, targetList) 5595 { 5596 TargetEntry *tle = (TargetEntry *) lfirst(l); 5597 char *colname; 5598 char *attname; 5599 5600 if (tle->resjunk) 5601 continue; /* ignore junk entries */ 5602 5603 appendStringInfoString(buf, sep); 5604 sep = ", "; 5605 colno++; 5606 5607 /* 5608 * Put the new field text into targetbuf so we can decide after we've 5609 * got it whether or not it needs to go on a new line. 5610 */ 5611 resetStringInfo(&targetbuf); 5612 context->buf = &targetbuf; 5613 5614 /* 5615 * We special-case Var nodes rather than using get_rule_expr. This is 5616 * needed because get_rule_expr will display a whole-row Var as 5617 * "foo.*", which is the preferred notation in most contexts, but at 5618 * the top level of a SELECT list it's not right (the parser will 5619 * expand that notation into multiple columns, yielding behavior 5620 * different from a whole-row Var). We need to call get_variable 5621 * directly so that we can tell it to do the right thing, and so that 5622 * we can get the attribute name which is the default AS label. 5623 */ 5624 if (tle->expr && (IsA(tle->expr, Var))) 5625 { 5626 attname = get_variable((Var *) tle->expr, 0, true, context); 5627 } 5628 else 5629 { 5630 get_rule_expr((Node *) tle->expr, context, true); 5631 /* We'll show the AS name unless it's this: */ 5632 attname = "?column?"; 5633 } 5634 5635 /* 5636 * Figure out what the result column should be called. In the context 5637 * of a view, use the view's tuple descriptor (so as to pick up the 5638 * effects of any column RENAME that's been done on the view). 5639 * Otherwise, just use what we can find in the TLE. 5640 */ 5641 if (resultDesc && colno <= resultDesc->natts) 5642 colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); 5643 else 5644 colname = tle->resname; 5645 5646 /* Show AS unless the column's name is correct as-is */ 5647 if (colname) /* resname could be NULL */ 5648 { 5649 if (attname == NULL || strcmp(attname, colname) != 0) 5650 appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname)); 5651 } 5652 5653 /* Restore context's output buffer */ 5654 context->buf = buf; 5655 5656 /* Consider line-wrapping if enabled */ 5657 if (PRETTY_INDENT(context) && context->wrapColumn >= 0) 5658 { 5659 int leading_nl_pos; 5660 5661 /* Does the new field start with a new line? */ 5662 if (targetbuf.len > 0 && targetbuf.data[0] == '\n') 5663 leading_nl_pos = 0; 5664 else 5665 leading_nl_pos = -1; 5666 5667 /* If so, we shouldn't add anything */ 5668 if (leading_nl_pos >= 0) 5669 { 5670 /* instead, remove any trailing spaces currently in buf */ 5671 removeStringInfoSpaces(buf); 5672 } 5673 else 5674 { 5675 char *trailing_nl; 5676 5677 /* Locate the start of the current line in the output buffer */ 5678 trailing_nl = strrchr(buf->data, '\n'); 5679 if (trailing_nl == NULL) 5680 trailing_nl = buf->data; 5681 else 5682 trailing_nl++; 5683 5684 /* 5685 * Add a newline, plus some indentation, if the new field is 5686 * not the first and either the new field would cause an 5687 * overflow or the last field used more than one line. 5688 */ 5689 if (colno > 1 && 5690 ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) || 5691 last_was_multiline)) 5692 appendContextKeyword(context, "", -PRETTYINDENT_STD, 5693 PRETTYINDENT_STD, PRETTYINDENT_VAR); 5694 } 5695 5696 /* Remember this field's multiline status for next iteration */ 5697 last_was_multiline = 5698 (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL); 5699 } 5700 5701 /* Add the new field */ 5702 appendStringInfoString(buf, targetbuf.data); 5703 } 5704 5705 /* clean up */ 5706 pfree(targetbuf.data); 5707 } 5708 5709 static void 5710 get_setop_query(Node *setOp, Query *query, deparse_context *context, 5711 TupleDesc resultDesc) 5712 { 5713 StringInfo buf = context->buf; 5714 bool need_paren; 5715 5716 /* Guard against excessively long or deeply-nested queries */ 5717 CHECK_FOR_INTERRUPTS(); 5718 check_stack_depth(); 5719 5720 if (IsA(setOp, RangeTblRef)) 5721 { 5722 RangeTblRef *rtr = (RangeTblRef *) setOp; 5723 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable); 5724 Query *subquery = rte->subquery; 5725 5726 Assert(subquery != NULL); 5727 Assert(subquery->setOperations == NULL); 5728 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */ 5729 need_paren = (subquery->cteList || 5730 subquery->sortClause || 5731 subquery->rowMarks || 5732 subquery->limitOffset || 5733 subquery->limitCount); 5734 if (need_paren) 5735 appendStringInfoChar(buf, '('); 5736 get_query_def(subquery, buf, context->namespaces, resultDesc, 5737 context->prettyFlags, context->wrapColumn, 5738 context->indentLevel); 5739 if (need_paren) 5740 appendStringInfoChar(buf, ')'); 5741 } 5742 else if (IsA(setOp, SetOperationStmt)) 5743 { 5744 SetOperationStmt *op = (SetOperationStmt *) setOp; 5745 int subindent; 5746 5747 /* 5748 * We force parens when nesting two SetOperationStmts, except when the 5749 * lefthand input is another setop of the same kind. Syntactically, 5750 * we could omit parens in rather more cases, but it seems best to use 5751 * parens to flag cases where the setop operator changes. If we use 5752 * parens, we also increase the indentation level for the child query. 5753 * 5754 * There are some cases in which parens are needed around a leaf query 5755 * too, but those are more easily handled at the next level down (see 5756 * code above). 5757 */ 5758 if (IsA(op->larg, SetOperationStmt)) 5759 { 5760 SetOperationStmt *lop = (SetOperationStmt *) op->larg; 5761 5762 if (op->op == lop->op && op->all == lop->all) 5763 need_paren = false; 5764 else 5765 need_paren = true; 5766 } 5767 else 5768 need_paren = false; 5769 5770 if (need_paren) 5771 { 5772 appendStringInfoChar(buf, '('); 5773 subindent = PRETTYINDENT_STD; 5774 appendContextKeyword(context, "", subindent, 0, 0); 5775 } 5776 else 5777 subindent = 0; 5778 5779 get_setop_query(op->larg, query, context, resultDesc); 5780 5781 if (need_paren) 5782 appendContextKeyword(context, ") ", -subindent, 0, 0); 5783 else if (PRETTY_INDENT(context)) 5784 appendContextKeyword(context, "", -subindent, 0, 0); 5785 else 5786 appendStringInfoChar(buf, ' '); 5787 5788 switch (op->op) 5789 { 5790 case SETOP_UNION: 5791 appendStringInfoString(buf, "UNION "); 5792 break; 5793 case SETOP_INTERSECT: 5794 appendStringInfoString(buf, "INTERSECT "); 5795 break; 5796 case SETOP_EXCEPT: 5797 appendStringInfoString(buf, "EXCEPT "); 5798 break; 5799 default: 5800 elog(ERROR, "unrecognized set op: %d", 5801 (int) op->op); 5802 } 5803 if (op->all) 5804 appendStringInfoString(buf, "ALL "); 5805 5806 /* Always parenthesize if RHS is another setop */ 5807 need_paren = IsA(op->rarg, SetOperationStmt); 5808 5809 /* 5810 * The indentation code here is deliberately a bit different from that 5811 * for the lefthand input, because we want the line breaks in 5812 * different places. 5813 */ 5814 if (need_paren) 5815 { 5816 appendStringInfoChar(buf, '('); 5817 subindent = PRETTYINDENT_STD; 5818 } 5819 else 5820 subindent = 0; 5821 appendContextKeyword(context, "", subindent, 0, 0); 5822 5823 get_setop_query(op->rarg, query, context, resultDesc); 5824 5825 if (PRETTY_INDENT(context)) 5826 context->indentLevel -= subindent; 5827 if (need_paren) 5828 appendContextKeyword(context, ")", 0, 0, 0); 5829 } 5830 else 5831 { 5832 elog(ERROR, "unrecognized node type: %d", 5833 (int) nodeTag(setOp)); 5834 } 5835 } 5836 5837 /* 5838 * Display a sort/group clause. 5839 * 5840 * Also returns the expression tree, so caller need not find it again. 5841 */ 5842 static Node * 5843 get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, 5844 deparse_context *context) 5845 { 5846 StringInfo buf = context->buf; 5847 TargetEntry *tle; 5848 Node *expr; 5849 5850 tle = get_sortgroupref_tle(ref, tlist); 5851 expr = (Node *) tle->expr; 5852 5853 /* 5854 * Use column-number form if requested by caller. Otherwise, if 5855 * expression is a constant, force it to be dumped with an explicit cast 5856 * as decoration --- this is because a simple integer constant is 5857 * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we 5858 * dump it without any decoration. If it's anything more complex than a 5859 * simple Var, then force extra parens around it, to ensure it can't be 5860 * misinterpreted as a cube() or rollup() construct. 5861 */ 5862 if (force_colno) 5863 { 5864 Assert(!tle->resjunk); 5865 appendStringInfo(buf, "%d", tle->resno); 5866 } 5867 else if (expr && IsA(expr, Const)) 5868 get_const_expr((Const *) expr, context, 1); 5869 else if (!expr || IsA(expr, Var)) 5870 get_rule_expr(expr, context, true); 5871 else 5872 { 5873 /* 5874 * We must force parens for function-like expressions even if 5875 * PRETTY_PAREN is off, since those are the ones in danger of 5876 * misparsing. For other expressions we need to force them only if 5877 * PRETTY_PAREN is on, since otherwise the expression will output them 5878 * itself. (We can't skip the parens.) 5879 */ 5880 bool need_paren = (PRETTY_PAREN(context) 5881 || IsA(expr, FuncExpr) 5882 ||IsA(expr, Aggref) 5883 ||IsA(expr, WindowFunc)); 5884 5885 if (need_paren) 5886 appendStringInfoChar(context->buf, '('); 5887 get_rule_expr(expr, context, true); 5888 if (need_paren) 5889 appendStringInfoChar(context->buf, ')'); 5890 } 5891 5892 return expr; 5893 } 5894 5895 /* 5896 * Display a GroupingSet 5897 */ 5898 static void 5899 get_rule_groupingset(GroupingSet *gset, List *targetlist, 5900 bool omit_parens, deparse_context *context) 5901 { 5902 ListCell *l; 5903 StringInfo buf = context->buf; 5904 bool omit_child_parens = true; 5905 char *sep = ""; 5906 5907 switch (gset->kind) 5908 { 5909 case GROUPING_SET_EMPTY: 5910 appendStringInfoString(buf, "()"); 5911 return; 5912 5913 case GROUPING_SET_SIMPLE: 5914 { 5915 if (!omit_parens || list_length(gset->content) != 1) 5916 appendStringInfoChar(buf, '('); 5917 5918 foreach(l, gset->content) 5919 { 5920 Index ref = lfirst_int(l); 5921 5922 appendStringInfoString(buf, sep); 5923 get_rule_sortgroupclause(ref, targetlist, 5924 false, context); 5925 sep = ", "; 5926 } 5927 5928 if (!omit_parens || list_length(gset->content) != 1) 5929 appendStringInfoChar(buf, ')'); 5930 } 5931 return; 5932 5933 case GROUPING_SET_ROLLUP: 5934 appendStringInfoString(buf, "ROLLUP("); 5935 break; 5936 case GROUPING_SET_CUBE: 5937 appendStringInfoString(buf, "CUBE("); 5938 break; 5939 case GROUPING_SET_SETS: 5940 appendStringInfoString(buf, "GROUPING SETS ("); 5941 omit_child_parens = false; 5942 break; 5943 } 5944 5945 foreach(l, gset->content) 5946 { 5947 appendStringInfoString(buf, sep); 5948 get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context); 5949 sep = ", "; 5950 } 5951 5952 appendStringInfoChar(buf, ')'); 5953 } 5954 5955 /* 5956 * Display an ORDER BY list. 5957 */ 5958 static void 5959 get_rule_orderby(List *orderList, List *targetList, 5960 bool force_colno, deparse_context *context) 5961 { 5962 StringInfo buf = context->buf; 5963 const char *sep; 5964 ListCell *l; 5965 5966 sep = ""; 5967 foreach(l, orderList) 5968 { 5969 SortGroupClause *srt = (SortGroupClause *) lfirst(l); 5970 Node *sortexpr; 5971 Oid sortcoltype; 5972 TypeCacheEntry *typentry; 5973 5974 appendStringInfoString(buf, sep); 5975 sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList, 5976 force_colno, context); 5977 sortcoltype = exprType(sortexpr); 5978 /* See whether operator is default < or > for datatype */ 5979 typentry = lookup_type_cache(sortcoltype, 5980 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR); 5981 if (srt->sortop == typentry->lt_opr) 5982 { 5983 /* ASC is default, so emit nothing for it */ 5984 if (srt->nulls_first) 5985 appendStringInfoString(buf, " NULLS FIRST"); 5986 } 5987 else if (srt->sortop == typentry->gt_opr) 5988 { 5989 appendStringInfoString(buf, " DESC"); 5990 /* DESC defaults to NULLS FIRST */ 5991 if (!srt->nulls_first) 5992 appendStringInfoString(buf, " NULLS LAST"); 5993 } 5994 else 5995 { 5996 appendStringInfo(buf, " USING %s", 5997 generate_operator_name(srt->sortop, 5998 sortcoltype, 5999 sortcoltype)); 6000 /* be specific to eliminate ambiguity */ 6001 if (srt->nulls_first) 6002 appendStringInfoString(buf, " NULLS FIRST"); 6003 else 6004 appendStringInfoString(buf, " NULLS LAST"); 6005 } 6006 sep = ", "; 6007 } 6008 } 6009 6010 /* 6011 * Display a WINDOW clause. 6012 * 6013 * Note that the windowClause list might contain only anonymous window 6014 * specifications, in which case we should print nothing here. 6015 */ 6016 static void 6017 get_rule_windowclause(Query *query, deparse_context *context) 6018 { 6019 StringInfo buf = context->buf; 6020 const char *sep; 6021 ListCell *l; 6022 6023 sep = NULL; 6024 foreach(l, query->windowClause) 6025 { 6026 WindowClause *wc = (WindowClause *) lfirst(l); 6027 6028 if (wc->name == NULL) 6029 continue; /* ignore anonymous windows */ 6030 6031 if (sep == NULL) 6032 appendContextKeyword(context, " WINDOW ", 6033 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6034 else 6035 appendStringInfoString(buf, sep); 6036 6037 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name)); 6038 6039 get_rule_windowspec(wc, query->targetList, context); 6040 6041 sep = ", "; 6042 } 6043 } 6044 6045 /* 6046 * Display a window definition 6047 */ 6048 static void 6049 get_rule_windowspec(WindowClause *wc, List *targetList, 6050 deparse_context *context) 6051 { 6052 StringInfo buf = context->buf; 6053 bool needspace = false; 6054 const char *sep; 6055 ListCell *l; 6056 6057 appendStringInfoChar(buf, '('); 6058 if (wc->refname) 6059 { 6060 appendStringInfoString(buf, quote_identifier(wc->refname)); 6061 needspace = true; 6062 } 6063 /* partition clauses are always inherited, so only print if no refname */ 6064 if (wc->partitionClause && !wc->refname) 6065 { 6066 if (needspace) 6067 appendStringInfoChar(buf, ' '); 6068 appendStringInfoString(buf, "PARTITION BY "); 6069 sep = ""; 6070 foreach(l, wc->partitionClause) 6071 { 6072 SortGroupClause *grp = (SortGroupClause *) lfirst(l); 6073 6074 appendStringInfoString(buf, sep); 6075 get_rule_sortgroupclause(grp->tleSortGroupRef, targetList, 6076 false, context); 6077 sep = ", "; 6078 } 6079 needspace = true; 6080 } 6081 /* print ordering clause only if not inherited */ 6082 if (wc->orderClause && !wc->copiedOrder) 6083 { 6084 if (needspace) 6085 appendStringInfoChar(buf, ' '); 6086 appendStringInfoString(buf, "ORDER BY "); 6087 get_rule_orderby(wc->orderClause, targetList, false, context); 6088 needspace = true; 6089 } 6090 /* framing clause is never inherited, so print unless it's default */ 6091 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT) 6092 { 6093 if (needspace) 6094 appendStringInfoChar(buf, ' '); 6095 if (wc->frameOptions & FRAMEOPTION_RANGE) 6096 appendStringInfoString(buf, "RANGE "); 6097 else if (wc->frameOptions & FRAMEOPTION_ROWS) 6098 appendStringInfoString(buf, "ROWS "); 6099 else if (wc->frameOptions & FRAMEOPTION_GROUPS) 6100 appendStringInfoString(buf, "GROUPS "); 6101 else 6102 Assert(false); 6103 if (wc->frameOptions & FRAMEOPTION_BETWEEN) 6104 appendStringInfoString(buf, "BETWEEN "); 6105 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) 6106 appendStringInfoString(buf, "UNBOUNDED PRECEDING "); 6107 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW) 6108 appendStringInfoString(buf, "CURRENT ROW "); 6109 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET) 6110 { 6111 get_rule_expr(wc->startOffset, context, false); 6112 if (wc->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) 6113 appendStringInfoString(buf, " PRECEDING "); 6114 else if (wc->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) 6115 appendStringInfoString(buf, " FOLLOWING "); 6116 else 6117 Assert(false); 6118 } 6119 else 6120 Assert(false); 6121 if (wc->frameOptions & FRAMEOPTION_BETWEEN) 6122 { 6123 appendStringInfoString(buf, "AND "); 6124 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) 6125 appendStringInfoString(buf, "UNBOUNDED FOLLOWING "); 6126 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW) 6127 appendStringInfoString(buf, "CURRENT ROW "); 6128 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET) 6129 { 6130 get_rule_expr(wc->endOffset, context, false); 6131 if (wc->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) 6132 appendStringInfoString(buf, " PRECEDING "); 6133 else if (wc->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING) 6134 appendStringInfoString(buf, " FOLLOWING "); 6135 else 6136 Assert(false); 6137 } 6138 else 6139 Assert(false); 6140 } 6141 if (wc->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) 6142 appendStringInfoString(buf, "EXCLUDE CURRENT ROW "); 6143 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP) 6144 appendStringInfoString(buf, "EXCLUDE GROUP "); 6145 else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES) 6146 appendStringInfoString(buf, "EXCLUDE TIES "); 6147 /* we will now have a trailing space; remove it */ 6148 buf->len--; 6149 } 6150 appendStringInfoChar(buf, ')'); 6151 } 6152 6153 /* ---------- 6154 * get_insert_query_def - Parse back an INSERT parsetree 6155 * ---------- 6156 */ 6157 static void 6158 get_insert_query_def(Query *query, deparse_context *context) 6159 { 6160 StringInfo buf = context->buf; 6161 RangeTblEntry *select_rte = NULL; 6162 RangeTblEntry *values_rte = NULL; 6163 RangeTblEntry *rte; 6164 char *sep; 6165 ListCell *l; 6166 List *strippedexprs; 6167 6168 /* Insert the WITH clause if given */ 6169 get_with_clause(query, context); 6170 6171 /* 6172 * If it's an INSERT ... SELECT or multi-row VALUES, there will be a 6173 * single RTE for the SELECT or VALUES. Plain VALUES has neither. 6174 */ 6175 foreach(l, query->rtable) 6176 { 6177 rte = (RangeTblEntry *) lfirst(l); 6178 6179 if (rte->rtekind == RTE_SUBQUERY) 6180 { 6181 if (select_rte) 6182 elog(ERROR, "too many subquery RTEs in INSERT"); 6183 select_rte = rte; 6184 } 6185 6186 if (rte->rtekind == RTE_VALUES) 6187 { 6188 if (values_rte) 6189 elog(ERROR, "too many values RTEs in INSERT"); 6190 values_rte = rte; 6191 } 6192 } 6193 if (select_rte && values_rte) 6194 elog(ERROR, "both subquery and values RTEs in INSERT"); 6195 6196 /* 6197 * Start the query with INSERT INTO relname 6198 */ 6199 rte = rt_fetch(query->resultRelation, query->rtable); 6200 Assert(rte->rtekind == RTE_RELATION); 6201 6202 if (PRETTY_INDENT(context)) 6203 { 6204 context->indentLevel += PRETTYINDENT_STD; 6205 appendStringInfoChar(buf, ' '); 6206 } 6207 appendStringInfo(buf, "INSERT INTO %s ", 6208 generate_relation_name(rte->relid, NIL)); 6209 /* INSERT requires AS keyword for target alias */ 6210 if (rte->alias != NULL) 6211 appendStringInfo(buf, "AS %s ", 6212 quote_identifier(rte->alias->aliasname)); 6213 6214 /* 6215 * Add the insert-column-names list. Any indirection decoration needed on 6216 * the column names can be inferred from the top targetlist. 6217 */ 6218 strippedexprs = NIL; 6219 sep = ""; 6220 if (query->targetList) 6221 appendStringInfoChar(buf, '('); 6222 foreach(l, query->targetList) 6223 { 6224 TargetEntry *tle = (TargetEntry *) lfirst(l); 6225 6226 if (tle->resjunk) 6227 continue; /* ignore junk entries */ 6228 6229 appendStringInfoString(buf, sep); 6230 sep = ", "; 6231 6232 /* 6233 * Put out name of target column; look in the catalogs, not at 6234 * tle->resname, since resname will fail to track RENAME. 6235 */ 6236 appendStringInfoString(buf, 6237 quote_identifier(get_attname(rte->relid, 6238 tle->resno, 6239 false))); 6240 6241 /* 6242 * Print any indirection needed (subfields or subscripts), and strip 6243 * off the top-level nodes representing the indirection assignments. 6244 * Add the stripped expressions to strippedexprs. (If it's a 6245 * single-VALUES statement, the stripped expressions are the VALUES to 6246 * print below. Otherwise they're just Vars and not really 6247 * interesting.) 6248 */ 6249 strippedexprs = lappend(strippedexprs, 6250 processIndirection((Node *) tle->expr, 6251 context)); 6252 } 6253 if (query->targetList) 6254 appendStringInfoString(buf, ") "); 6255 6256 if (query->override) 6257 { 6258 if (query->override == OVERRIDING_SYSTEM_VALUE) 6259 appendStringInfoString(buf, "OVERRIDING SYSTEM VALUE "); 6260 else if (query->override == OVERRIDING_USER_VALUE) 6261 appendStringInfoString(buf, "OVERRIDING USER VALUE "); 6262 } 6263 6264 if (select_rte) 6265 { 6266 /* Add the SELECT */ 6267 get_query_def(select_rte->subquery, buf, NIL, NULL, 6268 context->prettyFlags, context->wrapColumn, 6269 context->indentLevel); 6270 } 6271 else if (values_rte) 6272 { 6273 /* Add the multi-VALUES expression lists */ 6274 get_values_def(values_rte->values_lists, context); 6275 } 6276 else if (strippedexprs) 6277 { 6278 /* Add the single-VALUES expression list */ 6279 appendContextKeyword(context, "VALUES (", 6280 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); 6281 get_rule_expr((Node *) strippedexprs, context, false); 6282 appendStringInfoChar(buf, ')'); 6283 } 6284 else 6285 { 6286 /* No expressions, so it must be DEFAULT VALUES */ 6287 appendStringInfoString(buf, "DEFAULT VALUES"); 6288 } 6289 6290 /* Add ON CONFLICT if present */ 6291 if (query->onConflict) 6292 { 6293 OnConflictExpr *confl = query->onConflict; 6294 6295 appendStringInfoString(buf, " ON CONFLICT"); 6296 6297 if (confl->arbiterElems) 6298 { 6299 /* Add the single-VALUES expression list */ 6300 appendStringInfoChar(buf, '('); 6301 get_rule_expr((Node *) confl->arbiterElems, context, false); 6302 appendStringInfoChar(buf, ')'); 6303 6304 /* Add a WHERE clause (for partial indexes) if given */ 6305 if (confl->arbiterWhere != NULL) 6306 { 6307 bool save_varprefix; 6308 6309 /* 6310 * Force non-prefixing of Vars, since parser assumes that they 6311 * belong to target relation. WHERE clause does not use 6312 * InferenceElem, so this is separately required. 6313 */ 6314 save_varprefix = context->varprefix; 6315 context->varprefix = false; 6316 6317 appendContextKeyword(context, " WHERE ", 6318 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6319 get_rule_expr(confl->arbiterWhere, context, false); 6320 6321 context->varprefix = save_varprefix; 6322 } 6323 } 6324 else if (OidIsValid(confl->constraint)) 6325 { 6326 char *constraint = get_constraint_name(confl->constraint); 6327 6328 if (!constraint) 6329 elog(ERROR, "cache lookup failed for constraint %u", 6330 confl->constraint); 6331 appendStringInfo(buf, " ON CONSTRAINT %s", 6332 quote_identifier(constraint)); 6333 } 6334 6335 if (confl->action == ONCONFLICT_NOTHING) 6336 { 6337 appendStringInfoString(buf, " DO NOTHING"); 6338 } 6339 else 6340 { 6341 appendStringInfoString(buf, " DO UPDATE SET "); 6342 /* Deparse targetlist */ 6343 get_update_query_targetlist_def(query, confl->onConflictSet, 6344 context, rte); 6345 6346 /* Add a WHERE clause if given */ 6347 if (confl->onConflictWhere != NULL) 6348 { 6349 appendContextKeyword(context, " WHERE ", 6350 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6351 get_rule_expr(confl->onConflictWhere, context, false); 6352 } 6353 } 6354 } 6355 6356 /* Add RETURNING if present */ 6357 if (query->returningList) 6358 { 6359 appendContextKeyword(context, " RETURNING", 6360 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6361 get_target_list(query->returningList, context, NULL); 6362 } 6363 } 6364 6365 6366 /* ---------- 6367 * get_update_query_def - Parse back an UPDATE parsetree 6368 * ---------- 6369 */ 6370 static void 6371 get_update_query_def(Query *query, deparse_context *context) 6372 { 6373 StringInfo buf = context->buf; 6374 RangeTblEntry *rte; 6375 6376 /* Insert the WITH clause if given */ 6377 get_with_clause(query, context); 6378 6379 /* 6380 * Start the query with UPDATE relname SET 6381 */ 6382 rte = rt_fetch(query->resultRelation, query->rtable); 6383 Assert(rte->rtekind == RTE_RELATION); 6384 if (PRETTY_INDENT(context)) 6385 { 6386 appendStringInfoChar(buf, ' '); 6387 context->indentLevel += PRETTYINDENT_STD; 6388 } 6389 appendStringInfo(buf, "UPDATE %s%s", 6390 only_marker(rte), 6391 generate_relation_name(rte->relid, NIL)); 6392 if (rte->alias != NULL) 6393 appendStringInfo(buf, " %s", 6394 quote_identifier(rte->alias->aliasname)); 6395 appendStringInfoString(buf, " SET "); 6396 6397 /* Deparse targetlist */ 6398 get_update_query_targetlist_def(query, query->targetList, context, rte); 6399 6400 /* Add the FROM clause if needed */ 6401 get_from_clause(query, " FROM ", context); 6402 6403 /* Add a WHERE clause if given */ 6404 if (query->jointree->quals != NULL) 6405 { 6406 appendContextKeyword(context, " WHERE ", 6407 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6408 get_rule_expr(query->jointree->quals, context, false); 6409 } 6410 6411 /* Add RETURNING if present */ 6412 if (query->returningList) 6413 { 6414 appendContextKeyword(context, " RETURNING", 6415 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6416 get_target_list(query->returningList, context, NULL); 6417 } 6418 } 6419 6420 6421 /* ---------- 6422 * get_update_query_targetlist_def - Parse back an UPDATE targetlist 6423 * ---------- 6424 */ 6425 static void 6426 get_update_query_targetlist_def(Query *query, List *targetList, 6427 deparse_context *context, RangeTblEntry *rte) 6428 { 6429 StringInfo buf = context->buf; 6430 ListCell *l; 6431 ListCell *next_ma_cell; 6432 int remaining_ma_columns; 6433 const char *sep; 6434 SubLink *cur_ma_sublink; 6435 List *ma_sublinks; 6436 6437 /* 6438 * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks 6439 * into a list. We expect them to appear, in ID order, in resjunk tlist 6440 * entries. 6441 */ 6442 ma_sublinks = NIL; 6443 if (query->hasSubLinks) /* else there can't be any */ 6444 { 6445 foreach(l, targetList) 6446 { 6447 TargetEntry *tle = (TargetEntry *) lfirst(l); 6448 6449 if (tle->resjunk && IsA(tle->expr, SubLink)) 6450 { 6451 SubLink *sl = (SubLink *) tle->expr; 6452 6453 if (sl->subLinkType == MULTIEXPR_SUBLINK) 6454 { 6455 ma_sublinks = lappend(ma_sublinks, sl); 6456 Assert(sl->subLinkId == list_length(ma_sublinks)); 6457 } 6458 } 6459 } 6460 } 6461 next_ma_cell = list_head(ma_sublinks); 6462 cur_ma_sublink = NULL; 6463 remaining_ma_columns = 0; 6464 6465 /* Add the comma separated list of 'attname = value' */ 6466 sep = ""; 6467 foreach(l, targetList) 6468 { 6469 TargetEntry *tle = (TargetEntry *) lfirst(l); 6470 Node *expr; 6471 6472 if (tle->resjunk) 6473 continue; /* ignore junk entries */ 6474 6475 /* Emit separator (OK whether we're in multiassignment or not) */ 6476 appendStringInfoString(buf, sep); 6477 sep = ", "; 6478 6479 /* 6480 * Check to see if we're starting a multiassignment group: if so, 6481 * output a left paren. 6482 */ 6483 if (next_ma_cell != NULL && cur_ma_sublink == NULL) 6484 { 6485 /* 6486 * We must dig down into the expr to see if it's a PARAM_MULTIEXPR 6487 * Param. That could be buried under FieldStores and 6488 * SubscriptingRefs and CoerceToDomains (cf processIndirection()), 6489 * and underneath those there could be an implicit type coercion. 6490 * Because we would ignore implicit type coercions anyway, we 6491 * don't need to be as careful as processIndirection() is about 6492 * descending past implicit CoerceToDomains. 6493 */ 6494 expr = (Node *) tle->expr; 6495 while (expr) 6496 { 6497 if (IsA(expr, FieldStore)) 6498 { 6499 FieldStore *fstore = (FieldStore *) expr; 6500 6501 expr = (Node *) linitial(fstore->newvals); 6502 } 6503 else if (IsA(expr, SubscriptingRef)) 6504 { 6505 SubscriptingRef *sbsref = (SubscriptingRef *) expr; 6506 6507 if (sbsref->refassgnexpr == NULL) 6508 break; 6509 6510 expr = (Node *) sbsref->refassgnexpr; 6511 } 6512 else if (IsA(expr, CoerceToDomain)) 6513 { 6514 CoerceToDomain *cdomain = (CoerceToDomain *) expr; 6515 6516 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST) 6517 break; 6518 expr = (Node *) cdomain->arg; 6519 } 6520 else 6521 break; 6522 } 6523 expr = strip_implicit_coercions(expr); 6524 6525 if (expr && IsA(expr, Param) && 6526 ((Param *) expr)->paramkind == PARAM_MULTIEXPR) 6527 { 6528 cur_ma_sublink = (SubLink *) lfirst(next_ma_cell); 6529 next_ma_cell = lnext(next_ma_cell); 6530 remaining_ma_columns = count_nonjunk_tlist_entries( 6531 ((Query *) cur_ma_sublink->subselect)->targetList); 6532 Assert(((Param *) expr)->paramid == 6533 ((cur_ma_sublink->subLinkId << 16) | 1)); 6534 appendStringInfoChar(buf, '('); 6535 } 6536 } 6537 6538 /* 6539 * Put out name of target column; look in the catalogs, not at 6540 * tle->resname, since resname will fail to track RENAME. 6541 */ 6542 appendStringInfoString(buf, 6543 quote_identifier(get_attname(rte->relid, 6544 tle->resno, 6545 false))); 6546 6547 /* 6548 * Print any indirection needed (subfields or subscripts), and strip 6549 * off the top-level nodes representing the indirection assignments. 6550 */ 6551 expr = processIndirection((Node *) tle->expr, context); 6552 6553 /* 6554 * If we're in a multiassignment, skip printing anything more, unless 6555 * this is the last column; in which case, what we print should be the 6556 * sublink, not the Param. 6557 */ 6558 if (cur_ma_sublink != NULL) 6559 { 6560 if (--remaining_ma_columns > 0) 6561 continue; /* not the last column of multiassignment */ 6562 appendStringInfoChar(buf, ')'); 6563 expr = (Node *) cur_ma_sublink; 6564 cur_ma_sublink = NULL; 6565 } 6566 6567 appendStringInfoString(buf, " = "); 6568 6569 get_rule_expr(expr, context, false); 6570 } 6571 } 6572 6573 6574 /* ---------- 6575 * get_delete_query_def - Parse back a DELETE parsetree 6576 * ---------- 6577 */ 6578 static void 6579 get_delete_query_def(Query *query, deparse_context *context) 6580 { 6581 StringInfo buf = context->buf; 6582 RangeTblEntry *rte; 6583 6584 /* Insert the WITH clause if given */ 6585 get_with_clause(query, context); 6586 6587 /* 6588 * Start the query with DELETE FROM relname 6589 */ 6590 rte = rt_fetch(query->resultRelation, query->rtable); 6591 Assert(rte->rtekind == RTE_RELATION); 6592 if (PRETTY_INDENT(context)) 6593 { 6594 appendStringInfoChar(buf, ' '); 6595 context->indentLevel += PRETTYINDENT_STD; 6596 } 6597 appendStringInfo(buf, "DELETE FROM %s%s", 6598 only_marker(rte), 6599 generate_relation_name(rte->relid, NIL)); 6600 if (rte->alias != NULL) 6601 appendStringInfo(buf, " %s", 6602 quote_identifier(rte->alias->aliasname)); 6603 6604 /* Add the USING clause if given */ 6605 get_from_clause(query, " USING ", context); 6606 6607 /* Add a WHERE clause if given */ 6608 if (query->jointree->quals != NULL) 6609 { 6610 appendContextKeyword(context, " WHERE ", 6611 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6612 get_rule_expr(query->jointree->quals, context, false); 6613 } 6614 6615 /* Add RETURNING if present */ 6616 if (query->returningList) 6617 { 6618 appendContextKeyword(context, " RETURNING", 6619 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); 6620 get_target_list(query->returningList, context, NULL); 6621 } 6622 } 6623 6624 6625 /* ---------- 6626 * get_utility_query_def - Parse back a UTILITY parsetree 6627 * ---------- 6628 */ 6629 static void 6630 get_utility_query_def(Query *query, deparse_context *context) 6631 { 6632 StringInfo buf = context->buf; 6633 6634 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) 6635 { 6636 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; 6637 6638 appendContextKeyword(context, "", 6639 0, PRETTYINDENT_STD, 1); 6640 appendStringInfo(buf, "NOTIFY %s", 6641 quote_identifier(stmt->conditionname)); 6642 if (stmt->payload) 6643 { 6644 appendStringInfoString(buf, ", "); 6645 simple_quote_literal(buf, stmt->payload); 6646 } 6647 } 6648 else 6649 { 6650 /* Currently only NOTIFY utility commands can appear in rules */ 6651 elog(ERROR, "unexpected utility statement type"); 6652 } 6653 } 6654 6655 /* 6656 * Display a Var appropriately. 6657 * 6658 * In some cases (currently only when recursing into an unnamed join) 6659 * the Var's varlevelsup has to be interpreted with respect to a context 6660 * above the current one; levelsup indicates the offset. 6661 * 6662 * If istoplevel is true, the Var is at the top level of a SELECT's 6663 * targetlist, which means we need special treatment of whole-row Vars. 6664 * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a 6665 * dirty hack to prevent "tab.*" from being expanded into multiple columns. 6666 * (The parser will strip the useless coercion, so no inefficiency is added in 6667 * dump and reload.) We used to print just "tab" in such cases, but that is 6668 * ambiguous and will yield the wrong result if "tab" is also a plain column 6669 * name in the query. 6670 * 6671 * Returns the attname of the Var, or NULL if the Var has no attname (because 6672 * it is a whole-row Var or a subplan output reference). 6673 */ 6674 static char * 6675 get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) 6676 { 6677 StringInfo buf = context->buf; 6678 RangeTblEntry *rte; 6679 AttrNumber attnum; 6680 int netlevelsup; 6681 deparse_namespace *dpns; 6682 deparse_columns *colinfo; 6683 char *refname; 6684 char *attname; 6685 6686 /* Find appropriate nesting depth */ 6687 netlevelsup = var->varlevelsup + levelsup; 6688 if (netlevelsup >= list_length(context->namespaces)) 6689 elog(ERROR, "bogus varlevelsup: %d offset %d", 6690 var->varlevelsup, levelsup); 6691 dpns = (deparse_namespace *) list_nth(context->namespaces, 6692 netlevelsup); 6693 6694 /* 6695 * Try to find the relevant RTE in this rtable. In a plan tree, it's 6696 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig 6697 * down into the subplans, or INDEX_VAR, which is resolved similarly. Also 6698 * find the aliases previously assigned for this RTE. 6699 */ 6700 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) 6701 { 6702 rte = rt_fetch(var->varno, dpns->rtable); 6703 refname = (char *) list_nth(dpns->rtable_names, var->varno - 1); 6704 colinfo = deparse_columns_fetch(var->varno, dpns); 6705 attnum = var->varattno; 6706 } 6707 else 6708 { 6709 resolve_special_varno((Node *) var, context, NULL, 6710 get_special_variable); 6711 return NULL; 6712 } 6713 6714 /* 6715 * The planner will sometimes emit Vars referencing resjunk elements of a 6716 * subquery's target list (this is currently only possible if it chooses 6717 * to generate a "physical tlist" for a SubqueryScan or CteScan node). 6718 * Although we prefer to print subquery-referencing Vars using the 6719 * subquery's alias, that's not possible for resjunk items since they have 6720 * no alias. So in that case, drill down to the subplan and print the 6721 * contents of the referenced tlist item. This works because in a plan 6722 * tree, such Vars can only occur in a SubqueryScan or CteScan node, and 6723 * we'll have set dpns->inner_planstate to reference the child plan node. 6724 */ 6725 if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) && 6726 attnum > list_length(rte->eref->colnames) && 6727 dpns->inner_planstate) 6728 { 6729 TargetEntry *tle; 6730 deparse_namespace save_dpns; 6731 6732 tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); 6733 if (!tle) 6734 elog(ERROR, "invalid attnum %d for relation \"%s\"", 6735 var->varattno, rte->eref->aliasname); 6736 6737 Assert(netlevelsup == 0); 6738 push_child_plan(dpns, dpns->inner_planstate, &save_dpns); 6739 6740 /* 6741 * Force parentheses because our caller probably assumed a Var is a 6742 * simple expression. 6743 */ 6744 if (!IsA(tle->expr, Var)) 6745 appendStringInfoChar(buf, '('); 6746 get_rule_expr((Node *) tle->expr, context, true); 6747 if (!IsA(tle->expr, Var)) 6748 appendStringInfoChar(buf, ')'); 6749 6750 pop_child_plan(dpns, &save_dpns); 6751 return NULL; 6752 } 6753 6754 /* 6755 * If it's an unnamed join, look at the expansion of the alias variable. 6756 * If it's a simple reference to one of the input vars, then recursively 6757 * print the name of that var instead. When it's not a simple reference, 6758 * we have to just print the unqualified join column name. (This can only 6759 * happen with "dangerous" merged columns in a JOIN USING; we took pains 6760 * previously to make the unqualified column name unique in such cases.) 6761 * 6762 * This wouldn't work in decompiling plan trees, because we don't store 6763 * joinaliasvars lists after planning; but a plan tree should never 6764 * contain a join alias variable. 6765 */ 6766 if (rte->rtekind == RTE_JOIN && rte->alias == NULL) 6767 { 6768 if (rte->joinaliasvars == NIL) 6769 elog(ERROR, "cannot decompile join alias var in plan tree"); 6770 if (attnum > 0) 6771 { 6772 Var *aliasvar; 6773 6774 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1); 6775 /* we intentionally don't strip implicit coercions here */ 6776 if (aliasvar && IsA(aliasvar, Var)) 6777 { 6778 return get_variable(aliasvar, var->varlevelsup + levelsup, 6779 istoplevel, context); 6780 } 6781 } 6782 6783 /* 6784 * Unnamed join has no refname. (Note: since it's unnamed, there is 6785 * no way the user could have referenced it to create a whole-row Var 6786 * for it. So we don't have to cover that case below.) 6787 */ 6788 Assert(refname == NULL); 6789 } 6790 6791 if (attnum == InvalidAttrNumber) 6792 attname = NULL; 6793 else if (attnum > 0) 6794 { 6795 /* Get column name to use from the colinfo struct */ 6796 if (attnum > colinfo->num_cols) 6797 elog(ERROR, "invalid attnum %d for relation \"%s\"", 6798 attnum, rte->eref->aliasname); 6799 attname = colinfo->colnames[attnum - 1]; 6800 if (attname == NULL) /* dropped column? */ 6801 elog(ERROR, "invalid attnum %d for relation \"%s\"", 6802 attnum, rte->eref->aliasname); 6803 } 6804 else 6805 { 6806 /* System column - name is fixed, get it from the catalog */ 6807 attname = get_rte_attribute_name(rte, attnum); 6808 } 6809 6810 if (refname && (context->varprefix || attname == NULL)) 6811 { 6812 appendStringInfoString(buf, quote_identifier(refname)); 6813 appendStringInfoChar(buf, '.'); 6814 } 6815 if (attname) 6816 appendStringInfoString(buf, quote_identifier(attname)); 6817 else 6818 { 6819 appendStringInfoChar(buf, '*'); 6820 if (istoplevel) 6821 appendStringInfo(buf, "::%s", 6822 format_type_with_typemod(var->vartype, 6823 var->vartypmod)); 6824 } 6825 6826 return attname; 6827 } 6828 6829 /* 6830 * Deparse a Var which references OUTER_VAR, INNER_VAR, or INDEX_VAR. This 6831 * routine is actually a callback for get_special_varno, which handles finding 6832 * the correct TargetEntry. We get the expression contained in that 6833 * TargetEntry and just need to deparse it, a job we can throw back on 6834 * get_rule_expr. 6835 */ 6836 static void 6837 get_special_variable(Node *node, deparse_context *context, void *private) 6838 { 6839 StringInfo buf = context->buf; 6840 6841 /* 6842 * Force parentheses because our caller probably assumed a Var is a simple 6843 * expression. 6844 */ 6845 if (!IsA(node, Var)) 6846 appendStringInfoChar(buf, '('); 6847 get_rule_expr(node, context, true); 6848 if (!IsA(node, Var)) 6849 appendStringInfoChar(buf, ')'); 6850 } 6851 6852 /* 6853 * Chase through plan references to special varnos (OUTER_VAR, INNER_VAR, 6854 * INDEX_VAR) until we find a real Var or some kind of non-Var node; then, 6855 * invoke the callback provided. 6856 */ 6857 static void 6858 resolve_special_varno(Node *node, deparse_context *context, void *private, 6859 void (*callback) (Node *, deparse_context *, void *)) 6860 { 6861 Var *var; 6862 deparse_namespace *dpns; 6863 6864 /* If it's not a Var, invoke the callback. */ 6865 if (!IsA(node, Var)) 6866 { 6867 callback(node, context, private); 6868 return; 6869 } 6870 6871 /* Find appropriate nesting depth */ 6872 var = (Var *) node; 6873 dpns = (deparse_namespace *) list_nth(context->namespaces, 6874 var->varlevelsup); 6875 6876 /* 6877 * It's a special RTE, so recurse. 6878 */ 6879 if (var->varno == OUTER_VAR && dpns->outer_tlist) 6880 { 6881 TargetEntry *tle; 6882 deparse_namespace save_dpns; 6883 6884 tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); 6885 if (!tle) 6886 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); 6887 6888 push_child_plan(dpns, dpns->outer_planstate, &save_dpns); 6889 resolve_special_varno((Node *) tle->expr, context, private, callback); 6890 pop_child_plan(dpns, &save_dpns); 6891 return; 6892 } 6893 else if (var->varno == INNER_VAR && dpns->inner_tlist) 6894 { 6895 TargetEntry *tle; 6896 deparse_namespace save_dpns; 6897 6898 tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); 6899 if (!tle) 6900 elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); 6901 6902 push_child_plan(dpns, dpns->inner_planstate, &save_dpns); 6903 resolve_special_varno((Node *) tle->expr, context, private, callback); 6904 pop_child_plan(dpns, &save_dpns); 6905 return; 6906 } 6907 else if (var->varno == INDEX_VAR && dpns->index_tlist) 6908 { 6909 TargetEntry *tle; 6910 6911 tle = get_tle_by_resno(dpns->index_tlist, var->varattno); 6912 if (!tle) 6913 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); 6914 6915 resolve_special_varno((Node *) tle->expr, context, private, callback); 6916 return; 6917 } 6918 else if (var->varno < 1 || var->varno > list_length(dpns->rtable)) 6919 elog(ERROR, "bogus varno: %d", var->varno); 6920 6921 /* Not special. Just invoke the callback. */ 6922 callback(node, context, private); 6923 } 6924 6925 /* 6926 * Get the name of a field of an expression of composite type. The 6927 * expression is usually a Var, but we handle other cases too. 6928 * 6929 * levelsup is an extra offset to interpret the Var's varlevelsup correctly. 6930 * 6931 * This is fairly straightforward when the expression has a named composite 6932 * type; we need only look up the type in the catalogs. However, the type 6933 * could also be RECORD. Since no actual table or view column is allowed to 6934 * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE 6935 * or to a subquery output. We drill down to find the ultimate defining 6936 * expression and attempt to infer the field name from it. We ereport if we 6937 * can't determine the name. 6938 * 6939 * Similarly, a PARAM of type RECORD has to refer to some expression of 6940 * a determinable composite type. 6941 */ 6942 static const char * 6943 get_name_for_var_field(Var *var, int fieldno, 6944 int levelsup, deparse_context *context) 6945 { 6946 RangeTblEntry *rte; 6947 AttrNumber attnum; 6948 int netlevelsup; 6949 deparse_namespace *dpns; 6950 TupleDesc tupleDesc; 6951 Node *expr; 6952 6953 /* 6954 * If it's a RowExpr that was expanded from a whole-row Var, use the 6955 * column names attached to it. 6956 */ 6957 if (IsA(var, RowExpr)) 6958 { 6959 RowExpr *r = (RowExpr *) var; 6960 6961 if (fieldno > 0 && fieldno <= list_length(r->colnames)) 6962 return strVal(list_nth(r->colnames, fieldno - 1)); 6963 } 6964 6965 /* 6966 * If it's a Param of type RECORD, try to find what the Param refers to. 6967 */ 6968 if (IsA(var, Param)) 6969 { 6970 Param *param = (Param *) var; 6971 ListCell *ancestor_cell; 6972 6973 expr = find_param_referent(param, context, &dpns, &ancestor_cell); 6974 if (expr) 6975 { 6976 /* Found a match, so recurse to decipher the field name */ 6977 deparse_namespace save_dpns; 6978 const char *result; 6979 6980 push_ancestor_plan(dpns, ancestor_cell, &save_dpns); 6981 result = get_name_for_var_field((Var *) expr, fieldno, 6982 0, context); 6983 pop_ancestor_plan(dpns, &save_dpns); 6984 return result; 6985 } 6986 } 6987 6988 /* 6989 * If it's a Var of type RECORD, we have to find what the Var refers to; 6990 * if not, we can use get_expr_result_tupdesc(). 6991 */ 6992 if (!IsA(var, Var) || 6993 var->vartype != RECORDOID) 6994 { 6995 tupleDesc = get_expr_result_tupdesc((Node *) var, false); 6996 /* Got the tupdesc, so we can extract the field name */ 6997 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); 6998 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname); 6999 } 7000 7001 /* Find appropriate nesting depth */ 7002 netlevelsup = var->varlevelsup + levelsup; 7003 if (netlevelsup >= list_length(context->namespaces)) 7004 elog(ERROR, "bogus varlevelsup: %d offset %d", 7005 var->varlevelsup, levelsup); 7006 dpns = (deparse_namespace *) list_nth(context->namespaces, 7007 netlevelsup); 7008 7009 /* 7010 * Try to find the relevant RTE in this rtable. In a plan tree, it's 7011 * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig 7012 * down into the subplans, or INDEX_VAR, which is resolved similarly. 7013 */ 7014 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) 7015 { 7016 rte = rt_fetch(var->varno, dpns->rtable); 7017 attnum = var->varattno; 7018 } 7019 else if (var->varno == OUTER_VAR && dpns->outer_tlist) 7020 { 7021 TargetEntry *tle; 7022 deparse_namespace save_dpns; 7023 const char *result; 7024 7025 tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); 7026 if (!tle) 7027 elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); 7028 7029 Assert(netlevelsup == 0); 7030 push_child_plan(dpns, dpns->outer_planstate, &save_dpns); 7031 7032 result = get_name_for_var_field((Var *) tle->expr, fieldno, 7033 levelsup, context); 7034 7035 pop_child_plan(dpns, &save_dpns); 7036 return result; 7037 } 7038 else if (var->varno == INNER_VAR && dpns->inner_tlist) 7039 { 7040 TargetEntry *tle; 7041 deparse_namespace save_dpns; 7042 const char *result; 7043 7044 tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); 7045 if (!tle) 7046 elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); 7047 7048 Assert(netlevelsup == 0); 7049 push_child_plan(dpns, dpns->inner_planstate, &save_dpns); 7050 7051 result = get_name_for_var_field((Var *) tle->expr, fieldno, 7052 levelsup, context); 7053 7054 pop_child_plan(dpns, &save_dpns); 7055 return result; 7056 } 7057 else if (var->varno == INDEX_VAR && dpns->index_tlist) 7058 { 7059 TargetEntry *tle; 7060 const char *result; 7061 7062 tle = get_tle_by_resno(dpns->index_tlist, var->varattno); 7063 if (!tle) 7064 elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); 7065 7066 Assert(netlevelsup == 0); 7067 7068 result = get_name_for_var_field((Var *) tle->expr, fieldno, 7069 levelsup, context); 7070 7071 return result; 7072 } 7073 else 7074 { 7075 elog(ERROR, "bogus varno: %d", var->varno); 7076 return NULL; /* keep compiler quiet */ 7077 } 7078 7079 if (attnum == InvalidAttrNumber) 7080 { 7081 /* Var is whole-row reference to RTE, so select the right field */ 7082 return get_rte_attribute_name(rte, fieldno); 7083 } 7084 7085 /* 7086 * This part has essentially the same logic as the parser's 7087 * expandRecordVariable() function, but we are dealing with a different 7088 * representation of the input context, and we only need one field name 7089 * not a TupleDesc. Also, we need special cases for finding subquery and 7090 * CTE subplans when deparsing Plan trees. 7091 */ 7092 expr = (Node *) var; /* default if we can't drill down */ 7093 7094 switch (rte->rtekind) 7095 { 7096 case RTE_RELATION: 7097 case RTE_VALUES: 7098 case RTE_NAMEDTUPLESTORE: 7099 case RTE_RESULT: 7100 7101 /* 7102 * This case should not occur: a column of a table, values list, 7103 * or ENR shouldn't have type RECORD. Fall through and fail (most 7104 * likely) at the bottom. 7105 */ 7106 break; 7107 case RTE_SUBQUERY: 7108 /* Subselect-in-FROM: examine sub-select's output expr */ 7109 { 7110 if (rte->subquery) 7111 { 7112 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, 7113 attnum); 7114 7115 if (ste == NULL || ste->resjunk) 7116 elog(ERROR, "subquery %s does not have attribute %d", 7117 rte->eref->aliasname, attnum); 7118 expr = (Node *) ste->expr; 7119 if (IsA(expr, Var)) 7120 { 7121 /* 7122 * Recurse into the sub-select to see what its Var 7123 * refers to. We have to build an additional level of 7124 * namespace to keep in step with varlevelsup in the 7125 * subselect. 7126 */ 7127 deparse_namespace mydpns; 7128 const char *result; 7129 7130 set_deparse_for_query(&mydpns, rte->subquery, 7131 context->namespaces); 7132 7133 context->namespaces = lcons(&mydpns, 7134 context->namespaces); 7135 7136 result = get_name_for_var_field((Var *) expr, fieldno, 7137 0, context); 7138 7139 context->namespaces = 7140 list_delete_first(context->namespaces); 7141 7142 return result; 7143 } 7144 /* else fall through to inspect the expression */ 7145 } 7146 else 7147 { 7148 /* 7149 * We're deparsing a Plan tree so we don't have complete 7150 * RTE entries (in particular, rte->subquery is NULL). But 7151 * the only place we'd see a Var directly referencing a 7152 * SUBQUERY RTE is in a SubqueryScan plan node, and we can 7153 * look into the child plan's tlist instead. 7154 */ 7155 TargetEntry *tle; 7156 deparse_namespace save_dpns; 7157 const char *result; 7158 7159 if (!dpns->inner_planstate) 7160 elog(ERROR, "failed to find plan for subquery %s", 7161 rte->eref->aliasname); 7162 tle = get_tle_by_resno(dpns->inner_tlist, attnum); 7163 if (!tle) 7164 elog(ERROR, "bogus varattno for subquery var: %d", 7165 attnum); 7166 Assert(netlevelsup == 0); 7167 push_child_plan(dpns, dpns->inner_planstate, &save_dpns); 7168 7169 result = get_name_for_var_field((Var *) tle->expr, fieldno, 7170 levelsup, context); 7171 7172 pop_child_plan(dpns, &save_dpns); 7173 return result; 7174 } 7175 } 7176 break; 7177 case RTE_JOIN: 7178 /* Join RTE --- recursively inspect the alias variable */ 7179 if (rte->joinaliasvars == NIL) 7180 elog(ERROR, "cannot decompile join alias var in plan tree"); 7181 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); 7182 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1); 7183 Assert(expr != NULL); 7184 /* we intentionally don't strip implicit coercions here */ 7185 if (IsA(expr, Var)) 7186 return get_name_for_var_field((Var *) expr, fieldno, 7187 var->varlevelsup + levelsup, 7188 context); 7189 /* else fall through to inspect the expression */ 7190 break; 7191 case RTE_FUNCTION: 7192 case RTE_TABLEFUNC: 7193 7194 /* 7195 * We couldn't get here unless a function is declared with one of 7196 * its result columns as RECORD, which is not allowed. 7197 */ 7198 break; 7199 case RTE_CTE: 7200 /* CTE reference: examine subquery's output expr */ 7201 { 7202 CommonTableExpr *cte = NULL; 7203 Index ctelevelsup; 7204 ListCell *lc; 7205 7206 /* 7207 * Try to find the referenced CTE using the namespace stack. 7208 */ 7209 ctelevelsup = rte->ctelevelsup + netlevelsup; 7210 if (ctelevelsup >= list_length(context->namespaces)) 7211 lc = NULL; 7212 else 7213 { 7214 deparse_namespace *ctedpns; 7215 7216 ctedpns = (deparse_namespace *) 7217 list_nth(context->namespaces, ctelevelsup); 7218 foreach(lc, ctedpns->ctes) 7219 { 7220 cte = (CommonTableExpr *) lfirst(lc); 7221 if (strcmp(cte->ctename, rte->ctename) == 0) 7222 break; 7223 } 7224 } 7225 if (lc != NULL) 7226 { 7227 Query *ctequery = (Query *) cte->ctequery; 7228 TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte), 7229 attnum); 7230 7231 if (ste == NULL || ste->resjunk) 7232 elog(ERROR, "subquery %s does not have attribute %d", 7233 rte->eref->aliasname, attnum); 7234 expr = (Node *) ste->expr; 7235 if (IsA(expr, Var)) 7236 { 7237 /* 7238 * Recurse into the CTE to see what its Var refers to. 7239 * We have to build an additional level of namespace 7240 * to keep in step with varlevelsup in the CTE. 7241 * Furthermore it could be an outer CTE, so we may 7242 * have to delete some levels of namespace. 7243 */ 7244 List *save_nslist = context->namespaces; 7245 List *new_nslist; 7246 deparse_namespace mydpns; 7247 const char *result; 7248 7249 set_deparse_for_query(&mydpns, ctequery, 7250 context->namespaces); 7251 7252 new_nslist = list_copy_tail(context->namespaces, 7253 ctelevelsup); 7254 context->namespaces = lcons(&mydpns, new_nslist); 7255 7256 result = get_name_for_var_field((Var *) expr, fieldno, 7257 0, context); 7258 7259 context->namespaces = save_nslist; 7260 7261 return result; 7262 } 7263 /* else fall through to inspect the expression */ 7264 } 7265 else 7266 { 7267 /* 7268 * We're deparsing a Plan tree so we don't have a CTE 7269 * list. But the only place we'd see a Var directly 7270 * referencing a CTE RTE is in a CteScan plan node, and we 7271 * can look into the subplan's tlist instead. 7272 */ 7273 TargetEntry *tle; 7274 deparse_namespace save_dpns; 7275 const char *result; 7276 7277 if (!dpns->inner_planstate) 7278 elog(ERROR, "failed to find plan for CTE %s", 7279 rte->eref->aliasname); 7280 tle = get_tle_by_resno(dpns->inner_tlist, attnum); 7281 if (!tle) 7282 elog(ERROR, "bogus varattno for subquery var: %d", 7283 attnum); 7284 Assert(netlevelsup == 0); 7285 push_child_plan(dpns, dpns->inner_planstate, &save_dpns); 7286 7287 result = get_name_for_var_field((Var *) tle->expr, fieldno, 7288 levelsup, context); 7289 7290 pop_child_plan(dpns, &save_dpns); 7291 return result; 7292 } 7293 } 7294 break; 7295 } 7296 7297 /* 7298 * We now have an expression we can't expand any more, so see if 7299 * get_expr_result_tupdesc() can do anything with it. 7300 */ 7301 tupleDesc = get_expr_result_tupdesc(expr, false); 7302 /* Got the tupdesc, so we can extract the field name */ 7303 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); 7304 return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname); 7305 } 7306 7307 /* 7308 * Try to find the referenced expression for a PARAM_EXEC Param that might 7309 * reference a parameter supplied by an upper NestLoop or SubPlan plan node. 7310 * 7311 * If successful, return the expression and set *dpns_p and *ancestor_cell_p 7312 * appropriately for calling push_ancestor_plan(). If no referent can be 7313 * found, return NULL. 7314 */ 7315 static Node * 7316 find_param_referent(Param *param, deparse_context *context, 7317 deparse_namespace **dpns_p, ListCell **ancestor_cell_p) 7318 { 7319 /* Initialize output parameters to prevent compiler warnings */ 7320 *dpns_p = NULL; 7321 *ancestor_cell_p = NULL; 7322 7323 /* 7324 * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or 7325 * SubPlan argument. This will necessarily be in some ancestor of the 7326 * current expression's PlanState. 7327 */ 7328 if (param->paramkind == PARAM_EXEC) 7329 { 7330 deparse_namespace *dpns; 7331 PlanState *child_ps; 7332 bool in_same_plan_level; 7333 ListCell *lc; 7334 7335 dpns = (deparse_namespace *) linitial(context->namespaces); 7336 child_ps = dpns->planstate; 7337 in_same_plan_level = true; 7338 7339 foreach(lc, dpns->ancestors) 7340 { 7341 PlanState *ps = (PlanState *) lfirst(lc); 7342 ListCell *lc2; 7343 7344 /* 7345 * NestLoops transmit params to their inner child only; also, once 7346 * we've crawled up out of a subplan, this couldn't possibly be 7347 * the right match. 7348 */ 7349 if (IsA(ps, NestLoopState) && 7350 child_ps == innerPlanState(ps) && 7351 in_same_plan_level) 7352 { 7353 NestLoop *nl = (NestLoop *) ps->plan; 7354 7355 foreach(lc2, nl->nestParams) 7356 { 7357 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2); 7358 7359 if (nlp->paramno == param->paramid) 7360 { 7361 /* Found a match, so return it */ 7362 *dpns_p = dpns; 7363 *ancestor_cell_p = lc; 7364 return (Node *) nlp->paramval; 7365 } 7366 } 7367 } 7368 7369 /* 7370 * Check to see if we're crawling up from a subplan. 7371 */ 7372 foreach(lc2, ps->subPlan) 7373 { 7374 SubPlanState *sstate = (SubPlanState *) lfirst(lc2); 7375 SubPlan *subplan = sstate->subplan; 7376 ListCell *lc3; 7377 ListCell *lc4; 7378 7379 if (child_ps != sstate->planstate) 7380 continue; 7381 7382 /* Matched subplan, so check its arguments */ 7383 forboth(lc3, subplan->parParam, lc4, subplan->args) 7384 { 7385 int paramid = lfirst_int(lc3); 7386 Node *arg = (Node *) lfirst(lc4); 7387 7388 if (paramid == param->paramid) 7389 { 7390 /* Found a match, so return it */ 7391 *dpns_p = dpns; 7392 *ancestor_cell_p = lc; 7393 return arg; 7394 } 7395 } 7396 7397 /* Keep looking, but we are emerging from a subplan. */ 7398 in_same_plan_level = false; 7399 break; 7400 } 7401 7402 /* 7403 * Likewise check to see if we're emerging from an initplan. 7404 * Initplans never have any parParams, so no need to search that 7405 * list, but we need to know if we should reset 7406 * in_same_plan_level. 7407 */ 7408 foreach(lc2, ps->initPlan) 7409 { 7410 SubPlanState *sstate = (SubPlanState *) lfirst(lc2); 7411 7412 if (child_ps != sstate->planstate) 7413 continue; 7414 7415 /* No parameters to be had here. */ 7416 Assert(sstate->subplan->parParam == NIL); 7417 7418 /* Keep looking, but we are emerging from an initplan. */ 7419 in_same_plan_level = false; 7420 break; 7421 } 7422 7423 /* No luck, crawl up to next ancestor */ 7424 child_ps = ps; 7425 } 7426 } 7427 7428 /* No referent found */ 7429 return NULL; 7430 } 7431 7432 /* 7433 * Display a Param appropriately. 7434 */ 7435 static void 7436 get_parameter(Param *param, deparse_context *context) 7437 { 7438 Node *expr; 7439 deparse_namespace *dpns; 7440 ListCell *ancestor_cell; 7441 7442 /* 7443 * If it's a PARAM_EXEC parameter, try to locate the expression from which 7444 * the parameter was computed. Note that failing to find a referent isn't 7445 * an error, since the Param might well be a subplan output rather than an 7446 * input. 7447 */ 7448 expr = find_param_referent(param, context, &dpns, &ancestor_cell); 7449 if (expr) 7450 { 7451 /* Found a match, so print it */ 7452 deparse_namespace save_dpns; 7453 bool save_varprefix; 7454 bool need_paren; 7455 7456 /* Switch attention to the ancestor plan node */ 7457 push_ancestor_plan(dpns, ancestor_cell, &save_dpns); 7458 7459 /* 7460 * Force prefixing of Vars, since they won't belong to the relation 7461 * being scanned in the original plan node. 7462 */ 7463 save_varprefix = context->varprefix; 7464 context->varprefix = true; 7465 7466 /* 7467 * A Param's expansion is typically a Var, Aggref, or upper-level 7468 * Param, which wouldn't need extra parentheses. Otherwise, insert 7469 * parens to ensure the expression looks atomic. 7470 */ 7471 need_paren = !(IsA(expr, Var) || 7472 IsA(expr, Aggref) || 7473 IsA(expr, Param)); 7474 if (need_paren) 7475 appendStringInfoChar(context->buf, '('); 7476 7477 get_rule_expr(expr, context, false); 7478 7479 if (need_paren) 7480 appendStringInfoChar(context->buf, ')'); 7481 7482 context->varprefix = save_varprefix; 7483 7484 pop_ancestor_plan(dpns, &save_dpns); 7485 7486 return; 7487 } 7488 7489 /* 7490 * Not PARAM_EXEC, or couldn't find referent: just print $N. 7491 */ 7492 appendStringInfo(context->buf, "$%d", param->paramid); 7493 } 7494 7495 /* 7496 * get_simple_binary_op_name 7497 * 7498 * helper function for isSimpleNode 7499 * will return single char binary operator name, or NULL if it's not 7500 */ 7501 static const char * 7502 get_simple_binary_op_name(OpExpr *expr) 7503 { 7504 List *args = expr->args; 7505 7506 if (list_length(args) == 2) 7507 { 7508 /* binary operator */ 7509 Node *arg1 = (Node *) linitial(args); 7510 Node *arg2 = (Node *) lsecond(args); 7511 const char *op; 7512 7513 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2)); 7514 if (strlen(op) == 1) 7515 return op; 7516 } 7517 return NULL; 7518 } 7519 7520 7521 /* 7522 * isSimpleNode - check if given node is simple (doesn't need parenthesizing) 7523 * 7524 * true : simple in the context of parent node's type 7525 * false : not simple 7526 */ 7527 static bool 7528 isSimpleNode(Node *node, Node *parentNode, int prettyFlags) 7529 { 7530 if (!node) 7531 return false; 7532 7533 switch (nodeTag(node)) 7534 { 7535 case T_Var: 7536 case T_Const: 7537 case T_Param: 7538 case T_CoerceToDomainValue: 7539 case T_SetToDefault: 7540 case T_CurrentOfExpr: 7541 /* single words: always simple */ 7542 return true; 7543 7544 case T_SubscriptingRef: 7545 case T_ArrayExpr: 7546 case T_RowExpr: 7547 case T_CoalesceExpr: 7548 case T_MinMaxExpr: 7549 case T_SQLValueFunction: 7550 case T_XmlExpr: 7551 case T_NextValueExpr: 7552 case T_NullIfExpr: 7553 case T_Aggref: 7554 case T_WindowFunc: 7555 case T_FuncExpr: 7556 /* function-like: name(..) or name[..] */ 7557 return true; 7558 7559 /* CASE keywords act as parentheses */ 7560 case T_CaseExpr: 7561 return true; 7562 7563 case T_FieldSelect: 7564 7565 /* 7566 * appears simple since . has top precedence, unless parent is 7567 * T_FieldSelect itself! 7568 */ 7569 return (IsA(parentNode, FieldSelect) ? false : true); 7570 7571 case T_FieldStore: 7572 7573 /* 7574 * treat like FieldSelect (probably doesn't matter) 7575 */ 7576 return (IsA(parentNode, FieldStore) ? false : true); 7577 7578 case T_CoerceToDomain: 7579 /* maybe simple, check args */ 7580 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg, 7581 node, prettyFlags); 7582 case T_RelabelType: 7583 return isSimpleNode((Node *) ((RelabelType *) node)->arg, 7584 node, prettyFlags); 7585 case T_CoerceViaIO: 7586 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg, 7587 node, prettyFlags); 7588 case T_ArrayCoerceExpr: 7589 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg, 7590 node, prettyFlags); 7591 case T_ConvertRowtypeExpr: 7592 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg, 7593 node, prettyFlags); 7594 7595 case T_OpExpr: 7596 { 7597 /* depends on parent node type; needs further checking */ 7598 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr)) 7599 { 7600 const char *op; 7601 const char *parentOp; 7602 bool is_lopriop; 7603 bool is_hipriop; 7604 bool is_lopriparent; 7605 bool is_hipriparent; 7606 7607 op = get_simple_binary_op_name((OpExpr *) node); 7608 if (!op) 7609 return false; 7610 7611 /* We know only the basic operators + - and * / % */ 7612 is_lopriop = (strchr("+-", *op) != NULL); 7613 is_hipriop = (strchr("*/%", *op) != NULL); 7614 if (!(is_lopriop || is_hipriop)) 7615 return false; 7616 7617 parentOp = get_simple_binary_op_name((OpExpr *) parentNode); 7618 if (!parentOp) 7619 return false; 7620 7621 is_lopriparent = (strchr("+-", *parentOp) != NULL); 7622 is_hipriparent = (strchr("*/%", *parentOp) != NULL); 7623 if (!(is_lopriparent || is_hipriparent)) 7624 return false; 7625 7626 if (is_hipriop && is_lopriparent) 7627 return true; /* op binds tighter than parent */ 7628 7629 if (is_lopriop && is_hipriparent) 7630 return false; 7631 7632 /* 7633 * Operators are same priority --- can skip parens only if 7634 * we have (a - b) - c, not a - (b - c). 7635 */ 7636 if (node == (Node *) linitial(((OpExpr *) parentNode)->args)) 7637 return true; 7638 7639 return false; 7640 } 7641 /* else do the same stuff as for T_SubLink et al. */ 7642 } 7643 /* FALLTHROUGH */ 7644 7645 case T_SubLink: 7646 case T_NullTest: 7647 case T_BooleanTest: 7648 case T_DistinctExpr: 7649 switch (nodeTag(parentNode)) 7650 { 7651 case T_FuncExpr: 7652 { 7653 /* special handling for casts */ 7654 CoercionForm type = ((FuncExpr *) parentNode)->funcformat; 7655 7656 if (type == COERCE_EXPLICIT_CAST || 7657 type == COERCE_IMPLICIT_CAST) 7658 return false; 7659 return true; /* own parentheses */ 7660 } 7661 case T_BoolExpr: /* lower precedence */ 7662 case T_SubscriptingRef: /* other separators */ 7663 case T_ArrayExpr: /* other separators */ 7664 case T_RowExpr: /* other separators */ 7665 case T_CoalesceExpr: /* own parentheses */ 7666 case T_MinMaxExpr: /* own parentheses */ 7667 case T_XmlExpr: /* own parentheses */ 7668 case T_NullIfExpr: /* other separators */ 7669 case T_Aggref: /* own parentheses */ 7670 case T_WindowFunc: /* own parentheses */ 7671 case T_CaseExpr: /* other separators */ 7672 return true; 7673 default: 7674 return false; 7675 } 7676 7677 case T_BoolExpr: 7678 switch (nodeTag(parentNode)) 7679 { 7680 case T_BoolExpr: 7681 if (prettyFlags & PRETTYFLAG_PAREN) 7682 { 7683 BoolExprType type; 7684 BoolExprType parentType; 7685 7686 type = ((BoolExpr *) node)->boolop; 7687 parentType = ((BoolExpr *) parentNode)->boolop; 7688 switch (type) 7689 { 7690 case NOT_EXPR: 7691 case AND_EXPR: 7692 if (parentType == AND_EXPR || parentType == OR_EXPR) 7693 return true; 7694 break; 7695 case OR_EXPR: 7696 if (parentType == OR_EXPR) 7697 return true; 7698 break; 7699 } 7700 } 7701 return false; 7702 case T_FuncExpr: 7703 { 7704 /* special handling for casts */ 7705 CoercionForm type = ((FuncExpr *) parentNode)->funcformat; 7706 7707 if (type == COERCE_EXPLICIT_CAST || 7708 type == COERCE_IMPLICIT_CAST) 7709 return false; 7710 return true; /* own parentheses */ 7711 } 7712 case T_SubscriptingRef: /* other separators */ 7713 case T_ArrayExpr: /* other separators */ 7714 case T_RowExpr: /* other separators */ 7715 case T_CoalesceExpr: /* own parentheses */ 7716 case T_MinMaxExpr: /* own parentheses */ 7717 case T_XmlExpr: /* own parentheses */ 7718 case T_NullIfExpr: /* other separators */ 7719 case T_Aggref: /* own parentheses */ 7720 case T_WindowFunc: /* own parentheses */ 7721 case T_CaseExpr: /* other separators */ 7722 return true; 7723 default: 7724 return false; 7725 } 7726 7727 default: 7728 break; 7729 } 7730 /* those we don't know: in dubio complexo */ 7731 return false; 7732 } 7733 7734 7735 /* 7736 * appendContextKeyword - append a keyword to buffer 7737 * 7738 * If prettyPrint is enabled, perform a line break, and adjust indentation. 7739 * Otherwise, just append the keyword. 7740 */ 7741 static void 7742 appendContextKeyword(deparse_context *context, const char *str, 7743 int indentBefore, int indentAfter, int indentPlus) 7744 { 7745 StringInfo buf = context->buf; 7746 7747 if (PRETTY_INDENT(context)) 7748 { 7749 int indentAmount; 7750 7751 context->indentLevel += indentBefore; 7752 7753 /* remove any trailing spaces currently in the buffer ... */ 7754 removeStringInfoSpaces(buf); 7755 /* ... then add a newline and some spaces */ 7756 appendStringInfoChar(buf, '\n'); 7757 7758 if (context->indentLevel < PRETTYINDENT_LIMIT) 7759 indentAmount = Max(context->indentLevel, 0) + indentPlus; 7760 else 7761 { 7762 /* 7763 * If we're indented more than PRETTYINDENT_LIMIT characters, try 7764 * to conserve horizontal space by reducing the per-level 7765 * indentation. For best results the scale factor here should 7766 * divide all the indent amounts that get added to indentLevel 7767 * (PRETTYINDENT_STD, etc). It's important that the indentation 7768 * not grow unboundedly, else deeply-nested trees use O(N^2) 7769 * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT. 7770 */ 7771 indentAmount = PRETTYINDENT_LIMIT + 7772 (context->indentLevel - PRETTYINDENT_LIMIT) / 7773 (PRETTYINDENT_STD / 2); 7774 indentAmount %= PRETTYINDENT_LIMIT; 7775 /* scale/wrap logic affects indentLevel, but not indentPlus */ 7776 indentAmount += indentPlus; 7777 } 7778 appendStringInfoSpaces(buf, indentAmount); 7779 7780 appendStringInfoString(buf, str); 7781 7782 context->indentLevel += indentAfter; 7783 if (context->indentLevel < 0) 7784 context->indentLevel = 0; 7785 } 7786 else 7787 appendStringInfoString(buf, str); 7788 } 7789 7790 /* 7791 * removeStringInfoSpaces - delete trailing spaces from a buffer. 7792 * 7793 * Possibly this should move to stringinfo.c at some point. 7794 */ 7795 static void 7796 removeStringInfoSpaces(StringInfo str) 7797 { 7798 while (str->len > 0 && str->data[str->len - 1] == ' ') 7799 str->data[--(str->len)] = '\0'; 7800 } 7801 7802 7803 /* 7804 * get_rule_expr_paren - deparse expr using get_rule_expr, 7805 * embracing the string with parentheses if necessary for prettyPrint. 7806 * 7807 * Never embrace if prettyFlags=0, because it's done in the calling node. 7808 * 7809 * Any node that does *not* embrace its argument node by sql syntax (with 7810 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should 7811 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be 7812 * added. 7813 */ 7814 static void 7815 get_rule_expr_paren(Node *node, deparse_context *context, 7816 bool showimplicit, Node *parentNode) 7817 { 7818 bool need_paren; 7819 7820 need_paren = PRETTY_PAREN(context) && 7821 !isSimpleNode(node, parentNode, context->prettyFlags); 7822 7823 if (need_paren) 7824 appendStringInfoChar(context->buf, '('); 7825 7826 get_rule_expr(node, context, showimplicit); 7827 7828 if (need_paren) 7829 appendStringInfoChar(context->buf, ')'); 7830 } 7831 7832 7833 /* ---------- 7834 * get_rule_expr - Parse back an expression 7835 * 7836 * Note: showimplicit determines whether we display any implicit cast that 7837 * is present at the top of the expression tree. It is a passed argument, 7838 * not a field of the context struct, because we change the value as we 7839 * recurse down into the expression. In general we suppress implicit casts 7840 * when the result type is known with certainty (eg, the arguments of an 7841 * OR must be boolean). We display implicit casts for arguments of functions 7842 * and operators, since this is needed to be certain that the same function 7843 * or operator will be chosen when the expression is re-parsed. 7844 * ---------- 7845 */ 7846 static void 7847 get_rule_expr(Node *node, deparse_context *context, 7848 bool showimplicit) 7849 { 7850 StringInfo buf = context->buf; 7851 7852 if (node == NULL) 7853 return; 7854 7855 /* Guard against excessively long or deeply-nested queries */ 7856 CHECK_FOR_INTERRUPTS(); 7857 check_stack_depth(); 7858 7859 /* 7860 * Each level of get_rule_expr must emit an indivisible term 7861 * (parenthesized if necessary) to ensure result is reparsed into the same 7862 * expression tree. The only exception is that when the input is a List, 7863 * we emit the component items comma-separated with no surrounding 7864 * decoration; this is convenient for most callers. 7865 */ 7866 switch (nodeTag(node)) 7867 { 7868 case T_Var: 7869 (void) get_variable((Var *) node, 0, false, context); 7870 break; 7871 7872 case T_Const: 7873 get_const_expr((Const *) node, context, 0); 7874 break; 7875 7876 case T_Param: 7877 get_parameter((Param *) node, context); 7878 break; 7879 7880 case T_Aggref: 7881 get_agg_expr((Aggref *) node, context, (Aggref *) node); 7882 break; 7883 7884 case T_GroupingFunc: 7885 { 7886 GroupingFunc *gexpr = (GroupingFunc *) node; 7887 7888 appendStringInfoString(buf, "GROUPING("); 7889 get_rule_expr((Node *) gexpr->args, context, true); 7890 appendStringInfoChar(buf, ')'); 7891 } 7892 break; 7893 7894 case T_WindowFunc: 7895 get_windowfunc_expr((WindowFunc *) node, context); 7896 break; 7897 7898 case T_SubscriptingRef: 7899 { 7900 SubscriptingRef *sbsref = (SubscriptingRef *) node; 7901 bool need_parens; 7902 7903 /* 7904 * If the argument is a CaseTestExpr, we must be inside a 7905 * FieldStore, ie, we are assigning to an element of an array 7906 * within a composite column. Since we already punted on 7907 * displaying the FieldStore's target information, just punt 7908 * here too, and display only the assignment source 7909 * expression. 7910 */ 7911 if (IsA(sbsref->refexpr, CaseTestExpr)) 7912 { 7913 Assert(sbsref->refassgnexpr); 7914 get_rule_expr((Node *) sbsref->refassgnexpr, 7915 context, showimplicit); 7916 break; 7917 } 7918 7919 /* 7920 * Parenthesize the argument unless it's a simple Var or a 7921 * FieldSelect. (In particular, if it's another 7922 * SubscriptingRef, we *must* parenthesize to avoid 7923 * confusion.) 7924 */ 7925 need_parens = !IsA(sbsref->refexpr, Var) && 7926 !IsA(sbsref->refexpr, FieldSelect); 7927 if (need_parens) 7928 appendStringInfoChar(buf, '('); 7929 get_rule_expr((Node *) sbsref->refexpr, context, showimplicit); 7930 if (need_parens) 7931 appendStringInfoChar(buf, ')'); 7932 7933 /* 7934 * If there's a refassgnexpr, we want to print the node in the 7935 * format "container[subscripts] := refassgnexpr". This is 7936 * not legal SQL, so decompilation of INSERT or UPDATE 7937 * statements should always use processIndirection as part of 7938 * the statement-level syntax. We should only see this when 7939 * EXPLAIN tries to print the targetlist of a plan resulting 7940 * from such a statement. 7941 */ 7942 if (sbsref->refassgnexpr) 7943 { 7944 Node *refassgnexpr; 7945 7946 /* 7947 * Use processIndirection to print this node's subscripts 7948 * as well as any additional field selections or 7949 * subscripting in immediate descendants. It returns the 7950 * RHS expr that is actually being "assigned". 7951 */ 7952 refassgnexpr = processIndirection(node, context); 7953 appendStringInfoString(buf, " := "); 7954 get_rule_expr(refassgnexpr, context, showimplicit); 7955 } 7956 else 7957 { 7958 /* Just an ordinary container fetch, so print subscripts */ 7959 printSubscripts(sbsref, context); 7960 } 7961 } 7962 break; 7963 7964 case T_FuncExpr: 7965 get_func_expr((FuncExpr *) node, context, showimplicit); 7966 break; 7967 7968 case T_NamedArgExpr: 7969 { 7970 NamedArgExpr *na = (NamedArgExpr *) node; 7971 7972 appendStringInfo(buf, "%s => ", quote_identifier(na->name)); 7973 get_rule_expr((Node *) na->arg, context, showimplicit); 7974 } 7975 break; 7976 7977 case T_OpExpr: 7978 get_oper_expr((OpExpr *) node, context); 7979 break; 7980 7981 case T_DistinctExpr: 7982 { 7983 DistinctExpr *expr = (DistinctExpr *) node; 7984 List *args = expr->args; 7985 Node *arg1 = (Node *) linitial(args); 7986 Node *arg2 = (Node *) lsecond(args); 7987 7988 if (!PRETTY_PAREN(context)) 7989 appendStringInfoChar(buf, '('); 7990 get_rule_expr_paren(arg1, context, true, node); 7991 appendStringInfoString(buf, " IS DISTINCT FROM "); 7992 get_rule_expr_paren(arg2, context, true, node); 7993 if (!PRETTY_PAREN(context)) 7994 appendStringInfoChar(buf, ')'); 7995 } 7996 break; 7997 7998 case T_NullIfExpr: 7999 { 8000 NullIfExpr *nullifexpr = (NullIfExpr *) node; 8001 8002 appendStringInfoString(buf, "NULLIF("); 8003 get_rule_expr((Node *) nullifexpr->args, context, true); 8004 appendStringInfoChar(buf, ')'); 8005 } 8006 break; 8007 8008 case T_ScalarArrayOpExpr: 8009 { 8010 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; 8011 List *args = expr->args; 8012 Node *arg1 = (Node *) linitial(args); 8013 Node *arg2 = (Node *) lsecond(args); 8014 8015 if (!PRETTY_PAREN(context)) 8016 appendStringInfoChar(buf, '('); 8017 get_rule_expr_paren(arg1, context, true, node); 8018 appendStringInfo(buf, " %s %s (", 8019 generate_operator_name(expr->opno, 8020 exprType(arg1), 8021 get_base_element_type(exprType(arg2))), 8022 expr->useOr ? "ANY" : "ALL"); 8023 get_rule_expr_paren(arg2, context, true, node); 8024 8025 /* 8026 * There's inherent ambiguity in "x op ANY/ALL (y)" when y is 8027 * a bare sub-SELECT. Since we're here, the sub-SELECT must 8028 * be meant as a scalar sub-SELECT yielding an array value to 8029 * be used in ScalarArrayOpExpr; but the grammar will 8030 * preferentially interpret such a construct as an ANY/ALL 8031 * SubLink. To prevent misparsing the output that way, insert 8032 * a dummy coercion (which will be stripped by parse analysis, 8033 * so no inefficiency is added in dump and reload). This is 8034 * indeed most likely what the user wrote to get the construct 8035 * accepted in the first place. 8036 */ 8037 if (IsA(arg2, SubLink) && 8038 ((SubLink *) arg2)->subLinkType == EXPR_SUBLINK) 8039 appendStringInfo(buf, "::%s", 8040 format_type_with_typemod(exprType(arg2), 8041 exprTypmod(arg2))); 8042 appendStringInfoChar(buf, ')'); 8043 if (!PRETTY_PAREN(context)) 8044 appendStringInfoChar(buf, ')'); 8045 } 8046 break; 8047 8048 case T_BoolExpr: 8049 { 8050 BoolExpr *expr = (BoolExpr *) node; 8051 Node *first_arg = linitial(expr->args); 8052 ListCell *arg = lnext(list_head(expr->args)); 8053 8054 switch (expr->boolop) 8055 { 8056 case AND_EXPR: 8057 if (!PRETTY_PAREN(context)) 8058 appendStringInfoChar(buf, '('); 8059 get_rule_expr_paren(first_arg, context, 8060 false, node); 8061 while (arg) 8062 { 8063 appendStringInfoString(buf, " AND "); 8064 get_rule_expr_paren((Node *) lfirst(arg), context, 8065 false, node); 8066 arg = lnext(arg); 8067 } 8068 if (!PRETTY_PAREN(context)) 8069 appendStringInfoChar(buf, ')'); 8070 break; 8071 8072 case OR_EXPR: 8073 if (!PRETTY_PAREN(context)) 8074 appendStringInfoChar(buf, '('); 8075 get_rule_expr_paren(first_arg, context, 8076 false, node); 8077 while (arg) 8078 { 8079 appendStringInfoString(buf, " OR "); 8080 get_rule_expr_paren((Node *) lfirst(arg), context, 8081 false, node); 8082 arg = lnext(arg); 8083 } 8084 if (!PRETTY_PAREN(context)) 8085 appendStringInfoChar(buf, ')'); 8086 break; 8087 8088 case NOT_EXPR: 8089 if (!PRETTY_PAREN(context)) 8090 appendStringInfoChar(buf, '('); 8091 appendStringInfoString(buf, "NOT "); 8092 get_rule_expr_paren(first_arg, context, 8093 false, node); 8094 if (!PRETTY_PAREN(context)) 8095 appendStringInfoChar(buf, ')'); 8096 break; 8097 8098 default: 8099 elog(ERROR, "unrecognized boolop: %d", 8100 (int) expr->boolop); 8101 } 8102 } 8103 break; 8104 8105 case T_SubLink: 8106 get_sublink_expr((SubLink *) node, context); 8107 break; 8108 8109 case T_SubPlan: 8110 { 8111 SubPlan *subplan = (SubPlan *) node; 8112 8113 /* 8114 * We cannot see an already-planned subplan in rule deparsing, 8115 * only while EXPLAINing a query plan. We don't try to 8116 * reconstruct the original SQL, just reference the subplan 8117 * that appears elsewhere in EXPLAIN's result. 8118 */ 8119 if (subplan->useHashTable) 8120 appendStringInfo(buf, "(hashed %s)", subplan->plan_name); 8121 else 8122 appendStringInfo(buf, "(%s)", subplan->plan_name); 8123 } 8124 break; 8125 8126 case T_AlternativeSubPlan: 8127 { 8128 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; 8129 ListCell *lc; 8130 8131 /* As above, this can only happen during EXPLAIN */ 8132 appendStringInfoString(buf, "(alternatives: "); 8133 foreach(lc, asplan->subplans) 8134 { 8135 SubPlan *splan = lfirst_node(SubPlan, lc); 8136 8137 if (splan->useHashTable) 8138 appendStringInfo(buf, "hashed %s", splan->plan_name); 8139 else 8140 appendStringInfoString(buf, splan->plan_name); 8141 if (lnext(lc)) 8142 appendStringInfoString(buf, " or "); 8143 } 8144 appendStringInfoChar(buf, ')'); 8145 } 8146 break; 8147 8148 case T_FieldSelect: 8149 { 8150 FieldSelect *fselect = (FieldSelect *) node; 8151 Node *arg = (Node *) fselect->arg; 8152 int fno = fselect->fieldnum; 8153 const char *fieldname; 8154 bool need_parens; 8155 8156 /* 8157 * Parenthesize the argument unless it's an SubscriptingRef or 8158 * another FieldSelect. Note in particular that it would be 8159 * WRONG to not parenthesize a Var argument; simplicity is not 8160 * the issue here, having the right number of names is. 8161 */ 8162 need_parens = !IsA(arg, SubscriptingRef) && 8163 !IsA(arg, FieldSelect); 8164 if (need_parens) 8165 appendStringInfoChar(buf, '('); 8166 get_rule_expr(arg, context, true); 8167 if (need_parens) 8168 appendStringInfoChar(buf, ')'); 8169 8170 /* 8171 * Get and print the field name. 8172 */ 8173 fieldname = get_name_for_var_field((Var *) arg, fno, 8174 0, context); 8175 appendStringInfo(buf, ".%s", quote_identifier(fieldname)); 8176 } 8177 break; 8178 8179 case T_FieldStore: 8180 { 8181 FieldStore *fstore = (FieldStore *) node; 8182 bool need_parens; 8183 8184 /* 8185 * There is no good way to represent a FieldStore as real SQL, 8186 * so decompilation of INSERT or UPDATE statements should 8187 * always use processIndirection as part of the 8188 * statement-level syntax. We should only get here when 8189 * EXPLAIN tries to print the targetlist of a plan resulting 8190 * from such a statement. The plan case is even harder than 8191 * ordinary rules would be, because the planner tries to 8192 * collapse multiple assignments to the same field or subfield 8193 * into one FieldStore; so we can see a list of target fields 8194 * not just one, and the arguments could be FieldStores 8195 * themselves. We don't bother to try to print the target 8196 * field names; we just print the source arguments, with a 8197 * ROW() around them if there's more than one. This isn't 8198 * terribly complete, but it's probably good enough for 8199 * EXPLAIN's purposes; especially since anything more would be 8200 * either hopelessly confusing or an even poorer 8201 * representation of what the plan is actually doing. 8202 */ 8203 need_parens = (list_length(fstore->newvals) != 1); 8204 if (need_parens) 8205 appendStringInfoString(buf, "ROW("); 8206 get_rule_expr((Node *) fstore->newvals, context, showimplicit); 8207 if (need_parens) 8208 appendStringInfoChar(buf, ')'); 8209 } 8210 break; 8211 8212 case T_RelabelType: 8213 { 8214 RelabelType *relabel = (RelabelType *) node; 8215 Node *arg = (Node *) relabel->arg; 8216 8217 if (relabel->relabelformat == COERCE_IMPLICIT_CAST && 8218 !showimplicit) 8219 { 8220 /* don't show the implicit cast */ 8221 get_rule_expr_paren(arg, context, false, node); 8222 } 8223 else 8224 { 8225 get_coercion_expr(arg, context, 8226 relabel->resulttype, 8227 relabel->resulttypmod, 8228 node); 8229 } 8230 } 8231 break; 8232 8233 case T_CoerceViaIO: 8234 { 8235 CoerceViaIO *iocoerce = (CoerceViaIO *) node; 8236 Node *arg = (Node *) iocoerce->arg; 8237 8238 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST && 8239 !showimplicit) 8240 { 8241 /* don't show the implicit cast */ 8242 get_rule_expr_paren(arg, context, false, node); 8243 } 8244 else 8245 { 8246 get_coercion_expr(arg, context, 8247 iocoerce->resulttype, 8248 -1, 8249 node); 8250 } 8251 } 8252 break; 8253 8254 case T_ArrayCoerceExpr: 8255 { 8256 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; 8257 Node *arg = (Node *) acoerce->arg; 8258 8259 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST && 8260 !showimplicit) 8261 { 8262 /* don't show the implicit cast */ 8263 get_rule_expr_paren(arg, context, false, node); 8264 } 8265 else 8266 { 8267 get_coercion_expr(arg, context, 8268 acoerce->resulttype, 8269 acoerce->resulttypmod, 8270 node); 8271 } 8272 } 8273 break; 8274 8275 case T_ConvertRowtypeExpr: 8276 { 8277 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; 8278 Node *arg = (Node *) convert->arg; 8279 8280 if (convert->convertformat == COERCE_IMPLICIT_CAST && 8281 !showimplicit) 8282 { 8283 /* don't show the implicit cast */ 8284 get_rule_expr_paren(arg, context, false, node); 8285 } 8286 else 8287 { 8288 get_coercion_expr(arg, context, 8289 convert->resulttype, -1, 8290 node); 8291 } 8292 } 8293 break; 8294 8295 case T_CollateExpr: 8296 { 8297 CollateExpr *collate = (CollateExpr *) node; 8298 Node *arg = (Node *) collate->arg; 8299 8300 if (!PRETTY_PAREN(context)) 8301 appendStringInfoChar(buf, '('); 8302 get_rule_expr_paren(arg, context, showimplicit, node); 8303 appendStringInfo(buf, " COLLATE %s", 8304 generate_collation_name(collate->collOid)); 8305 if (!PRETTY_PAREN(context)) 8306 appendStringInfoChar(buf, ')'); 8307 } 8308 break; 8309 8310 case T_CaseExpr: 8311 { 8312 CaseExpr *caseexpr = (CaseExpr *) node; 8313 ListCell *temp; 8314 8315 appendContextKeyword(context, "CASE", 8316 0, PRETTYINDENT_VAR, 0); 8317 if (caseexpr->arg) 8318 { 8319 appendStringInfoChar(buf, ' '); 8320 get_rule_expr((Node *) caseexpr->arg, context, true); 8321 } 8322 foreach(temp, caseexpr->args) 8323 { 8324 CaseWhen *when = (CaseWhen *) lfirst(temp); 8325 Node *w = (Node *) when->expr; 8326 8327 if (caseexpr->arg) 8328 { 8329 /* 8330 * The parser should have produced WHEN clauses of the 8331 * form "CaseTestExpr = RHS", possibly with an 8332 * implicit coercion inserted above the CaseTestExpr. 8333 * For accurate decompilation of rules it's essential 8334 * that we show just the RHS. However in an 8335 * expression that's been through the optimizer, the 8336 * WHEN clause could be almost anything (since the 8337 * equality operator could have been expanded into an 8338 * inline function). If we don't recognize the form 8339 * of the WHEN clause, just punt and display it as-is. 8340 */ 8341 if (IsA(w, OpExpr)) 8342 { 8343 List *args = ((OpExpr *) w)->args; 8344 8345 if (list_length(args) == 2 && 8346 IsA(strip_implicit_coercions(linitial(args)), 8347 CaseTestExpr)) 8348 w = (Node *) lsecond(args); 8349 } 8350 } 8351 8352 if (!PRETTY_INDENT(context)) 8353 appendStringInfoChar(buf, ' '); 8354 appendContextKeyword(context, "WHEN ", 8355 0, 0, 0); 8356 get_rule_expr(w, context, false); 8357 appendStringInfoString(buf, " THEN "); 8358 get_rule_expr((Node *) when->result, context, true); 8359 } 8360 if (!PRETTY_INDENT(context)) 8361 appendStringInfoChar(buf, ' '); 8362 appendContextKeyword(context, "ELSE ", 8363 0, 0, 0); 8364 get_rule_expr((Node *) caseexpr->defresult, context, true); 8365 if (!PRETTY_INDENT(context)) 8366 appendStringInfoChar(buf, ' '); 8367 appendContextKeyword(context, "END", 8368 -PRETTYINDENT_VAR, 0, 0); 8369 } 8370 break; 8371 8372 case T_CaseTestExpr: 8373 { 8374 /* 8375 * Normally we should never get here, since for expressions 8376 * that can contain this node type we attempt to avoid 8377 * recursing to it. But in an optimized expression we might 8378 * be unable to avoid that (see comments for CaseExpr). If we 8379 * do see one, print it as CASE_TEST_EXPR. 8380 */ 8381 appendStringInfoString(buf, "CASE_TEST_EXPR"); 8382 } 8383 break; 8384 8385 case T_ArrayExpr: 8386 { 8387 ArrayExpr *arrayexpr = (ArrayExpr *) node; 8388 8389 appendStringInfoString(buf, "ARRAY["); 8390 get_rule_expr((Node *) arrayexpr->elements, context, true); 8391 appendStringInfoChar(buf, ']'); 8392 8393 /* 8394 * If the array isn't empty, we assume its elements are 8395 * coerced to the desired type. If it's empty, though, we 8396 * need an explicit coercion to the array type. 8397 */ 8398 if (arrayexpr->elements == NIL) 8399 appendStringInfo(buf, "::%s", 8400 format_type_with_typemod(arrayexpr->array_typeid, -1)); 8401 } 8402 break; 8403 8404 case T_RowExpr: 8405 { 8406 RowExpr *rowexpr = (RowExpr *) node; 8407 TupleDesc tupdesc = NULL; 8408 ListCell *arg; 8409 int i; 8410 char *sep; 8411 8412 /* 8413 * If it's a named type and not RECORD, we may have to skip 8414 * dropped columns and/or claim there are NULLs for added 8415 * columns. 8416 */ 8417 if (rowexpr->row_typeid != RECORDOID) 8418 { 8419 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1); 8420 Assert(list_length(rowexpr->args) <= tupdesc->natts); 8421 } 8422 8423 /* 8424 * SQL99 allows "ROW" to be omitted when there is more than 8425 * one column, but for simplicity we always print it. 8426 */ 8427 appendStringInfoString(buf, "ROW("); 8428 sep = ""; 8429 i = 0; 8430 foreach(arg, rowexpr->args) 8431 { 8432 Node *e = (Node *) lfirst(arg); 8433 8434 if (tupdesc == NULL || 8435 !TupleDescAttr(tupdesc, i)->attisdropped) 8436 { 8437 appendStringInfoString(buf, sep); 8438 /* Whole-row Vars need special treatment here */ 8439 get_rule_expr_toplevel(e, context, true); 8440 sep = ", "; 8441 } 8442 i++; 8443 } 8444 if (tupdesc != NULL) 8445 { 8446 while (i < tupdesc->natts) 8447 { 8448 if (!TupleDescAttr(tupdesc, i)->attisdropped) 8449 { 8450 appendStringInfoString(buf, sep); 8451 appendStringInfoString(buf, "NULL"); 8452 sep = ", "; 8453 } 8454 i++; 8455 } 8456 8457 ReleaseTupleDesc(tupdesc); 8458 } 8459 appendStringInfoChar(buf, ')'); 8460 if (rowexpr->row_format == COERCE_EXPLICIT_CAST) 8461 appendStringInfo(buf, "::%s", 8462 format_type_with_typemod(rowexpr->row_typeid, -1)); 8463 } 8464 break; 8465 8466 case T_RowCompareExpr: 8467 { 8468 RowCompareExpr *rcexpr = (RowCompareExpr *) node; 8469 ListCell *arg; 8470 char *sep; 8471 8472 /* 8473 * SQL99 allows "ROW" to be omitted when there is more than 8474 * one column, but for simplicity we always print it. 8475 */ 8476 appendStringInfoString(buf, "(ROW("); 8477 sep = ""; 8478 foreach(arg, rcexpr->largs) 8479 { 8480 Node *e = (Node *) lfirst(arg); 8481 8482 appendStringInfoString(buf, sep); 8483 get_rule_expr(e, context, true); 8484 sep = ", "; 8485 } 8486 8487 /* 8488 * We assume that the name of the first-column operator will 8489 * do for all the rest too. This is definitely open to 8490 * failure, eg if some but not all operators were renamed 8491 * since the construct was parsed, but there seems no way to 8492 * be perfect. 8493 */ 8494 appendStringInfo(buf, ") %s ROW(", 8495 generate_operator_name(linitial_oid(rcexpr->opnos), 8496 exprType(linitial(rcexpr->largs)), 8497 exprType(linitial(rcexpr->rargs)))); 8498 sep = ""; 8499 foreach(arg, rcexpr->rargs) 8500 { 8501 Node *e = (Node *) lfirst(arg); 8502 8503 appendStringInfoString(buf, sep); 8504 get_rule_expr(e, context, true); 8505 sep = ", "; 8506 } 8507 appendStringInfoString(buf, "))"); 8508 } 8509 break; 8510 8511 case T_CoalesceExpr: 8512 { 8513 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; 8514 8515 appendStringInfoString(buf, "COALESCE("); 8516 get_rule_expr((Node *) coalesceexpr->args, context, true); 8517 appendStringInfoChar(buf, ')'); 8518 } 8519 break; 8520 8521 case T_MinMaxExpr: 8522 { 8523 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; 8524 8525 switch (minmaxexpr->op) 8526 { 8527 case IS_GREATEST: 8528 appendStringInfoString(buf, "GREATEST("); 8529 break; 8530 case IS_LEAST: 8531 appendStringInfoString(buf, "LEAST("); 8532 break; 8533 } 8534 get_rule_expr((Node *) minmaxexpr->args, context, true); 8535 appendStringInfoChar(buf, ')'); 8536 } 8537 break; 8538 8539 case T_SQLValueFunction: 8540 { 8541 SQLValueFunction *svf = (SQLValueFunction *) node; 8542 8543 /* 8544 * Note: this code knows that typmod for time, timestamp, and 8545 * timestamptz just prints as integer. 8546 */ 8547 switch (svf->op) 8548 { 8549 case SVFOP_CURRENT_DATE: 8550 appendStringInfoString(buf, "CURRENT_DATE"); 8551 break; 8552 case SVFOP_CURRENT_TIME: 8553 appendStringInfoString(buf, "CURRENT_TIME"); 8554 break; 8555 case SVFOP_CURRENT_TIME_N: 8556 appendStringInfo(buf, "CURRENT_TIME(%d)", svf->typmod); 8557 break; 8558 case SVFOP_CURRENT_TIMESTAMP: 8559 appendStringInfoString(buf, "CURRENT_TIMESTAMP"); 8560 break; 8561 case SVFOP_CURRENT_TIMESTAMP_N: 8562 appendStringInfo(buf, "CURRENT_TIMESTAMP(%d)", 8563 svf->typmod); 8564 break; 8565 case SVFOP_LOCALTIME: 8566 appendStringInfoString(buf, "LOCALTIME"); 8567 break; 8568 case SVFOP_LOCALTIME_N: 8569 appendStringInfo(buf, "LOCALTIME(%d)", svf->typmod); 8570 break; 8571 case SVFOP_LOCALTIMESTAMP: 8572 appendStringInfoString(buf, "LOCALTIMESTAMP"); 8573 break; 8574 case SVFOP_LOCALTIMESTAMP_N: 8575 appendStringInfo(buf, "LOCALTIMESTAMP(%d)", 8576 svf->typmod); 8577 break; 8578 case SVFOP_CURRENT_ROLE: 8579 appendStringInfoString(buf, "CURRENT_ROLE"); 8580 break; 8581 case SVFOP_CURRENT_USER: 8582 appendStringInfoString(buf, "CURRENT_USER"); 8583 break; 8584 case SVFOP_USER: 8585 appendStringInfoString(buf, "USER"); 8586 break; 8587 case SVFOP_SESSION_USER: 8588 appendStringInfoString(buf, "SESSION_USER"); 8589 break; 8590 case SVFOP_CURRENT_CATALOG: 8591 appendStringInfoString(buf, "CURRENT_CATALOG"); 8592 break; 8593 case SVFOP_CURRENT_SCHEMA: 8594 appendStringInfoString(buf, "CURRENT_SCHEMA"); 8595 break; 8596 } 8597 } 8598 break; 8599 8600 case T_XmlExpr: 8601 { 8602 XmlExpr *xexpr = (XmlExpr *) node; 8603 bool needcomma = false; 8604 ListCell *arg; 8605 ListCell *narg; 8606 Const *con; 8607 8608 switch (xexpr->op) 8609 { 8610 case IS_XMLCONCAT: 8611 appendStringInfoString(buf, "XMLCONCAT("); 8612 break; 8613 case IS_XMLELEMENT: 8614 appendStringInfoString(buf, "XMLELEMENT("); 8615 break; 8616 case IS_XMLFOREST: 8617 appendStringInfoString(buf, "XMLFOREST("); 8618 break; 8619 case IS_XMLPARSE: 8620 appendStringInfoString(buf, "XMLPARSE("); 8621 break; 8622 case IS_XMLPI: 8623 appendStringInfoString(buf, "XMLPI("); 8624 break; 8625 case IS_XMLROOT: 8626 appendStringInfoString(buf, "XMLROOT("); 8627 break; 8628 case IS_XMLSERIALIZE: 8629 appendStringInfoString(buf, "XMLSERIALIZE("); 8630 break; 8631 case IS_DOCUMENT: 8632 break; 8633 } 8634 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE) 8635 { 8636 if (xexpr->xmloption == XMLOPTION_DOCUMENT) 8637 appendStringInfoString(buf, "DOCUMENT "); 8638 else 8639 appendStringInfoString(buf, "CONTENT "); 8640 } 8641 if (xexpr->name) 8642 { 8643 appendStringInfo(buf, "NAME %s", 8644 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name))); 8645 needcomma = true; 8646 } 8647 if (xexpr->named_args) 8648 { 8649 if (xexpr->op != IS_XMLFOREST) 8650 { 8651 if (needcomma) 8652 appendStringInfoString(buf, ", "); 8653 appendStringInfoString(buf, "XMLATTRIBUTES("); 8654 needcomma = false; 8655 } 8656 forboth(arg, xexpr->named_args, narg, xexpr->arg_names) 8657 { 8658 Node *e = (Node *) lfirst(arg); 8659 char *argname = strVal(lfirst(narg)); 8660 8661 if (needcomma) 8662 appendStringInfoString(buf, ", "); 8663 get_rule_expr((Node *) e, context, true); 8664 appendStringInfo(buf, " AS %s", 8665 quote_identifier(map_xml_name_to_sql_identifier(argname))); 8666 needcomma = true; 8667 } 8668 if (xexpr->op != IS_XMLFOREST) 8669 appendStringInfoChar(buf, ')'); 8670 } 8671 if (xexpr->args) 8672 { 8673 if (needcomma) 8674 appendStringInfoString(buf, ", "); 8675 switch (xexpr->op) 8676 { 8677 case IS_XMLCONCAT: 8678 case IS_XMLELEMENT: 8679 case IS_XMLFOREST: 8680 case IS_XMLPI: 8681 case IS_XMLSERIALIZE: 8682 /* no extra decoration needed */ 8683 get_rule_expr((Node *) xexpr->args, context, true); 8684 break; 8685 case IS_XMLPARSE: 8686 Assert(list_length(xexpr->args) == 2); 8687 8688 get_rule_expr((Node *) linitial(xexpr->args), 8689 context, true); 8690 8691 con = lsecond_node(Const, xexpr->args); 8692 Assert(!con->constisnull); 8693 if (DatumGetBool(con->constvalue)) 8694 appendStringInfoString(buf, 8695 " PRESERVE WHITESPACE"); 8696 else 8697 appendStringInfoString(buf, 8698 " STRIP WHITESPACE"); 8699 break; 8700 case IS_XMLROOT: 8701 Assert(list_length(xexpr->args) == 3); 8702 8703 get_rule_expr((Node *) linitial(xexpr->args), 8704 context, true); 8705 8706 appendStringInfoString(buf, ", VERSION "); 8707 con = (Const *) lsecond(xexpr->args); 8708 if (IsA(con, Const) && 8709 con->constisnull) 8710 appendStringInfoString(buf, "NO VALUE"); 8711 else 8712 get_rule_expr((Node *) con, context, false); 8713 8714 con = lthird_node(Const, xexpr->args); 8715 if (con->constisnull) 8716 /* suppress STANDALONE NO VALUE */ ; 8717 else 8718 { 8719 switch (DatumGetInt32(con->constvalue)) 8720 { 8721 case XML_STANDALONE_YES: 8722 appendStringInfoString(buf, 8723 ", STANDALONE YES"); 8724 break; 8725 case XML_STANDALONE_NO: 8726 appendStringInfoString(buf, 8727 ", STANDALONE NO"); 8728 break; 8729 case XML_STANDALONE_NO_VALUE: 8730 appendStringInfoString(buf, 8731 ", STANDALONE NO VALUE"); 8732 break; 8733 default: 8734 break; 8735 } 8736 } 8737 break; 8738 case IS_DOCUMENT: 8739 get_rule_expr_paren((Node *) xexpr->args, context, false, node); 8740 break; 8741 } 8742 8743 } 8744 if (xexpr->op == IS_XMLSERIALIZE) 8745 appendStringInfo(buf, " AS %s", 8746 format_type_with_typemod(xexpr->type, 8747 xexpr->typmod)); 8748 if (xexpr->op == IS_DOCUMENT) 8749 appendStringInfoString(buf, " IS DOCUMENT"); 8750 else 8751 appendStringInfoChar(buf, ')'); 8752 } 8753 break; 8754 8755 case T_NullTest: 8756 { 8757 NullTest *ntest = (NullTest *) node; 8758 8759 if (!PRETTY_PAREN(context)) 8760 appendStringInfoChar(buf, '('); 8761 get_rule_expr_paren((Node *) ntest->arg, context, true, node); 8762 8763 /* 8764 * For scalar inputs, we prefer to print as IS [NOT] NULL, 8765 * which is shorter and traditional. If it's a rowtype input 8766 * but we're applying a scalar test, must print IS [NOT] 8767 * DISTINCT FROM NULL to be semantically correct. 8768 */ 8769 if (ntest->argisrow || 8770 !type_is_rowtype(exprType((Node *) ntest->arg))) 8771 { 8772 switch (ntest->nulltesttype) 8773 { 8774 case IS_NULL: 8775 appendStringInfoString(buf, " IS NULL"); 8776 break; 8777 case IS_NOT_NULL: 8778 appendStringInfoString(buf, " IS NOT NULL"); 8779 break; 8780 default: 8781 elog(ERROR, "unrecognized nulltesttype: %d", 8782 (int) ntest->nulltesttype); 8783 } 8784 } 8785 else 8786 { 8787 switch (ntest->nulltesttype) 8788 { 8789 case IS_NULL: 8790 appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL"); 8791 break; 8792 case IS_NOT_NULL: 8793 appendStringInfoString(buf, " IS DISTINCT FROM NULL"); 8794 break; 8795 default: 8796 elog(ERROR, "unrecognized nulltesttype: %d", 8797 (int) ntest->nulltesttype); 8798 } 8799 } 8800 if (!PRETTY_PAREN(context)) 8801 appendStringInfoChar(buf, ')'); 8802 } 8803 break; 8804 8805 case T_BooleanTest: 8806 { 8807 BooleanTest *btest = (BooleanTest *) node; 8808 8809 if (!PRETTY_PAREN(context)) 8810 appendStringInfoChar(buf, '('); 8811 get_rule_expr_paren((Node *) btest->arg, context, false, node); 8812 switch (btest->booltesttype) 8813 { 8814 case IS_TRUE: 8815 appendStringInfoString(buf, " IS TRUE"); 8816 break; 8817 case IS_NOT_TRUE: 8818 appendStringInfoString(buf, " IS NOT TRUE"); 8819 break; 8820 case IS_FALSE: 8821 appendStringInfoString(buf, " IS FALSE"); 8822 break; 8823 case IS_NOT_FALSE: 8824 appendStringInfoString(buf, " IS NOT FALSE"); 8825 break; 8826 case IS_UNKNOWN: 8827 appendStringInfoString(buf, " IS UNKNOWN"); 8828 break; 8829 case IS_NOT_UNKNOWN: 8830 appendStringInfoString(buf, " IS NOT UNKNOWN"); 8831 break; 8832 default: 8833 elog(ERROR, "unrecognized booltesttype: %d", 8834 (int) btest->booltesttype); 8835 } 8836 if (!PRETTY_PAREN(context)) 8837 appendStringInfoChar(buf, ')'); 8838 } 8839 break; 8840 8841 case T_CoerceToDomain: 8842 { 8843 CoerceToDomain *ctest = (CoerceToDomain *) node; 8844 Node *arg = (Node *) ctest->arg; 8845 8846 if (ctest->coercionformat == COERCE_IMPLICIT_CAST && 8847 !showimplicit) 8848 { 8849 /* don't show the implicit cast */ 8850 get_rule_expr(arg, context, false); 8851 } 8852 else 8853 { 8854 get_coercion_expr(arg, context, 8855 ctest->resulttype, 8856 ctest->resulttypmod, 8857 node); 8858 } 8859 } 8860 break; 8861 8862 case T_CoerceToDomainValue: 8863 appendStringInfoString(buf, "VALUE"); 8864 break; 8865 8866 case T_SetToDefault: 8867 appendStringInfoString(buf, "DEFAULT"); 8868 break; 8869 8870 case T_CurrentOfExpr: 8871 { 8872 CurrentOfExpr *cexpr = (CurrentOfExpr *) node; 8873 8874 if (cexpr->cursor_name) 8875 appendStringInfo(buf, "CURRENT OF %s", 8876 quote_identifier(cexpr->cursor_name)); 8877 else 8878 appendStringInfo(buf, "CURRENT OF $%d", 8879 cexpr->cursor_param); 8880 } 8881 break; 8882 8883 case T_NextValueExpr: 8884 { 8885 NextValueExpr *nvexpr = (NextValueExpr *) node; 8886 8887 /* 8888 * This isn't exactly nextval(), but that seems close enough 8889 * for EXPLAIN's purposes. 8890 */ 8891 appendStringInfoString(buf, "nextval("); 8892 simple_quote_literal(buf, 8893 generate_relation_name(nvexpr->seqid, 8894 NIL)); 8895 appendStringInfoChar(buf, ')'); 8896 } 8897 break; 8898 8899 case T_InferenceElem: 8900 { 8901 InferenceElem *iexpr = (InferenceElem *) node; 8902 bool save_varprefix; 8903 bool need_parens; 8904 8905 /* 8906 * InferenceElem can only refer to target relation, so a 8907 * prefix is not useful, and indeed would cause parse errors. 8908 */ 8909 save_varprefix = context->varprefix; 8910 context->varprefix = false; 8911 8912 /* 8913 * Parenthesize the element unless it's a simple Var or a bare 8914 * function call. Follows pg_get_indexdef_worker(). 8915 */ 8916 need_parens = !IsA(iexpr->expr, Var); 8917 if (IsA(iexpr->expr, FuncExpr) && 8918 ((FuncExpr *) iexpr->expr)->funcformat == 8919 COERCE_EXPLICIT_CALL) 8920 need_parens = false; 8921 8922 if (need_parens) 8923 appendStringInfoChar(buf, '('); 8924 get_rule_expr((Node *) iexpr->expr, 8925 context, false); 8926 if (need_parens) 8927 appendStringInfoChar(buf, ')'); 8928 8929 context->varprefix = save_varprefix; 8930 8931 if (iexpr->infercollid) 8932 appendStringInfo(buf, " COLLATE %s", 8933 generate_collation_name(iexpr->infercollid)); 8934 8935 /* Add the operator class name, if not default */ 8936 if (iexpr->inferopclass) 8937 { 8938 Oid inferopclass = iexpr->inferopclass; 8939 Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass); 8940 8941 get_opclass_name(inferopclass, inferopcinputtype, buf); 8942 } 8943 } 8944 break; 8945 8946 case T_PartitionBoundSpec: 8947 { 8948 PartitionBoundSpec *spec = (PartitionBoundSpec *) node; 8949 ListCell *cell; 8950 char *sep; 8951 8952 if (spec->is_default) 8953 { 8954 appendStringInfoString(buf, "DEFAULT"); 8955 break; 8956 } 8957 8958 switch (spec->strategy) 8959 { 8960 case PARTITION_STRATEGY_HASH: 8961 Assert(spec->modulus > 0 && spec->remainder >= 0); 8962 Assert(spec->modulus > spec->remainder); 8963 8964 appendStringInfoString(buf, "FOR VALUES"); 8965 appendStringInfo(buf, " WITH (modulus %d, remainder %d)", 8966 spec->modulus, spec->remainder); 8967 break; 8968 8969 case PARTITION_STRATEGY_LIST: 8970 Assert(spec->listdatums != NIL); 8971 8972 appendStringInfoString(buf, "FOR VALUES IN ("); 8973 sep = ""; 8974 foreach(cell, spec->listdatums) 8975 { 8976 Const *val = castNode(Const, lfirst(cell)); 8977 8978 appendStringInfoString(buf, sep); 8979 get_const_expr(val, context, -1); 8980 sep = ", "; 8981 } 8982 8983 appendStringInfoChar(buf, ')'); 8984 break; 8985 8986 case PARTITION_STRATEGY_RANGE: 8987 Assert(spec->lowerdatums != NIL && 8988 spec->upperdatums != NIL && 8989 list_length(spec->lowerdatums) == 8990 list_length(spec->upperdatums)); 8991 8992 appendStringInfo(buf, "FOR VALUES FROM %s TO %s", 8993 get_range_partbound_string(spec->lowerdatums), 8994 get_range_partbound_string(spec->upperdatums)); 8995 break; 8996 8997 default: 8998 elog(ERROR, "unrecognized partition strategy: %d", 8999 (int) spec->strategy); 9000 break; 9001 } 9002 } 9003 break; 9004 9005 case T_List: 9006 { 9007 char *sep; 9008 ListCell *l; 9009 9010 sep = ""; 9011 foreach(l, (List *) node) 9012 { 9013 appendStringInfoString(buf, sep); 9014 get_rule_expr((Node *) lfirst(l), context, showimplicit); 9015 sep = ", "; 9016 } 9017 } 9018 break; 9019 9020 case T_TableFunc: 9021 get_tablefunc((TableFunc *) node, context, showimplicit); 9022 break; 9023 9024 default: 9025 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); 9026 break; 9027 } 9028 } 9029 9030 /* 9031 * get_rule_expr_toplevel - Parse back a toplevel expression 9032 * 9033 * Same as get_rule_expr(), except that if the expr is just a Var, we pass 9034 * istoplevel = true not false to get_variable(). This causes whole-row Vars 9035 * to get printed with decoration that will prevent expansion of "*". 9036 * We need to use this in contexts such as ROW() and VALUES(), where the 9037 * parser would expand "foo.*" appearing at top level. (In principle we'd 9038 * use this in get_target_list() too, but that has additional worries about 9039 * whether to print AS, so it needs to invoke get_variable() directly anyway.) 9040 */ 9041 static void 9042 get_rule_expr_toplevel(Node *node, deparse_context *context, 9043 bool showimplicit) 9044 { 9045 if (node && IsA(node, Var)) 9046 (void) get_variable((Var *) node, 0, true, context); 9047 else 9048 get_rule_expr(node, context, showimplicit); 9049 } 9050 9051 /* 9052 * get_rule_expr_funccall - Parse back a function-call expression 9053 * 9054 * Same as get_rule_expr(), except that we guarantee that the output will 9055 * look like a function call, or like one of the things the grammar treats as 9056 * equivalent to a function call (see the func_expr_windowless production). 9057 * This is needed in places where the grammar uses func_expr_windowless and 9058 * you can't substitute a parenthesized a_expr. If what we have isn't going 9059 * to look like a function call, wrap it in a dummy CAST() expression, which 9060 * will satisfy the grammar --- and, indeed, is likely what the user wrote to 9061 * produce such a thing. 9062 */ 9063 static void 9064 get_rule_expr_funccall(Node *node, deparse_context *context, 9065 bool showimplicit) 9066 { 9067 if (looks_like_function(node)) 9068 get_rule_expr(node, context, showimplicit); 9069 else 9070 { 9071 StringInfo buf = context->buf; 9072 9073 appendStringInfoString(buf, "CAST("); 9074 /* no point in showing any top-level implicit cast */ 9075 get_rule_expr(node, context, false); 9076 appendStringInfo(buf, " AS %s)", 9077 format_type_with_typemod(exprType(node), 9078 exprTypmod(node))); 9079 } 9080 } 9081 9082 /* 9083 * Helper function to identify node types that satisfy func_expr_windowless. 9084 * If in doubt, "false" is always a safe answer. 9085 */ 9086 static bool 9087 looks_like_function(Node *node) 9088 { 9089 if (node == NULL) 9090 return false; /* probably shouldn't happen */ 9091 switch (nodeTag(node)) 9092 { 9093 case T_FuncExpr: 9094 /* OK, unless it's going to deparse as a cast */ 9095 return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL); 9096 case T_NullIfExpr: 9097 case T_CoalesceExpr: 9098 case T_MinMaxExpr: 9099 case T_SQLValueFunction: 9100 case T_XmlExpr: 9101 /* these are all accepted by func_expr_common_subexpr */ 9102 return true; 9103 default: 9104 break; 9105 } 9106 return false; 9107 } 9108 9109 9110 /* 9111 * get_oper_expr - Parse back an OpExpr node 9112 */ 9113 static void 9114 get_oper_expr(OpExpr *expr, deparse_context *context) 9115 { 9116 StringInfo buf = context->buf; 9117 Oid opno = expr->opno; 9118 List *args = expr->args; 9119 9120 if (!PRETTY_PAREN(context)) 9121 appendStringInfoChar(buf, '('); 9122 if (list_length(args) == 2) 9123 { 9124 /* binary operator */ 9125 Node *arg1 = (Node *) linitial(args); 9126 Node *arg2 = (Node *) lsecond(args); 9127 9128 get_rule_expr_paren(arg1, context, true, (Node *) expr); 9129 appendStringInfo(buf, " %s ", 9130 generate_operator_name(opno, 9131 exprType(arg1), 9132 exprType(arg2))); 9133 get_rule_expr_paren(arg2, context, true, (Node *) expr); 9134 } 9135 else 9136 { 9137 /* unary operator --- but which side? */ 9138 Node *arg = (Node *) linitial(args); 9139 HeapTuple tp; 9140 Form_pg_operator optup; 9141 9142 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno)); 9143 if (!HeapTupleIsValid(tp)) 9144 elog(ERROR, "cache lookup failed for operator %u", opno); 9145 optup = (Form_pg_operator) GETSTRUCT(tp); 9146 switch (optup->oprkind) 9147 { 9148 case 'l': 9149 appendStringInfo(buf, "%s ", 9150 generate_operator_name(opno, 9151 InvalidOid, 9152 exprType(arg))); 9153 get_rule_expr_paren(arg, context, true, (Node *) expr); 9154 break; 9155 case 'r': 9156 get_rule_expr_paren(arg, context, true, (Node *) expr); 9157 appendStringInfo(buf, " %s", 9158 generate_operator_name(opno, 9159 exprType(arg), 9160 InvalidOid)); 9161 break; 9162 default: 9163 elog(ERROR, "bogus oprkind: %d", optup->oprkind); 9164 } 9165 ReleaseSysCache(tp); 9166 } 9167 if (!PRETTY_PAREN(context)) 9168 appendStringInfoChar(buf, ')'); 9169 } 9170 9171 /* 9172 * get_func_expr - Parse back a FuncExpr node 9173 */ 9174 static void 9175 get_func_expr(FuncExpr *expr, deparse_context *context, 9176 bool showimplicit) 9177 { 9178 StringInfo buf = context->buf; 9179 Oid funcoid = expr->funcid; 9180 Oid argtypes[FUNC_MAX_ARGS]; 9181 int nargs; 9182 List *argnames; 9183 bool use_variadic; 9184 ListCell *l; 9185 9186 /* 9187 * If the function call came from an implicit coercion, then just show the 9188 * first argument --- unless caller wants to see implicit coercions. 9189 */ 9190 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit) 9191 { 9192 get_rule_expr_paren((Node *) linitial(expr->args), context, 9193 false, (Node *) expr); 9194 return; 9195 } 9196 9197 /* 9198 * If the function call came from a cast, then show the first argument 9199 * plus an explicit cast operation. 9200 */ 9201 if (expr->funcformat == COERCE_EXPLICIT_CAST || 9202 expr->funcformat == COERCE_IMPLICIT_CAST) 9203 { 9204 Node *arg = linitial(expr->args); 9205 Oid rettype = expr->funcresulttype; 9206 int32 coercedTypmod; 9207 9208 /* Get the typmod if this is a length-coercion function */ 9209 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod); 9210 9211 get_coercion_expr(arg, context, 9212 rettype, coercedTypmod, 9213 (Node *) expr); 9214 9215 return; 9216 } 9217 9218 /* 9219 * Normal function: display as proname(args). First we need to extract 9220 * the argument datatypes. 9221 */ 9222 if (list_length(expr->args) > FUNC_MAX_ARGS) 9223 ereport(ERROR, 9224 (errcode(ERRCODE_TOO_MANY_ARGUMENTS), 9225 errmsg("too many arguments"))); 9226 nargs = 0; 9227 argnames = NIL; 9228 foreach(l, expr->args) 9229 { 9230 Node *arg = (Node *) lfirst(l); 9231 9232 if (IsA(arg, NamedArgExpr)) 9233 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); 9234 argtypes[nargs] = exprType(arg); 9235 nargs++; 9236 } 9237 9238 appendStringInfo(buf, "%s(", 9239 generate_function_name(funcoid, nargs, 9240 argnames, argtypes, 9241 expr->funcvariadic, 9242 &use_variadic, 9243 context->special_exprkind)); 9244 nargs = 0; 9245 foreach(l, expr->args) 9246 { 9247 if (nargs++ > 0) 9248 appendStringInfoString(buf, ", "); 9249 if (use_variadic && lnext(l) == NULL) 9250 appendStringInfoString(buf, "VARIADIC "); 9251 get_rule_expr((Node *) lfirst(l), context, true); 9252 } 9253 appendStringInfoChar(buf, ')'); 9254 } 9255 9256 /* 9257 * get_agg_expr - Parse back an Aggref node 9258 */ 9259 static void 9260 get_agg_expr(Aggref *aggref, deparse_context *context, 9261 Aggref *original_aggref) 9262 { 9263 StringInfo buf = context->buf; 9264 Oid argtypes[FUNC_MAX_ARGS]; 9265 int nargs; 9266 bool use_variadic; 9267 9268 /* 9269 * For a combining aggregate, we look up and deparse the corresponding 9270 * partial aggregate instead. This is necessary because our input 9271 * argument list has been replaced; the new argument list always has just 9272 * one element, which will point to a partial Aggref that supplies us with 9273 * transition states to combine. 9274 */ 9275 if (DO_AGGSPLIT_COMBINE(aggref->aggsplit)) 9276 { 9277 TargetEntry *tle = linitial_node(TargetEntry, aggref->args); 9278 9279 Assert(list_length(aggref->args) == 1); 9280 resolve_special_varno((Node *) tle->expr, context, original_aggref, 9281 get_agg_combine_expr); 9282 return; 9283 } 9284 9285 /* 9286 * Mark as PARTIAL, if appropriate. We look to the original aggref so as 9287 * to avoid printing this when recursing from the code just above. 9288 */ 9289 if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit)) 9290 appendStringInfoString(buf, "PARTIAL "); 9291 9292 /* Extract the argument types as seen by the parser */ 9293 nargs = get_aggregate_argtypes(aggref, argtypes); 9294 9295 /* Print the aggregate name, schema-qualified if needed */ 9296 appendStringInfo(buf, "%s(%s", 9297 generate_function_name(aggref->aggfnoid, nargs, 9298 NIL, argtypes, 9299 aggref->aggvariadic, 9300 &use_variadic, 9301 context->special_exprkind), 9302 (aggref->aggdistinct != NIL) ? "DISTINCT " : ""); 9303 9304 if (AGGKIND_IS_ORDERED_SET(aggref->aggkind)) 9305 { 9306 /* 9307 * Ordered-set aggregates do not use "*" syntax. Also, we needn't 9308 * worry about inserting VARIADIC. So we can just dump the direct 9309 * args as-is. 9310 */ 9311 Assert(!aggref->aggvariadic); 9312 get_rule_expr((Node *) aggref->aggdirectargs, context, true); 9313 Assert(aggref->aggorder != NIL); 9314 appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY "); 9315 get_rule_orderby(aggref->aggorder, aggref->args, false, context); 9316 } 9317 else 9318 { 9319 /* aggstar can be set only in zero-argument aggregates */ 9320 if (aggref->aggstar) 9321 appendStringInfoChar(buf, '*'); 9322 else 9323 { 9324 ListCell *l; 9325 int i; 9326 9327 i = 0; 9328 foreach(l, aggref->args) 9329 { 9330 TargetEntry *tle = (TargetEntry *) lfirst(l); 9331 Node *arg = (Node *) tle->expr; 9332 9333 Assert(!IsA(arg, NamedArgExpr)); 9334 if (tle->resjunk) 9335 continue; 9336 if (i++ > 0) 9337 appendStringInfoString(buf, ", "); 9338 if (use_variadic && i == nargs) 9339 appendStringInfoString(buf, "VARIADIC "); 9340 get_rule_expr(arg, context, true); 9341 } 9342 } 9343 9344 if (aggref->aggorder != NIL) 9345 { 9346 appendStringInfoString(buf, " ORDER BY "); 9347 get_rule_orderby(aggref->aggorder, aggref->args, false, context); 9348 } 9349 } 9350 9351 if (aggref->aggfilter != NULL) 9352 { 9353 appendStringInfoString(buf, ") FILTER (WHERE "); 9354 get_rule_expr((Node *) aggref->aggfilter, context, false); 9355 } 9356 9357 appendStringInfoChar(buf, ')'); 9358 } 9359 9360 /* 9361 * This is a helper function for get_agg_expr(). It's used when we deparse 9362 * a combining Aggref; resolve_special_varno locates the corresponding partial 9363 * Aggref and then calls this. 9364 */ 9365 static void 9366 get_agg_combine_expr(Node *node, deparse_context *context, void *private) 9367 { 9368 Aggref *aggref; 9369 Aggref *original_aggref = private; 9370 9371 if (!IsA(node, Aggref)) 9372 elog(ERROR, "combining Aggref does not point to an Aggref"); 9373 9374 aggref = (Aggref *) node; 9375 get_agg_expr(aggref, context, original_aggref); 9376 } 9377 9378 /* 9379 * get_windowfunc_expr - Parse back a WindowFunc node 9380 */ 9381 static void 9382 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) 9383 { 9384 StringInfo buf = context->buf; 9385 Oid argtypes[FUNC_MAX_ARGS]; 9386 int nargs; 9387 List *argnames; 9388 ListCell *l; 9389 9390 if (list_length(wfunc->args) > FUNC_MAX_ARGS) 9391 ereport(ERROR, 9392 (errcode(ERRCODE_TOO_MANY_ARGUMENTS), 9393 errmsg("too many arguments"))); 9394 nargs = 0; 9395 argnames = NIL; 9396 foreach(l, wfunc->args) 9397 { 9398 Node *arg = (Node *) lfirst(l); 9399 9400 if (IsA(arg, NamedArgExpr)) 9401 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); 9402 argtypes[nargs] = exprType(arg); 9403 nargs++; 9404 } 9405 9406 appendStringInfo(buf, "%s(", 9407 generate_function_name(wfunc->winfnoid, nargs, 9408 argnames, argtypes, 9409 false, NULL, 9410 context->special_exprkind)); 9411 /* winstar can be set only in zero-argument aggregates */ 9412 if (wfunc->winstar) 9413 appendStringInfoChar(buf, '*'); 9414 else 9415 get_rule_expr((Node *) wfunc->args, context, true); 9416 9417 if (wfunc->aggfilter != NULL) 9418 { 9419 appendStringInfoString(buf, ") FILTER (WHERE "); 9420 get_rule_expr((Node *) wfunc->aggfilter, context, false); 9421 } 9422 9423 appendStringInfoString(buf, ") OVER "); 9424 9425 foreach(l, context->windowClause) 9426 { 9427 WindowClause *wc = (WindowClause *) lfirst(l); 9428 9429 if (wc->winref == wfunc->winref) 9430 { 9431 if (wc->name) 9432 appendStringInfoString(buf, quote_identifier(wc->name)); 9433 else 9434 get_rule_windowspec(wc, context->windowTList, context); 9435 break; 9436 } 9437 } 9438 if (l == NULL) 9439 { 9440 if (context->windowClause) 9441 elog(ERROR, "could not find window clause for winref %u", 9442 wfunc->winref); 9443 9444 /* 9445 * In EXPLAIN, we don't have window context information available, so 9446 * we have to settle for this: 9447 */ 9448 appendStringInfoString(buf, "(?)"); 9449 } 9450 } 9451 9452 /* ---------- 9453 * get_coercion_expr 9454 * 9455 * Make a string representation of a value coerced to a specific type 9456 * ---------- 9457 */ 9458 static void 9459 get_coercion_expr(Node *arg, deparse_context *context, 9460 Oid resulttype, int32 resulttypmod, 9461 Node *parentNode) 9462 { 9463 StringInfo buf = context->buf; 9464 9465 /* 9466 * Since parse_coerce.c doesn't immediately collapse application of 9467 * length-coercion functions to constants, what we'll typically see in 9468 * such cases is a Const with typmod -1 and a length-coercion function 9469 * right above it. Avoid generating redundant output. However, beware of 9470 * suppressing casts when the user actually wrote something like 9471 * 'foo'::text::char(3). 9472 * 9473 * Note: it might seem that we are missing the possibility of needing to 9474 * print a COLLATE clause for such a Const. However, a Const could only 9475 * have nondefault collation in a post-constant-folding tree, in which the 9476 * length coercion would have been folded too. See also the special 9477 * handling of CollateExpr in coerce_to_target_type(): any collation 9478 * marking will be above the coercion node, not below it. 9479 */ 9480 if (arg && IsA(arg, Const) && 9481 ((Const *) arg)->consttype == resulttype && 9482 ((Const *) arg)->consttypmod == -1) 9483 { 9484 /* Show the constant without normal ::typename decoration */ 9485 get_const_expr((Const *) arg, context, -1); 9486 } 9487 else 9488 { 9489 if (!PRETTY_PAREN(context)) 9490 appendStringInfoChar(buf, '('); 9491 get_rule_expr_paren(arg, context, false, parentNode); 9492 if (!PRETTY_PAREN(context)) 9493 appendStringInfoChar(buf, ')'); 9494 } 9495 9496 /* 9497 * Never emit resulttype(arg) functional notation. A pg_proc entry could 9498 * take precedence, and a resulttype in pg_temp would require schema 9499 * qualification that format_type_with_typemod() would usually omit. We've 9500 * standardized on arg::resulttype, but CAST(arg AS resulttype) notation 9501 * would work fine. 9502 */ 9503 appendStringInfo(buf, "::%s", 9504 format_type_with_typemod(resulttype, resulttypmod)); 9505 } 9506 9507 /* ---------- 9508 * get_const_expr 9509 * 9510 * Make a string representation of a Const 9511 * 9512 * showtype can be -1 to never show "::typename" decoration, or +1 to always 9513 * show it, or 0 to show it only if the constant wouldn't be assumed to be 9514 * the right type by default. 9515 * 9516 * If the Const's collation isn't default for its type, show that too. 9517 * We mustn't do this when showtype is -1 (since that means the caller will 9518 * print "::typename", and we can't put a COLLATE clause in between). It's 9519 * caller's responsibility that collation isn't missed in such cases. 9520 * ---------- 9521 */ 9522 static void 9523 get_const_expr(Const *constval, deparse_context *context, int showtype) 9524 { 9525 StringInfo buf = context->buf; 9526 Oid typoutput; 9527 bool typIsVarlena; 9528 char *extval; 9529 bool needlabel = false; 9530 9531 if (constval->constisnull) 9532 { 9533 /* 9534 * Always label the type of a NULL constant to prevent misdecisions 9535 * about type when reparsing. 9536 */ 9537 appendStringInfoString(buf, "NULL"); 9538 if (showtype >= 0) 9539 { 9540 appendStringInfo(buf, "::%s", 9541 format_type_with_typemod(constval->consttype, 9542 constval->consttypmod)); 9543 get_const_collation(constval, context); 9544 } 9545 return; 9546 } 9547 9548 getTypeOutputInfo(constval->consttype, 9549 &typoutput, &typIsVarlena); 9550 9551 extval = OidOutputFunctionCall(typoutput, constval->constvalue); 9552 9553 switch (constval->consttype) 9554 { 9555 case INT4OID: 9556 9557 /* 9558 * INT4 can be printed without any decoration, unless it is 9559 * negative; in that case print it as '-nnn'::integer to ensure 9560 * that the output will re-parse as a constant, not as a constant 9561 * plus operator. In most cases we could get away with printing 9562 * (-nnn) instead, because of the way that gram.y handles negative 9563 * literals; but that doesn't work for INT_MIN, and it doesn't 9564 * seem that much prettier anyway. 9565 */ 9566 if (extval[0] != '-') 9567 appendStringInfoString(buf, extval); 9568 else 9569 { 9570 appendStringInfo(buf, "'%s'", extval); 9571 needlabel = true; /* we must attach a cast */ 9572 } 9573 break; 9574 9575 case NUMERICOID: 9576 9577 /* 9578 * NUMERIC can be printed without quotes if it looks like a float 9579 * constant (not an integer, and not Infinity or NaN) and doesn't 9580 * have a leading sign (for the same reason as for INT4). 9581 */ 9582 if (isdigit((unsigned char) extval[0]) && 9583 strcspn(extval, "eE.") != strlen(extval)) 9584 { 9585 appendStringInfoString(buf, extval); 9586 } 9587 else 9588 { 9589 appendStringInfo(buf, "'%s'", extval); 9590 needlabel = true; /* we must attach a cast */ 9591 } 9592 break; 9593 9594 case BOOLOID: 9595 if (strcmp(extval, "t") == 0) 9596 appendStringInfoString(buf, "true"); 9597 else 9598 appendStringInfoString(buf, "false"); 9599 break; 9600 9601 default: 9602 simple_quote_literal(buf, extval); 9603 break; 9604 } 9605 9606 pfree(extval); 9607 9608 if (showtype < 0) 9609 return; 9610 9611 /* 9612 * For showtype == 0, append ::typename unless the constant will be 9613 * implicitly typed as the right type when it is read in. 9614 * 9615 * XXX this code has to be kept in sync with the behavior of the parser, 9616 * especially make_const. 9617 */ 9618 switch (constval->consttype) 9619 { 9620 case BOOLOID: 9621 case UNKNOWNOID: 9622 /* These types can be left unlabeled */ 9623 needlabel = false; 9624 break; 9625 case INT4OID: 9626 /* We determined above whether a label is needed */ 9627 break; 9628 case NUMERICOID: 9629 9630 /* 9631 * Float-looking constants will be typed as numeric, which we 9632 * checked above; but if there's a nondefault typmod we need to 9633 * show it. 9634 */ 9635 needlabel |= (constval->consttypmod >= 0); 9636 break; 9637 default: 9638 needlabel = true; 9639 break; 9640 } 9641 if (needlabel || showtype > 0) 9642 appendStringInfo(buf, "::%s", 9643 format_type_with_typemod(constval->consttype, 9644 constval->consttypmod)); 9645 9646 get_const_collation(constval, context); 9647 } 9648 9649 /* 9650 * helper for get_const_expr: append COLLATE if needed 9651 */ 9652 static void 9653 get_const_collation(Const *constval, deparse_context *context) 9654 { 9655 StringInfo buf = context->buf; 9656 9657 if (OidIsValid(constval->constcollid)) 9658 { 9659 Oid typcollation = get_typcollation(constval->consttype); 9660 9661 if (constval->constcollid != typcollation) 9662 { 9663 appendStringInfo(buf, " COLLATE %s", 9664 generate_collation_name(constval->constcollid)); 9665 } 9666 } 9667 } 9668 9669 /* 9670 * simple_quote_literal - Format a string as a SQL literal, append to buf 9671 */ 9672 static void 9673 simple_quote_literal(StringInfo buf, const char *val) 9674 { 9675 const char *valptr; 9676 9677 /* 9678 * We form the string literal according to the prevailing setting of 9679 * standard_conforming_strings; we never use E''. User is responsible for 9680 * making sure result is used correctly. 9681 */ 9682 appendStringInfoChar(buf, '\''); 9683 for (valptr = val; *valptr; valptr++) 9684 { 9685 char ch = *valptr; 9686 9687 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings)) 9688 appendStringInfoChar(buf, ch); 9689 appendStringInfoChar(buf, ch); 9690 } 9691 appendStringInfoChar(buf, '\''); 9692 } 9693 9694 9695 /* ---------- 9696 * get_sublink_expr - Parse back a sublink 9697 * ---------- 9698 */ 9699 static void 9700 get_sublink_expr(SubLink *sublink, deparse_context *context) 9701 { 9702 StringInfo buf = context->buf; 9703 Query *query = (Query *) (sublink->subselect); 9704 char *opname = NULL; 9705 bool need_paren; 9706 9707 if (sublink->subLinkType == ARRAY_SUBLINK) 9708 appendStringInfoString(buf, "ARRAY("); 9709 else 9710 appendStringInfoChar(buf, '('); 9711 9712 /* 9713 * Note that we print the name of only the first operator, when there are 9714 * multiple combining operators. This is an approximation that could go 9715 * wrong in various scenarios (operators in different schemas, renamed 9716 * operators, etc) but there is not a whole lot we can do about it, since 9717 * the syntax allows only one operator to be shown. 9718 */ 9719 if (sublink->testexpr) 9720 { 9721 if (IsA(sublink->testexpr, OpExpr)) 9722 { 9723 /* single combining operator */ 9724 OpExpr *opexpr = (OpExpr *) sublink->testexpr; 9725 9726 get_rule_expr(linitial(opexpr->args), context, true); 9727 opname = generate_operator_name(opexpr->opno, 9728 exprType(linitial(opexpr->args)), 9729 exprType(lsecond(opexpr->args))); 9730 } 9731 else if (IsA(sublink->testexpr, BoolExpr)) 9732 { 9733 /* multiple combining operators, = or <> cases */ 9734 char *sep; 9735 ListCell *l; 9736 9737 appendStringInfoChar(buf, '('); 9738 sep = ""; 9739 foreach(l, ((BoolExpr *) sublink->testexpr)->args) 9740 { 9741 OpExpr *opexpr = lfirst_node(OpExpr, l); 9742 9743 appendStringInfoString(buf, sep); 9744 get_rule_expr(linitial(opexpr->args), context, true); 9745 if (!opname) 9746 opname = generate_operator_name(opexpr->opno, 9747 exprType(linitial(opexpr->args)), 9748 exprType(lsecond(opexpr->args))); 9749 sep = ", "; 9750 } 9751 appendStringInfoChar(buf, ')'); 9752 } 9753 else if (IsA(sublink->testexpr, RowCompareExpr)) 9754 { 9755 /* multiple combining operators, < <= > >= cases */ 9756 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr; 9757 9758 appendStringInfoChar(buf, '('); 9759 get_rule_expr((Node *) rcexpr->largs, context, true); 9760 opname = generate_operator_name(linitial_oid(rcexpr->opnos), 9761 exprType(linitial(rcexpr->largs)), 9762 exprType(linitial(rcexpr->rargs))); 9763 appendStringInfoChar(buf, ')'); 9764 } 9765 else 9766 elog(ERROR, "unrecognized testexpr type: %d", 9767 (int) nodeTag(sublink->testexpr)); 9768 } 9769 9770 need_paren = true; 9771 9772 switch (sublink->subLinkType) 9773 { 9774 case EXISTS_SUBLINK: 9775 appendStringInfoString(buf, "EXISTS "); 9776 break; 9777 9778 case ANY_SUBLINK: 9779 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */ 9780 appendStringInfoString(buf, " IN "); 9781 else 9782 appendStringInfo(buf, " %s ANY ", opname); 9783 break; 9784 9785 case ALL_SUBLINK: 9786 appendStringInfo(buf, " %s ALL ", opname); 9787 break; 9788 9789 case ROWCOMPARE_SUBLINK: 9790 appendStringInfo(buf, " %s ", opname); 9791 break; 9792 9793 case EXPR_SUBLINK: 9794 case MULTIEXPR_SUBLINK: 9795 case ARRAY_SUBLINK: 9796 need_paren = false; 9797 break; 9798 9799 case CTE_SUBLINK: /* shouldn't occur in a SubLink */ 9800 default: 9801 elog(ERROR, "unrecognized sublink type: %d", 9802 (int) sublink->subLinkType); 9803 break; 9804 } 9805 9806 if (need_paren) 9807 appendStringInfoChar(buf, '('); 9808 9809 get_query_def(query, buf, context->namespaces, NULL, 9810 context->prettyFlags, context->wrapColumn, 9811 context->indentLevel); 9812 9813 if (need_paren) 9814 appendStringInfoString(buf, "))"); 9815 else 9816 appendStringInfoChar(buf, ')'); 9817 } 9818 9819 9820 /* ---------- 9821 * get_tablefunc - Parse back a table function 9822 * ---------- 9823 */ 9824 static void 9825 get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit) 9826 { 9827 StringInfo buf = context->buf; 9828 9829 /* XMLTABLE is the only existing implementation. */ 9830 9831 appendStringInfoString(buf, "XMLTABLE("); 9832 9833 if (tf->ns_uris != NIL) 9834 { 9835 ListCell *lc1, 9836 *lc2; 9837 bool first = true; 9838 9839 appendStringInfoString(buf, "XMLNAMESPACES ("); 9840 forboth(lc1, tf->ns_uris, lc2, tf->ns_names) 9841 { 9842 Node *expr = (Node *) lfirst(lc1); 9843 Value *ns_node = (Value *) lfirst(lc2); 9844 9845 if (!first) 9846 appendStringInfoString(buf, ", "); 9847 else 9848 first = false; 9849 9850 if (ns_node != NULL) 9851 { 9852 get_rule_expr(expr, context, showimplicit); 9853 appendStringInfo(buf, " AS %s", strVal(ns_node)); 9854 } 9855 else 9856 { 9857 appendStringInfoString(buf, "DEFAULT "); 9858 get_rule_expr(expr, context, showimplicit); 9859 } 9860 } 9861 appendStringInfoString(buf, "), "); 9862 } 9863 9864 appendStringInfoChar(buf, '('); 9865 get_rule_expr((Node *) tf->rowexpr, context, showimplicit); 9866 appendStringInfoString(buf, ") PASSING ("); 9867 get_rule_expr((Node *) tf->docexpr, context, showimplicit); 9868 appendStringInfoChar(buf, ')'); 9869 9870 if (tf->colexprs != NIL) 9871 { 9872 ListCell *l1; 9873 ListCell *l2; 9874 ListCell *l3; 9875 ListCell *l4; 9876 ListCell *l5; 9877 int colnum = 0; 9878 9879 appendStringInfoString(buf, " COLUMNS "); 9880 forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods, 9881 l4, tf->colexprs, l5, tf->coldefexprs) 9882 { 9883 char *colname = strVal(lfirst(l1)); 9884 Oid typid = lfirst_oid(l2); 9885 int32 typmod = lfirst_int(l3); 9886 Node *colexpr = (Node *) lfirst(l4); 9887 Node *coldefexpr = (Node *) lfirst(l5); 9888 bool ordinality = (tf->ordinalitycol == colnum); 9889 bool notnull = bms_is_member(colnum, tf->notnulls); 9890 9891 if (colnum > 0) 9892 appendStringInfoString(buf, ", "); 9893 colnum++; 9894 9895 appendStringInfo(buf, "%s %s", quote_identifier(colname), 9896 ordinality ? "FOR ORDINALITY" : 9897 format_type_with_typemod(typid, typmod)); 9898 if (ordinality) 9899 continue; 9900 9901 if (coldefexpr != NULL) 9902 { 9903 appendStringInfoString(buf, " DEFAULT ("); 9904 get_rule_expr((Node *) coldefexpr, context, showimplicit); 9905 appendStringInfoChar(buf, ')'); 9906 } 9907 if (colexpr != NULL) 9908 { 9909 appendStringInfoString(buf, " PATH ("); 9910 get_rule_expr((Node *) colexpr, context, showimplicit); 9911 appendStringInfoChar(buf, ')'); 9912 } 9913 if (notnull) 9914 appendStringInfoString(buf, " NOT NULL"); 9915 } 9916 } 9917 9918 appendStringInfoChar(buf, ')'); 9919 } 9920 9921 /* ---------- 9922 * get_from_clause - Parse back a FROM clause 9923 * 9924 * "prefix" is the keyword that denotes the start of the list of FROM 9925 * elements. It is FROM when used to parse back SELECT and UPDATE, but 9926 * is USING when parsing back DELETE. 9927 * ---------- 9928 */ 9929 static void 9930 get_from_clause(Query *query, const char *prefix, deparse_context *context) 9931 { 9932 StringInfo buf = context->buf; 9933 bool first = true; 9934 ListCell *l; 9935 9936 /* 9937 * We use the query's jointree as a guide to what to print. However, we 9938 * must ignore auto-added RTEs that are marked not inFromCl. (These can 9939 * only appear at the top level of the jointree, so it's sufficient to 9940 * check here.) This check also ensures we ignore the rule pseudo-RTEs 9941 * for NEW and OLD. 9942 */ 9943 foreach(l, query->jointree->fromlist) 9944 { 9945 Node *jtnode = (Node *) lfirst(l); 9946 9947 if (IsA(jtnode, RangeTblRef)) 9948 { 9949 int varno = ((RangeTblRef *) jtnode)->rtindex; 9950 RangeTblEntry *rte = rt_fetch(varno, query->rtable); 9951 9952 if (!rte->inFromCl) 9953 continue; 9954 } 9955 9956 if (first) 9957 { 9958 appendContextKeyword(context, prefix, 9959 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); 9960 first = false; 9961 9962 get_from_clause_item(jtnode, query, context); 9963 } 9964 else 9965 { 9966 StringInfoData itembuf; 9967 9968 appendStringInfoString(buf, ", "); 9969 9970 /* 9971 * Put the new FROM item's text into itembuf so we can decide 9972 * after we've got it whether or not it needs to go on a new line. 9973 */ 9974 initStringInfo(&itembuf); 9975 context->buf = &itembuf; 9976 9977 get_from_clause_item(jtnode, query, context); 9978 9979 /* Restore context's output buffer */ 9980 context->buf = buf; 9981 9982 /* Consider line-wrapping if enabled */ 9983 if (PRETTY_INDENT(context) && context->wrapColumn >= 0) 9984 { 9985 /* Does the new item start with a new line? */ 9986 if (itembuf.len > 0 && itembuf.data[0] == '\n') 9987 { 9988 /* If so, we shouldn't add anything */ 9989 /* instead, remove any trailing spaces currently in buf */ 9990 removeStringInfoSpaces(buf); 9991 } 9992 else 9993 { 9994 char *trailing_nl; 9995 9996 /* Locate the start of the current line in the buffer */ 9997 trailing_nl = strrchr(buf->data, '\n'); 9998 if (trailing_nl == NULL) 9999 trailing_nl = buf->data; 10000 else 10001 trailing_nl++; 10002 10003 /* 10004 * Add a newline, plus some indentation, if the new item 10005 * would cause an overflow. 10006 */ 10007 if (strlen(trailing_nl) + itembuf.len > context->wrapColumn) 10008 appendContextKeyword(context, "", -PRETTYINDENT_STD, 10009 PRETTYINDENT_STD, 10010 PRETTYINDENT_VAR); 10011 } 10012 } 10013 10014 /* Add the new item */ 10015 appendStringInfoString(buf, itembuf.data); 10016 10017 /* clean up */ 10018 pfree(itembuf.data); 10019 } 10020 } 10021 } 10022 10023 static void 10024 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) 10025 { 10026 StringInfo buf = context->buf; 10027 deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); 10028 10029 if (IsA(jtnode, RangeTblRef)) 10030 { 10031 int varno = ((RangeTblRef *) jtnode)->rtindex; 10032 RangeTblEntry *rte = rt_fetch(varno, query->rtable); 10033 char *refname = get_rtable_name(varno, context); 10034 deparse_columns *colinfo = deparse_columns_fetch(varno, dpns); 10035 RangeTblFunction *rtfunc1 = NULL; 10036 bool printalias; 10037 10038 if (rte->lateral) 10039 appendStringInfoString(buf, "LATERAL "); 10040 10041 /* Print the FROM item proper */ 10042 switch (rte->rtekind) 10043 { 10044 case RTE_RELATION: 10045 /* Normal relation RTE */ 10046 appendStringInfo(buf, "%s%s", 10047 only_marker(rte), 10048 generate_relation_name(rte->relid, 10049 context->namespaces)); 10050 break; 10051 case RTE_SUBQUERY: 10052 /* Subquery RTE */ 10053 appendStringInfoChar(buf, '('); 10054 get_query_def(rte->subquery, buf, context->namespaces, NULL, 10055 context->prettyFlags, context->wrapColumn, 10056 context->indentLevel); 10057 appendStringInfoChar(buf, ')'); 10058 break; 10059 case RTE_FUNCTION: 10060 /* Function RTE */ 10061 rtfunc1 = (RangeTblFunction *) linitial(rte->functions); 10062 10063 /* 10064 * Omit ROWS FROM() syntax for just one function, unless it 10065 * has both a coldeflist and WITH ORDINALITY. If it has both, 10066 * we must use ROWS FROM() syntax to avoid ambiguity about 10067 * whether the coldeflist includes the ordinality column. 10068 */ 10069 if (list_length(rte->functions) == 1 && 10070 (rtfunc1->funccolnames == NIL || !rte->funcordinality)) 10071 { 10072 get_rule_expr_funccall(rtfunc1->funcexpr, context, true); 10073 /* we'll print the coldeflist below, if it has one */ 10074 } 10075 else 10076 { 10077 bool all_unnest; 10078 ListCell *lc; 10079 10080 /* 10081 * If all the function calls in the list are to unnest, 10082 * and none need a coldeflist, then collapse the list back 10083 * down to UNNEST(args). (If we had more than one 10084 * built-in unnest function, this would get more 10085 * difficult.) 10086 * 10087 * XXX This is pretty ugly, since it makes not-terribly- 10088 * future-proof assumptions about what the parser would do 10089 * with the output; but the alternative is to emit our 10090 * nonstandard ROWS FROM() notation for what might have 10091 * been a perfectly spec-compliant multi-argument 10092 * UNNEST(). 10093 */ 10094 all_unnest = true; 10095 foreach(lc, rte->functions) 10096 { 10097 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); 10098 10099 if (!IsA(rtfunc->funcexpr, FuncExpr) || 10100 ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST || 10101 rtfunc->funccolnames != NIL) 10102 { 10103 all_unnest = false; 10104 break; 10105 } 10106 } 10107 10108 if (all_unnest) 10109 { 10110 List *allargs = NIL; 10111 10112 foreach(lc, rte->functions) 10113 { 10114 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); 10115 List *args = ((FuncExpr *) rtfunc->funcexpr)->args; 10116 10117 allargs = list_concat(allargs, list_copy(args)); 10118 } 10119 10120 appendStringInfoString(buf, "UNNEST("); 10121 get_rule_expr((Node *) allargs, context, true); 10122 appendStringInfoChar(buf, ')'); 10123 } 10124 else 10125 { 10126 int funcno = 0; 10127 10128 appendStringInfoString(buf, "ROWS FROM("); 10129 foreach(lc, rte->functions) 10130 { 10131 RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); 10132 10133 if (funcno > 0) 10134 appendStringInfoString(buf, ", "); 10135 get_rule_expr_funccall(rtfunc->funcexpr, context, true); 10136 if (rtfunc->funccolnames != NIL) 10137 { 10138 /* Reconstruct the column definition list */ 10139 appendStringInfoString(buf, " AS "); 10140 get_from_clause_coldeflist(rtfunc, 10141 NULL, 10142 context); 10143 } 10144 funcno++; 10145 } 10146 appendStringInfoChar(buf, ')'); 10147 } 10148 /* prevent printing duplicate coldeflist below */ 10149 rtfunc1 = NULL; 10150 } 10151 if (rte->funcordinality) 10152 appendStringInfoString(buf, " WITH ORDINALITY"); 10153 break; 10154 case RTE_TABLEFUNC: 10155 get_tablefunc(rte->tablefunc, context, true); 10156 break; 10157 case RTE_VALUES: 10158 /* Values list RTE */ 10159 appendStringInfoChar(buf, '('); 10160 get_values_def(rte->values_lists, context); 10161 appendStringInfoChar(buf, ')'); 10162 break; 10163 case RTE_CTE: 10164 appendStringInfoString(buf, quote_identifier(rte->ctename)); 10165 break; 10166 default: 10167 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); 10168 break; 10169 } 10170 10171 /* Print the relation alias, if needed */ 10172 printalias = false; 10173 if (rte->alias != NULL) 10174 { 10175 /* Always print alias if user provided one */ 10176 printalias = true; 10177 } 10178 else if (colinfo->printaliases) 10179 { 10180 /* Always print alias if we need to print column aliases */ 10181 printalias = true; 10182 } 10183 else if (rte->rtekind == RTE_RELATION) 10184 { 10185 /* 10186 * No need to print alias if it's same as relation name (this 10187 * would normally be the case, but not if set_rtable_names had to 10188 * resolve a conflict). 10189 */ 10190 if (strcmp(refname, get_relation_name(rte->relid)) != 0) 10191 printalias = true; 10192 } 10193 else if (rte->rtekind == RTE_FUNCTION) 10194 { 10195 /* 10196 * For a function RTE, always print alias. This covers possible 10197 * renaming of the function and/or instability of the 10198 * FigureColname rules for things that aren't simple functions. 10199 * Note we'd need to force it anyway for the columndef list case. 10200 */ 10201 printalias = true; 10202 } 10203 else if (rte->rtekind == RTE_VALUES) 10204 { 10205 /* Alias is syntactically required for VALUES */ 10206 printalias = true; 10207 } 10208 else if (rte->rtekind == RTE_CTE) 10209 { 10210 /* 10211 * No need to print alias if it's same as CTE name (this would 10212 * normally be the case, but not if set_rtable_names had to 10213 * resolve a conflict). 10214 */ 10215 if (strcmp(refname, rte->ctename) != 0) 10216 printalias = true; 10217 } 10218 if (printalias) 10219 appendStringInfo(buf, " %s", quote_identifier(refname)); 10220 10221 /* Print the column definitions or aliases, if needed */ 10222 if (rtfunc1 && rtfunc1->funccolnames != NIL) 10223 { 10224 /* Reconstruct the columndef list, which is also the aliases */ 10225 get_from_clause_coldeflist(rtfunc1, colinfo, context); 10226 } 10227 else 10228 { 10229 /* Else print column aliases as needed */ 10230 get_column_alias_list(colinfo, context); 10231 } 10232 10233 /* Tablesample clause must go after any alias */ 10234 if (rte->rtekind == RTE_RELATION && rte->tablesample) 10235 get_tablesample_def(rte->tablesample, context); 10236 } 10237 else if (IsA(jtnode, JoinExpr)) 10238 { 10239 JoinExpr *j = (JoinExpr *) jtnode; 10240 deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); 10241 bool need_paren_on_right; 10242 10243 need_paren_on_right = PRETTY_PAREN(context) && 10244 !IsA(j->rarg, RangeTblRef) && 10245 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL); 10246 10247 if (!PRETTY_PAREN(context) || j->alias != NULL) 10248 appendStringInfoChar(buf, '('); 10249 10250 get_from_clause_item(j->larg, query, context); 10251 10252 switch (j->jointype) 10253 { 10254 case JOIN_INNER: 10255 if (j->quals) 10256 appendContextKeyword(context, " JOIN ", 10257 -PRETTYINDENT_STD, 10258 PRETTYINDENT_STD, 10259 PRETTYINDENT_JOIN); 10260 else 10261 appendContextKeyword(context, " CROSS JOIN ", 10262 -PRETTYINDENT_STD, 10263 PRETTYINDENT_STD, 10264 PRETTYINDENT_JOIN); 10265 break; 10266 case JOIN_LEFT: 10267 appendContextKeyword(context, " LEFT JOIN ", 10268 -PRETTYINDENT_STD, 10269 PRETTYINDENT_STD, 10270 PRETTYINDENT_JOIN); 10271 break; 10272 case JOIN_FULL: 10273 appendContextKeyword(context, " FULL JOIN ", 10274 -PRETTYINDENT_STD, 10275 PRETTYINDENT_STD, 10276 PRETTYINDENT_JOIN); 10277 break; 10278 case JOIN_RIGHT: 10279 appendContextKeyword(context, " RIGHT JOIN ", 10280 -PRETTYINDENT_STD, 10281 PRETTYINDENT_STD, 10282 PRETTYINDENT_JOIN); 10283 break; 10284 default: 10285 elog(ERROR, "unrecognized join type: %d", 10286 (int) j->jointype); 10287 } 10288 10289 if (need_paren_on_right) 10290 appendStringInfoChar(buf, '('); 10291 get_from_clause_item(j->rarg, query, context); 10292 if (need_paren_on_right) 10293 appendStringInfoChar(buf, ')'); 10294 10295 if (j->usingClause) 10296 { 10297 ListCell *lc; 10298 bool first = true; 10299 10300 appendStringInfoString(buf, " USING ("); 10301 /* Use the assigned names, not what's in usingClause */ 10302 foreach(lc, colinfo->usingNames) 10303 { 10304 char *colname = (char *) lfirst(lc); 10305 10306 if (first) 10307 first = false; 10308 else 10309 appendStringInfoString(buf, ", "); 10310 appendStringInfoString(buf, quote_identifier(colname)); 10311 } 10312 appendStringInfoChar(buf, ')'); 10313 } 10314 else if (j->quals) 10315 { 10316 appendStringInfoString(buf, " ON "); 10317 if (!PRETTY_PAREN(context)) 10318 appendStringInfoChar(buf, '('); 10319 get_rule_expr(j->quals, context, false); 10320 if (!PRETTY_PAREN(context)) 10321 appendStringInfoChar(buf, ')'); 10322 } 10323 else if (j->jointype != JOIN_INNER) 10324 { 10325 /* If we didn't say CROSS JOIN above, we must provide an ON */ 10326 appendStringInfoString(buf, " ON TRUE"); 10327 } 10328 10329 if (!PRETTY_PAREN(context) || j->alias != NULL) 10330 appendStringInfoChar(buf, ')'); 10331 10332 /* Yes, it's correct to put alias after the right paren ... */ 10333 if (j->alias != NULL) 10334 { 10335 /* 10336 * Note that it's correct to emit an alias clause if and only if 10337 * there was one originally. Otherwise we'd be converting a named 10338 * join to unnamed or vice versa, which creates semantic 10339 * subtleties we don't want. However, we might print a different 10340 * alias name than was there originally. 10341 */ 10342 appendStringInfo(buf, " %s", 10343 quote_identifier(get_rtable_name(j->rtindex, 10344 context))); 10345 get_column_alias_list(colinfo, context); 10346 } 10347 } 10348 else 10349 elog(ERROR, "unrecognized node type: %d", 10350 (int) nodeTag(jtnode)); 10351 } 10352 10353 /* 10354 * get_column_alias_list - print column alias list for an RTE 10355 * 10356 * Caller must already have printed the relation's alias name. 10357 */ 10358 static void 10359 get_column_alias_list(deparse_columns *colinfo, deparse_context *context) 10360 { 10361 StringInfo buf = context->buf; 10362 int i; 10363 bool first = true; 10364 10365 /* Don't print aliases if not needed */ 10366 if (!colinfo->printaliases) 10367 return; 10368 10369 for (i = 0; i < colinfo->num_new_cols; i++) 10370 { 10371 char *colname = colinfo->new_colnames[i]; 10372 10373 if (first) 10374 { 10375 appendStringInfoChar(buf, '('); 10376 first = false; 10377 } 10378 else 10379 appendStringInfoString(buf, ", "); 10380 appendStringInfoString(buf, quote_identifier(colname)); 10381 } 10382 if (!first) 10383 appendStringInfoChar(buf, ')'); 10384 } 10385 10386 /* 10387 * get_from_clause_coldeflist - reproduce FROM clause coldeflist 10388 * 10389 * When printing a top-level coldeflist (which is syntactically also the 10390 * relation's column alias list), use column names from colinfo. But when 10391 * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the 10392 * original coldeflist's names, which are available in rtfunc->funccolnames. 10393 * Pass NULL for colinfo to select the latter behavior. 10394 * 10395 * The coldeflist is appended immediately (no space) to buf. Caller is 10396 * responsible for ensuring that an alias or AS is present before it. 10397 */ 10398 static void 10399 get_from_clause_coldeflist(RangeTblFunction *rtfunc, 10400 deparse_columns *colinfo, 10401 deparse_context *context) 10402 { 10403 StringInfo buf = context->buf; 10404 ListCell *l1; 10405 ListCell *l2; 10406 ListCell *l3; 10407 ListCell *l4; 10408 int i; 10409 10410 appendStringInfoChar(buf, '('); 10411 10412 i = 0; 10413 forfour(l1, rtfunc->funccoltypes, 10414 l2, rtfunc->funccoltypmods, 10415 l3, rtfunc->funccolcollations, 10416 l4, rtfunc->funccolnames) 10417 { 10418 Oid atttypid = lfirst_oid(l1); 10419 int32 atttypmod = lfirst_int(l2); 10420 Oid attcollation = lfirst_oid(l3); 10421 char *attname; 10422 10423 if (colinfo) 10424 attname = colinfo->colnames[i]; 10425 else 10426 attname = strVal(lfirst(l4)); 10427 10428 Assert(attname); /* shouldn't be any dropped columns here */ 10429 10430 if (i > 0) 10431 appendStringInfoString(buf, ", "); 10432 appendStringInfo(buf, "%s %s", 10433 quote_identifier(attname), 10434 format_type_with_typemod(atttypid, atttypmod)); 10435 if (OidIsValid(attcollation) && 10436 attcollation != get_typcollation(atttypid)) 10437 appendStringInfo(buf, " COLLATE %s", 10438 generate_collation_name(attcollation)); 10439 10440 i++; 10441 } 10442 10443 appendStringInfoChar(buf, ')'); 10444 } 10445 10446 /* 10447 * get_tablesample_def - print a TableSampleClause 10448 */ 10449 static void 10450 get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) 10451 { 10452 StringInfo buf = context->buf; 10453 Oid argtypes[1]; 10454 int nargs; 10455 ListCell *l; 10456 10457 /* 10458 * We should qualify the handler's function name if it wouldn't be 10459 * resolved by lookup in the current search path. 10460 */ 10461 argtypes[0] = INTERNALOID; 10462 appendStringInfo(buf, " TABLESAMPLE %s (", 10463 generate_function_name(tablesample->tsmhandler, 1, 10464 NIL, argtypes, 10465 false, NULL, EXPR_KIND_NONE)); 10466 10467 nargs = 0; 10468 foreach(l, tablesample->args) 10469 { 10470 if (nargs++ > 0) 10471 appendStringInfoString(buf, ", "); 10472 get_rule_expr((Node *) lfirst(l), context, false); 10473 } 10474 appendStringInfoChar(buf, ')'); 10475 10476 if (tablesample->repeatable != NULL) 10477 { 10478 appendStringInfoString(buf, " REPEATABLE ("); 10479 get_rule_expr((Node *) tablesample->repeatable, context, false); 10480 appendStringInfoChar(buf, ')'); 10481 } 10482 } 10483 10484 /* 10485 * get_opclass_name - fetch name of an index operator class 10486 * 10487 * The opclass name is appended (after a space) to buf. 10488 * 10489 * Output is suppressed if the opclass is the default for the given 10490 * actual_datatype. (If you don't want this behavior, just pass 10491 * InvalidOid for actual_datatype.) 10492 */ 10493 static void 10494 get_opclass_name(Oid opclass, Oid actual_datatype, 10495 StringInfo buf) 10496 { 10497 HeapTuple ht_opc; 10498 Form_pg_opclass opcrec; 10499 char *opcname; 10500 char *nspname; 10501 10502 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass)); 10503 if (!HeapTupleIsValid(ht_opc)) 10504 elog(ERROR, "cache lookup failed for opclass %u", opclass); 10505 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc); 10506 10507 if (!OidIsValid(actual_datatype) || 10508 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass) 10509 { 10510 /* Okay, we need the opclass name. Do we need to qualify it? */ 10511 opcname = NameStr(opcrec->opcname); 10512 if (OpclassIsVisible(opclass)) 10513 appendStringInfo(buf, " %s", quote_identifier(opcname)); 10514 else 10515 { 10516 nspname = get_namespace_name(opcrec->opcnamespace); 10517 appendStringInfo(buf, " %s.%s", 10518 quote_identifier(nspname), 10519 quote_identifier(opcname)); 10520 } 10521 } 10522 ReleaseSysCache(ht_opc); 10523 } 10524 10525 /* 10526 * processIndirection - take care of array and subfield assignment 10527 * 10528 * We strip any top-level FieldStore or assignment SubscriptingRef nodes that 10529 * appear in the input, printing them as decoration for the base column 10530 * name (which we assume the caller just printed). We might also need to 10531 * strip CoerceToDomain nodes, but only ones that appear above assignment 10532 * nodes. 10533 * 10534 * Returns the subexpression that's to be assigned. 10535 */ 10536 static Node * 10537 processIndirection(Node *node, deparse_context *context) 10538 { 10539 StringInfo buf = context->buf; 10540 CoerceToDomain *cdomain = NULL; 10541 10542 for (;;) 10543 { 10544 if (node == NULL) 10545 break; 10546 if (IsA(node, FieldStore)) 10547 { 10548 FieldStore *fstore = (FieldStore *) node; 10549 Oid typrelid; 10550 char *fieldname; 10551 10552 /* lookup tuple type */ 10553 typrelid = get_typ_typrelid(fstore->resulttype); 10554 if (!OidIsValid(typrelid)) 10555 elog(ERROR, "argument type %s of FieldStore is not a tuple type", 10556 format_type_be(fstore->resulttype)); 10557 10558 /* 10559 * Print the field name. There should only be one target field in 10560 * stored rules. There could be more than that in executable 10561 * target lists, but this function cannot be used for that case. 10562 */ 10563 Assert(list_length(fstore->fieldnums) == 1); 10564 fieldname = get_attname(typrelid, 10565 linitial_int(fstore->fieldnums), false); 10566 appendStringInfo(buf, ".%s", quote_identifier(fieldname)); 10567 10568 /* 10569 * We ignore arg since it should be an uninteresting reference to 10570 * the target column or subcolumn. 10571 */ 10572 node = (Node *) linitial(fstore->newvals); 10573 } 10574 else if (IsA(node, SubscriptingRef)) 10575 { 10576 SubscriptingRef *sbsref = (SubscriptingRef *) node; 10577 10578 if (sbsref->refassgnexpr == NULL) 10579 break; 10580 10581 printSubscripts(sbsref, context); 10582 10583 /* 10584 * We ignore refexpr since it should be an uninteresting reference 10585 * to the target column or subcolumn. 10586 */ 10587 node = (Node *) sbsref->refassgnexpr; 10588 } 10589 else if (IsA(node, CoerceToDomain)) 10590 { 10591 cdomain = (CoerceToDomain *) node; 10592 /* If it's an explicit domain coercion, we're done */ 10593 if (cdomain->coercionformat != COERCE_IMPLICIT_CAST) 10594 break; 10595 /* Tentatively descend past the CoerceToDomain */ 10596 node = (Node *) cdomain->arg; 10597 } 10598 else 10599 break; 10600 } 10601 10602 /* 10603 * If we descended past a CoerceToDomain whose argument turned out not to 10604 * be a FieldStore or array assignment, back up to the CoerceToDomain. 10605 * (This is not enough to be fully correct if there are nested implicit 10606 * CoerceToDomains, but such cases shouldn't ever occur.) 10607 */ 10608 if (cdomain && node == (Node *) cdomain->arg) 10609 node = (Node *) cdomain; 10610 10611 return node; 10612 } 10613 10614 static void 10615 printSubscripts(SubscriptingRef *sbsref, deparse_context *context) 10616 { 10617 StringInfo buf = context->buf; 10618 ListCell *lowlist_item; 10619 ListCell *uplist_item; 10620 10621 lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */ 10622 foreach(uplist_item, sbsref->refupperindexpr) 10623 { 10624 appendStringInfoChar(buf, '['); 10625 if (lowlist_item) 10626 { 10627 /* If subexpression is NULL, get_rule_expr prints nothing */ 10628 get_rule_expr((Node *) lfirst(lowlist_item), context, false); 10629 appendStringInfoChar(buf, ':'); 10630 lowlist_item = lnext(lowlist_item); 10631 } 10632 /* If subexpression is NULL, get_rule_expr prints nothing */ 10633 get_rule_expr((Node *) lfirst(uplist_item), context, false); 10634 appendStringInfoChar(buf, ']'); 10635 } 10636 } 10637 10638 /* 10639 * quote_identifier - Quote an identifier only if needed 10640 * 10641 * When quotes are needed, we palloc the required space; slightly 10642 * space-wasteful but well worth it for notational simplicity. 10643 */ 10644 const char * 10645 quote_identifier(const char *ident) 10646 { 10647 /* 10648 * Can avoid quoting if ident starts with a lowercase letter or underscore 10649 * and contains only lowercase letters, digits, and underscores, *and* is 10650 * not any SQL keyword. Otherwise, supply quotes. 10651 */ 10652 int nquotes = 0; 10653 bool safe; 10654 const char *ptr; 10655 char *result; 10656 char *optr; 10657 10658 /* 10659 * would like to use <ctype.h> macros here, but they might yield unwanted 10660 * locale-specific results... 10661 */ 10662 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'); 10663 10664 for (ptr = ident; *ptr; ptr++) 10665 { 10666 char ch = *ptr; 10667 10668 if ((ch >= 'a' && ch <= 'z') || 10669 (ch >= '0' && ch <= '9') || 10670 (ch == '_')) 10671 { 10672 /* okay */ 10673 } 10674 else 10675 { 10676 safe = false; 10677 if (ch == '"') 10678 nquotes++; 10679 } 10680 } 10681 10682 if (quote_all_identifiers) 10683 safe = false; 10684 10685 if (safe) 10686 { 10687 /* 10688 * Check for keyword. We quote keywords except for unreserved ones. 10689 * (In some cases we could avoid quoting a col_name or type_func_name 10690 * keyword, but it seems much harder than it's worth to tell that.) 10691 * 10692 * Note: ScanKeywordLookup() does case-insensitive comparison, but 10693 * that's fine, since we already know we have all-lower-case. 10694 */ 10695 int kwnum = ScanKeywordLookup(ident, &ScanKeywords); 10696 10697 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD) 10698 safe = false; 10699 } 10700 10701 if (safe) 10702 return ident; /* no change needed */ 10703 10704 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1); 10705 10706 optr = result; 10707 *optr++ = '"'; 10708 for (ptr = ident; *ptr; ptr++) 10709 { 10710 char ch = *ptr; 10711 10712 if (ch == '"') 10713 *optr++ = '"'; 10714 *optr++ = ch; 10715 } 10716 *optr++ = '"'; 10717 *optr = '\0'; 10718 10719 return result; 10720 } 10721 10722 /* 10723 * quote_qualified_identifier - Quote a possibly-qualified identifier 10724 * 10725 * Return a name of the form qualifier.ident, or just ident if qualifier 10726 * is NULL, quoting each component if necessary. The result is palloc'd. 10727 */ 10728 char * 10729 quote_qualified_identifier(const char *qualifier, 10730 const char *ident) 10731 { 10732 StringInfoData buf; 10733 10734 initStringInfo(&buf); 10735 if (qualifier) 10736 appendStringInfo(&buf, "%s.", quote_identifier(qualifier)); 10737 appendStringInfoString(&buf, quote_identifier(ident)); 10738 return buf.data; 10739 } 10740 10741 /* 10742 * get_relation_name 10743 * Get the unqualified name of a relation specified by OID 10744 * 10745 * This differs from the underlying get_rel_name() function in that it will 10746 * throw error instead of silently returning NULL if the OID is bad. 10747 */ 10748 static char * 10749 get_relation_name(Oid relid) 10750 { 10751 char *relname = get_rel_name(relid); 10752 10753 if (!relname) 10754 elog(ERROR, "cache lookup failed for relation %u", relid); 10755 return relname; 10756 } 10757 10758 /* 10759 * generate_relation_name 10760 * Compute the name to display for a relation specified by OID 10761 * 10762 * The result includes all necessary quoting and schema-prefixing. 10763 * 10764 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes. 10765 * We will forcibly qualify the relation name if it equals any CTE name 10766 * visible in the namespace list. 10767 */ 10768 static char * 10769 generate_relation_name(Oid relid, List *namespaces) 10770 { 10771 HeapTuple tp; 10772 Form_pg_class reltup; 10773 bool need_qual; 10774 ListCell *nslist; 10775 char *relname; 10776 char *nspname; 10777 char *result; 10778 10779 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); 10780 if (!HeapTupleIsValid(tp)) 10781 elog(ERROR, "cache lookup failed for relation %u", relid); 10782 reltup = (Form_pg_class) GETSTRUCT(tp); 10783 relname = NameStr(reltup->relname); 10784 10785 /* Check for conflicting CTE name */ 10786 need_qual = false; 10787 foreach(nslist, namespaces) 10788 { 10789 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist); 10790 ListCell *ctlist; 10791 10792 foreach(ctlist, dpns->ctes) 10793 { 10794 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist); 10795 10796 if (strcmp(cte->ctename, relname) == 0) 10797 { 10798 need_qual = true; 10799 break; 10800 } 10801 } 10802 if (need_qual) 10803 break; 10804 } 10805 10806 /* Otherwise, qualify the name if not visible in search path */ 10807 if (!need_qual) 10808 need_qual = !RelationIsVisible(relid); 10809 10810 if (need_qual) 10811 nspname = get_namespace_name(reltup->relnamespace); 10812 else 10813 nspname = NULL; 10814 10815 result = quote_qualified_identifier(nspname, relname); 10816 10817 ReleaseSysCache(tp); 10818 10819 return result; 10820 } 10821 10822 /* 10823 * generate_qualified_relation_name 10824 * Compute the name to display for a relation specified by OID 10825 * 10826 * As above, but unconditionally schema-qualify the name. 10827 */ 10828 static char * 10829 generate_qualified_relation_name(Oid relid) 10830 { 10831 HeapTuple tp; 10832 Form_pg_class reltup; 10833 char *relname; 10834 char *nspname; 10835 char *result; 10836 10837 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); 10838 if (!HeapTupleIsValid(tp)) 10839 elog(ERROR, "cache lookup failed for relation %u", relid); 10840 reltup = (Form_pg_class) GETSTRUCT(tp); 10841 relname = NameStr(reltup->relname); 10842 10843 nspname = get_namespace_name(reltup->relnamespace); 10844 if (!nspname) 10845 elog(ERROR, "cache lookup failed for namespace %u", 10846 reltup->relnamespace); 10847 10848 result = quote_qualified_identifier(nspname, relname); 10849 10850 ReleaseSysCache(tp); 10851 10852 return result; 10853 } 10854 10855 /* 10856 * generate_function_name 10857 * Compute the name to display for a function specified by OID, 10858 * given that it is being called with the specified actual arg names and 10859 * types. (Those matter because of ambiguous-function resolution rules.) 10860 * 10861 * If we're dealing with a potentially variadic function (in practice, this 10862 * means a FuncExpr or Aggref, not some other way of calling a function), then 10863 * has_variadic must specify whether variadic arguments have been merged, 10864 * and *use_variadic_p will be set to indicate whether to print VARIADIC in 10865 * the output. For non-FuncExpr cases, has_variadic should be false and 10866 * use_variadic_p can be NULL. 10867 * 10868 * The result includes all necessary quoting and schema-prefixing. 10869 */ 10870 static char * 10871 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, 10872 bool has_variadic, bool *use_variadic_p, 10873 ParseExprKind special_exprkind) 10874 { 10875 char *result; 10876 HeapTuple proctup; 10877 Form_pg_proc procform; 10878 char *proname; 10879 bool use_variadic; 10880 char *nspname; 10881 FuncDetailCode p_result; 10882 Oid p_funcid; 10883 Oid p_rettype; 10884 bool p_retset; 10885 int p_nvargs; 10886 Oid p_vatype; 10887 Oid *p_true_typeids; 10888 bool force_qualify = false; 10889 10890 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); 10891 if (!HeapTupleIsValid(proctup)) 10892 elog(ERROR, "cache lookup failed for function %u", funcid); 10893 procform = (Form_pg_proc) GETSTRUCT(proctup); 10894 proname = NameStr(procform->proname); 10895 10896 /* 10897 * Due to parser hacks to avoid needing to reserve CUBE, we need to force 10898 * qualification in some special cases. 10899 */ 10900 if (special_exprkind == EXPR_KIND_GROUP_BY) 10901 { 10902 if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0) 10903 force_qualify = true; 10904 } 10905 10906 /* 10907 * Determine whether VARIADIC should be printed. We must do this first 10908 * since it affects the lookup rules in func_get_detail(). 10909 * 10910 * We always print VARIADIC if the function has a merged variadic-array 10911 * argument. Note that this is always the case for functions taking a 10912 * VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC 10913 * and printed the array elements as separate arguments, the call could 10914 * match a newer non-VARIADIC function. 10915 */ 10916 if (use_variadic_p) 10917 { 10918 /* Parser should not have set funcvariadic unless fn is variadic */ 10919 Assert(!has_variadic || OidIsValid(procform->provariadic)); 10920 use_variadic = has_variadic; 10921 *use_variadic_p = use_variadic; 10922 } 10923 else 10924 { 10925 Assert(!has_variadic); 10926 use_variadic = false; 10927 } 10928 10929 /* 10930 * The idea here is to schema-qualify only if the parser would fail to 10931 * resolve the correct function given the unqualified func name with the 10932 * specified argtypes and VARIADIC flag. But if we already decided to 10933 * force qualification, then we can skip the lookup and pretend we didn't 10934 * find it. 10935 */ 10936 if (!force_qualify) 10937 p_result = func_get_detail(list_make1(makeString(proname)), 10938 NIL, argnames, nargs, argtypes, 10939 !use_variadic, true, 10940 &p_funcid, &p_rettype, 10941 &p_retset, &p_nvargs, &p_vatype, 10942 &p_true_typeids, NULL); 10943 else 10944 { 10945 p_result = FUNCDETAIL_NOTFOUND; 10946 p_funcid = InvalidOid; 10947 } 10948 10949 if ((p_result == FUNCDETAIL_NORMAL || 10950 p_result == FUNCDETAIL_AGGREGATE || 10951 p_result == FUNCDETAIL_WINDOWFUNC) && 10952 p_funcid == funcid) 10953 nspname = NULL; 10954 else 10955 nspname = get_namespace_name(procform->pronamespace); 10956 10957 result = quote_qualified_identifier(nspname, proname); 10958 10959 ReleaseSysCache(proctup); 10960 10961 return result; 10962 } 10963 10964 /* 10965 * generate_operator_name 10966 * Compute the name to display for an operator specified by OID, 10967 * given that it is being called with the specified actual arg types. 10968 * (Arg types matter because of ambiguous-operator resolution rules. 10969 * Pass InvalidOid for unused arg of a unary operator.) 10970 * 10971 * The result includes all necessary quoting and schema-prefixing, 10972 * plus the OPERATOR() decoration needed to use a qualified operator name 10973 * in an expression. 10974 */ 10975 static char * 10976 generate_operator_name(Oid operid, Oid arg1, Oid arg2) 10977 { 10978 StringInfoData buf; 10979 HeapTuple opertup; 10980 Form_pg_operator operform; 10981 char *oprname; 10982 char *nspname; 10983 Operator p_result; 10984 10985 initStringInfo(&buf); 10986 10987 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid)); 10988 if (!HeapTupleIsValid(opertup)) 10989 elog(ERROR, "cache lookup failed for operator %u", operid); 10990 operform = (Form_pg_operator) GETSTRUCT(opertup); 10991 oprname = NameStr(operform->oprname); 10992 10993 /* 10994 * The idea here is to schema-qualify only if the parser would fail to 10995 * resolve the correct operator given the unqualified op name with the 10996 * specified argtypes. 10997 */ 10998 switch (operform->oprkind) 10999 { 11000 case 'b': 11001 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2, 11002 true, -1); 11003 break; 11004 case 'l': 11005 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2, 11006 true, -1); 11007 break; 11008 case 'r': 11009 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1, 11010 true, -1); 11011 break; 11012 default: 11013 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind); 11014 p_result = NULL; /* keep compiler quiet */ 11015 break; 11016 } 11017 11018 if (p_result != NULL && oprid(p_result) == operid) 11019 nspname = NULL; 11020 else 11021 { 11022 nspname = get_namespace_name(operform->oprnamespace); 11023 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname)); 11024 } 11025 11026 appendStringInfoString(&buf, oprname); 11027 11028 if (nspname) 11029 appendStringInfoChar(&buf, ')'); 11030 11031 if (p_result != NULL) 11032 ReleaseSysCache(p_result); 11033 11034 ReleaseSysCache(opertup); 11035 11036 return buf.data; 11037 } 11038 11039 /* 11040 * generate_operator_clause --- generate a binary-operator WHERE clause 11041 * 11042 * This is used for internally-generated-and-executed SQL queries, where 11043 * precision is essential and readability is secondary. The basic 11044 * requirement is to append "leftop op rightop" to buf, where leftop and 11045 * rightop are given as strings and are assumed to yield types leftoptype 11046 * and rightoptype; the operator is identified by OID. The complexity 11047 * comes from needing to be sure that the parser will select the desired 11048 * operator when the query is parsed. We always name the operator using 11049 * OPERATOR(schema.op) syntax, so as to avoid search-path uncertainties. 11050 * We have to emit casts too, if either input isn't already the input type 11051 * of the operator; else we are at the mercy of the parser's heuristics for 11052 * ambiguous-operator resolution. The caller must ensure that leftop and 11053 * rightop are suitable arguments for a cast operation; it's best to insert 11054 * parentheses if they aren't just variables or parameters. 11055 */ 11056 void 11057 generate_operator_clause(StringInfo buf, 11058 const char *leftop, Oid leftoptype, 11059 Oid opoid, 11060 const char *rightop, Oid rightoptype) 11061 { 11062 HeapTuple opertup; 11063 Form_pg_operator operform; 11064 char *oprname; 11065 char *nspname; 11066 11067 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opoid)); 11068 if (!HeapTupleIsValid(opertup)) 11069 elog(ERROR, "cache lookup failed for operator %u", opoid); 11070 operform = (Form_pg_operator) GETSTRUCT(opertup); 11071 Assert(operform->oprkind == 'b'); 11072 oprname = NameStr(operform->oprname); 11073 11074 nspname = get_namespace_name(operform->oprnamespace); 11075 11076 appendStringInfoString(buf, leftop); 11077 if (leftoptype != operform->oprleft) 11078 add_cast_to(buf, operform->oprleft); 11079 appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname)); 11080 appendStringInfoString(buf, oprname); 11081 appendStringInfo(buf, ") %s", rightop); 11082 if (rightoptype != operform->oprright) 11083 add_cast_to(buf, operform->oprright); 11084 11085 ReleaseSysCache(opertup); 11086 } 11087 11088 /* 11089 * Add a cast specification to buf. We spell out the type name the hard way, 11090 * intentionally not using format_type_be(). This is to avoid corner cases 11091 * for CHARACTER, BIT, and perhaps other types, where specifying the type 11092 * using SQL-standard syntax results in undesirable data truncation. By 11093 * doing it this way we can be certain that the cast will have default (-1) 11094 * target typmod. 11095 */ 11096 static void 11097 add_cast_to(StringInfo buf, Oid typid) 11098 { 11099 HeapTuple typetup; 11100 Form_pg_type typform; 11101 char *typname; 11102 char *nspname; 11103 11104 typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid)); 11105 if (!HeapTupleIsValid(typetup)) 11106 elog(ERROR, "cache lookup failed for type %u", typid); 11107 typform = (Form_pg_type) GETSTRUCT(typetup); 11108 11109 typname = NameStr(typform->typname); 11110 nspname = get_namespace_name(typform->typnamespace); 11111 11112 appendStringInfo(buf, "::%s.%s", 11113 quote_identifier(nspname), quote_identifier(typname)); 11114 11115 ReleaseSysCache(typetup); 11116 } 11117 11118 /* 11119 * generate_qualified_type_name 11120 * Compute the name to display for a type specified by OID 11121 * 11122 * This is different from format_type_be() in that we unconditionally 11123 * schema-qualify the name. That also means no special syntax for 11124 * SQL-standard type names ... although in current usage, this should 11125 * only get used for domains, so such cases wouldn't occur anyway. 11126 */ 11127 static char * 11128 generate_qualified_type_name(Oid typid) 11129 { 11130 HeapTuple tp; 11131 Form_pg_type typtup; 11132 char *typname; 11133 char *nspname; 11134 char *result; 11135 11136 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid)); 11137 if (!HeapTupleIsValid(tp)) 11138 elog(ERROR, "cache lookup failed for type %u", typid); 11139 typtup = (Form_pg_type) GETSTRUCT(tp); 11140 typname = NameStr(typtup->typname); 11141 11142 nspname = get_namespace_name(typtup->typnamespace); 11143 if (!nspname) 11144 elog(ERROR, "cache lookup failed for namespace %u", 11145 typtup->typnamespace); 11146 11147 result = quote_qualified_identifier(nspname, typname); 11148 11149 ReleaseSysCache(tp); 11150 11151 return result; 11152 } 11153 11154 /* 11155 * generate_collation_name 11156 * Compute the name to display for a collation specified by OID 11157 * 11158 * The result includes all necessary quoting and schema-prefixing. 11159 */ 11160 char * 11161 generate_collation_name(Oid collid) 11162 { 11163 HeapTuple tp; 11164 Form_pg_collation colltup; 11165 char *collname; 11166 char *nspname; 11167 char *result; 11168 11169 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); 11170 if (!HeapTupleIsValid(tp)) 11171 elog(ERROR, "cache lookup failed for collation %u", collid); 11172 colltup = (Form_pg_collation) GETSTRUCT(tp); 11173 collname = NameStr(colltup->collname); 11174 11175 if (!CollationIsVisible(collid)) 11176 nspname = get_namespace_name(colltup->collnamespace); 11177 else 11178 nspname = NULL; 11179 11180 result = quote_qualified_identifier(nspname, collname); 11181 11182 ReleaseSysCache(tp); 11183 11184 return result; 11185 } 11186 11187 /* 11188 * Given a C string, produce a TEXT datum. 11189 * 11190 * We assume that the input was palloc'd and may be freed. 11191 */ 11192 static text * 11193 string_to_text(char *str) 11194 { 11195 text *result; 11196 11197 result = cstring_to_text(str); 11198 pfree(str); 11199 return result; 11200 } 11201 11202 /* 11203 * Generate a C string representing a relation's reloptions, or NULL if none. 11204 */ 11205 static char * 11206 flatten_reloptions(Oid relid) 11207 { 11208 char *result = NULL; 11209 HeapTuple tuple; 11210 Datum reloptions; 11211 bool isnull; 11212 11213 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); 11214 if (!HeapTupleIsValid(tuple)) 11215 elog(ERROR, "cache lookup failed for relation %u", relid); 11216 11217 reloptions = SysCacheGetAttr(RELOID, tuple, 11218 Anum_pg_class_reloptions, &isnull); 11219 if (!isnull) 11220 { 11221 StringInfoData buf; 11222 Datum *options; 11223 int noptions; 11224 int i; 11225 11226 initStringInfo(&buf); 11227 11228 deconstruct_array(DatumGetArrayTypeP(reloptions), 11229 TEXTOID, -1, false, 'i', 11230 &options, NULL, &noptions); 11231 11232 for (i = 0; i < noptions; i++) 11233 { 11234 char *option = TextDatumGetCString(options[i]); 11235 char *name; 11236 char *separator; 11237 char *value; 11238 11239 /* 11240 * Each array element should have the form name=value. If the "=" 11241 * is missing for some reason, treat it like an empty value. 11242 */ 11243 name = option; 11244 separator = strchr(option, '='); 11245 if (separator) 11246 { 11247 *separator = '\0'; 11248 value = separator + 1; 11249 } 11250 else 11251 value = ""; 11252 11253 if (i > 0) 11254 appendStringInfoString(&buf, ", "); 11255 appendStringInfo(&buf, "%s=", quote_identifier(name)); 11256 11257 /* 11258 * In general we need to quote the value; but to avoid unnecessary 11259 * clutter, do not quote if it is an identifier that would not 11260 * need quoting. (We could also allow numbers, but that is a bit 11261 * trickier than it looks --- for example, are leading zeroes 11262 * significant? We don't want to assume very much here about what 11263 * custom reloptions might mean.) 11264 */ 11265 if (quote_identifier(value) == value) 11266 appendStringInfoString(&buf, value); 11267 else 11268 simple_quote_literal(&buf, value); 11269 11270 pfree(option); 11271 } 11272 11273 result = buf.data; 11274 } 11275 11276 ReleaseSysCache(tuple); 11277 11278 return result; 11279 } 11280 11281 /* 11282 * get_one_range_partition_bound_string 11283 * A C string representation of one range partition bound 11284 */ 11285 char * 11286 get_range_partbound_string(List *bound_datums) 11287 { 11288 deparse_context context; 11289 StringInfo buf = makeStringInfo(); 11290 ListCell *cell; 11291 char *sep; 11292 11293 memset(&context, 0, sizeof(deparse_context)); 11294 context.buf = buf; 11295 11296 appendStringInfoString(buf, "("); 11297 sep = ""; 11298 foreach(cell, bound_datums) 11299 { 11300 PartitionRangeDatum *datum = 11301 castNode(PartitionRangeDatum, lfirst(cell)); 11302 11303 appendStringInfoString(buf, sep); 11304 if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE) 11305 appendStringInfoString(buf, "MINVALUE"); 11306 else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE) 11307 appendStringInfoString(buf, "MAXVALUE"); 11308 else 11309 { 11310 Const *val = castNode(Const, datum->value); 11311 11312 get_const_expr(val, &context, -1); 11313 } 11314 sep = ", "; 11315 } 11316 appendStringInfoChar(buf, ')'); 11317 11318 return buf->data; 11319 } 11320