Skip to content

Commit 5177af1

Browse files
committed
Apply necessary ruleutils changes to PG18 ruleutils file (#788)
Done by taking the diff for PG17 ruleutils, manually changing 17 to 18 in there everywhere and then applying: To get the diff: ``` git diff e963297 src/vendor/pg_ruleutils_17.c > ruleutils.diff ``` To apply: ``` git apply --3way ruleutils.diff ```
1 parent 434e3f7 commit 5177af1

File tree

1 file changed

+109
-112
lines changed

1 file changed

+109
-112
lines changed

src/vendor/pg_ruleutils_18.c

Lines changed: 109 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* ruleutils.c
3+
* pg_ruleutils_18.c
44
* Functions to convert stored expressions/querytrees back to
55
* source text
66
*
77
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
*
11-
* IDENTIFICATION
12-
* src/backend/utils/adt/ruleutils.c
13-
*
1410
*-------------------------------------------------------------------------
1511
*/
1612
#include "postgres.h"
1713

14+
#if PG_VERSION_NUM >= 180000 && PG_VERSION_NUM < 190000
15+
16+
#pragma GCC diagnostic ignored "-Wshadow" // ignore any compiler warnings
17+
#pragma GCC diagnostic ignored "-Wsign-compare" // ignore any compiler warnings
18+
#pragma GCC diagnostic ignored "-Wunused-parameter" // ignore any compiler warnings
19+
1820
#include <ctype.h>
1921
#include <unistd.h>
2022
#include <fcntl.h>
@@ -65,13 +67,17 @@
6567
#include "utils/lsyscache.h"
6668
#include "utils/partcache.h"
6769
#include "utils/rel.h"
68-
#include "utils/ruleutils.h"
70+
#include "pgduckdb/vendor/pg_ruleutils.h"
6971
#include "utils/snapmgr.h"
7072
#include "utils/syscache.h"
7173
#include "utils/typcache.h"
7274
#include "utils/varlena.h"
7375
#include "utils/xml.h"
7476

77+
#include "pgduckdb/pgduckdb_ruleutils.h"
78+
79+
#include "pgduckdb/utility/rename_ruleutils.h"
80+
7581
/* ----------
7682
* Pretty formatting constants
7783
* ----------
@@ -92,7 +98,7 @@
9298
/* Standard conversion of a "bool pretty" option to detailed flags */
9399
#define GET_PRETTY_FLAGS(pretty) \
94100
((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
95-
: PRETTYFLAG_INDENT)
101+
: 0)
96102

97103
/* Default line length for pretty-print wrapping: 0 means wrap always */
98104
#define WRAP_COLUMN_DEFAULT 0
@@ -525,8 +531,6 @@ static void get_opclass_name(Oid opclass, Oid actual_datatype,
525531
static Node *processIndirection(Node *node, deparse_context *context);
526532
static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
527533
static char *get_relation_name(Oid relid);
528-
static char *generate_relation_name(Oid relid, List *namespaces);
529-
static char *generate_qualified_relation_name(Oid relid);
530534
static char *generate_function_name(Oid funcid, int nargs,
531535
List *argnames, Oid *argtypes,
532536
bool has_variadic, bool *use_variadic_p,
@@ -5773,6 +5777,9 @@ get_with_clause(Query *query, deparse_context *context)
57735777
if (query->cteList == NIL)
57745778
return;
57755779

5780+
bool previous_outermost_query = outermost_query;
5781+
outermost_query = false;
5782+
57765783
if (PRETTY_INDENT(context))
57775784
{
57785785
context->indentLevel += PRETTYINDENT_STD;
@@ -5896,6 +5903,8 @@ get_with_clause(Query *query, deparse_context *context)
58965903
}
58975904
else
58985905
appendStringInfoChar(buf, ' ');
5906+
5907+
outermost_query = previous_outermost_query;
58995908
}
59005909

59015910
/* ----------
@@ -6240,12 +6249,23 @@ get_target_list(List *targetList, deparse_context *context)
62406249

62416250
sep = " ";
62426251
colno = 0;
6252+
6253+
StarReconstructionContext star_reconstruction_context = {0};
6254+
star_reconstruction_context.target_list = targetList;
6255+
6256+
bool outermost_targetlist = outermost_query;
6257+
outermost_query = false;
6258+
62436259
foreach(l, targetList)
62446260
{
62456261
TargetEntry *tle = (TargetEntry *) lfirst(l);
62466262
char *colname;
62476263
char *attname;
62486264

6265+
if (pgduckdb_reconstruct_star_step(&star_reconstruction_context, l)) {
6266+
continue;
6267+
}
6268+
62496269
if (tle->resjunk)
62506270
continue; /* ignore junk entries */
62516271

@@ -6270,8 +6290,10 @@ get_target_list(List *targetList, deparse_context *context)
62706290
* directly so that we can tell it to do the right thing, and so that
62716291
* we can get the attribute name which is the default AS label.
62726292
*/
6293+
Var *var = NULL;
62736294
if (tle->expr && (IsA(tle->expr, Var)))
62746295
{
6296+
var = (Var *) tle->expr;
62756297
attname = get_variable((Var *) tle->expr, 0, true, context);
62766298
}
62776299
else
@@ -6298,8 +6320,33 @@ get_target_list(List *targetList, deparse_context *context)
62986320
else
62996321
colname = tle->resname;
63006322

6323+
/*
6324+
* This makes sure we don't add Postgres its bad default alias to the
6325+
* duckdb.row type.
6326+
*/
6327+
bool duckdb_skip_as = pgduckdb_var_is_duckdb_row(var);
6328+
6329+
/*
6330+
* For r['abc'] expressions we don't want the column name to be r, but
6331+
* instead we want it to be "abc". We can only to do this for the
6332+
* target list of the outside most query though to make sure references
6333+
* to the column name are still valid.
6334+
*/
6335+
if (!duckdb_skip_as && outermost_targetlist) {
6336+
Var *subscript_var = pgduckdb_duckdb_row_subscript_var(tle->expr);
6337+
if (subscript_var) {
6338+
/*
6339+
* This cannot be moved to pgduckdb_ruleutils, because of
6340+
* the reliance on the non-public deparse_namespace type.
6341+
*/
6342+
deparse_namespace* dpns = (deparse_namespace *) list_nth(context->namespaces,
6343+
subscript_var->varlevelsup);
6344+
duckdb_skip_as = !pgduckdb_subscript_has_custom_alias(dpns->plan, dpns->rtable, subscript_var, colname);
6345+
}
6346+
}
6347+
63016348
/* Show AS unless the column's name is correct as-is */
6302-
if (colname) /* resname could be NULL */
6349+
if (colname && !duckdb_skip_as) /* resname could be NULL */
63036350
{
63046351
if (attname == NULL || strcmp(attname, colname) != 0)
63056352
appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname));
@@ -6999,6 +7046,16 @@ get_insert_query_def(Query *query, deparse_context *context)
69997046
if (tle->resjunk)
70007047
continue; /* ignore junk entries */
70017048

7049+
/*
7050+
* If it's an INSERT ... SELECT or multi-row VALUES, the entry
7051+
* with the default value is ignored unless it is specified
7052+
*/
7053+
if (values_rte || select_rte)
7054+
{
7055+
if (!pgduckdb_is_not_default_expr((Node *) tle, NULL))
7056+
continue;
7057+
}
7058+
70027059
appendStringInfoString(buf, sep);
70037060
sep = ", ";
70047061

@@ -7791,6 +7848,11 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
77917848
if (attnum > colinfo->num_cols)
77927849
elog(ERROR, "invalid attnum %d for relation \"%s\"",
77937850
attnum, rte->eref->aliasname);
7851+
7852+
if (pgduckdb_var_is_duckdb_row(var)) {
7853+
return pgduckdb_write_row_refname(context->buf, refname, istoplevel);
7854+
}
7855+
77947856
attname = colinfo->colnames[attnum - 1];
77957857

77967858
/*
@@ -9354,8 +9416,9 @@ get_rule_expr(Node *node, deparse_context *context,
93549416
}
93559417
else
93569418
{
9419+
SubscriptingRef *new_sbsref = pgduckdb_strip_first_subscript(sbsref, context->buf);
93579420
/* Just an ordinary container fetch, so print subscripts */
9358-
printSubscripts(sbsref, context);
9421+
printSubscripts(new_sbsref, context);
93599422
}
93609423
}
93619424
break;
@@ -10736,12 +10799,13 @@ get_oper_expr(OpExpr *expr, deparse_context *context)
1073610799
Node *arg1 = (Node *) linitial(args);
1073710800
Node *arg2 = (Node *) lsecond(args);
1073810801

10802+
char* op_name = generate_operator_name(opno, exprType(arg1), exprType(arg2));
10803+
void* ctx = pg_duckdb_get_oper_expr_make_ctx(op_name, &arg1, &arg2);
10804+
pg_duckdb_get_oper_expr_prefix(buf, ctx);
1073910805
get_rule_expr_paren(arg1, context, true, (Node *) expr);
10740-
appendStringInfo(buf, " %s ",
10741-
generate_operator_name(opno,
10742-
exprType(arg1),
10743-
exprType(arg2)));
10806+
pg_duckdb_get_oper_expr_middle(buf, ctx);
1074410807
get_rule_expr_paren(arg2, context, true, (Node *) expr);
10808+
pg_duckdb_get_oper_expr_suffix(buf, ctx);
1074510809
}
1074610810
else
1074710811
{
@@ -11425,6 +11489,10 @@ get_coercion_expr(Node *arg, deparse_context *context,
1142511489
appendStringInfoChar(buf, ')');
1142611490
}
1142711491

11492+
if (pgduckdb_is_fake_type(resulttype)) {
11493+
return;
11494+
}
11495+
1142811496
/*
1142911497
* Never emit resulttype(arg) functional notation. A pg_proc entry could
1143011498
* take precedence, and a resulttype in pg_temp would require schema
@@ -11460,6 +11528,8 @@ get_const_expr(Const *constval, deparse_context *context, int showtype)
1146011528
char *extval;
1146111529
bool needlabel = false;
1146211530

11531+
showtype = pgduckdb_show_type(constval, showtype);
11532+
1146311533
if (constval->constisnull)
1146411534
{
1146511535
/*
@@ -12378,6 +12448,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
1237812448
break;
1237912449
case RTE_SUBQUERY:
1238012450
/* Subquery RTE */
12451+
if (pgduckdb_replace_subquery_with_view(rte->subquery, buf)) {
12452+
break;
12453+
}
1238112454
appendStringInfoChar(buf, '(');
1238212455
get_query_def(rte->subquery, buf, context->namespaces, NULL,
1238312456
true,
@@ -12500,8 +12573,18 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
1250012573
/* Print the relation alias, if needed */
1250112574
get_rte_alias(rte, varno, false, context);
1250212575

12576+
if (pgduckdb_func_returns_duckdb_row(rtfunc1)) {
12577+
/*
12578+
* We never want to print column aliases for functions that return
12579+
* a duckdb.row. The common pattern is for people to not provide an
12580+
* explicit column alias (i.e. "r" becomes "r(r)"). This obviously
12581+
* is a naming collision and DuckDB resolves that in the opposite
12582+
* way that we want. Never adding column aliases for duckdb.row
12583+
* avoids this conflict.
12584+
*/
12585+
}
1250312586
/* Print the column definitions or aliases, if needed */
12504-
if (rtfunc1 && rtfunc1->funccolnames != NIL)
12587+
else if (rtfunc1 && rtfunc1->funccolnames != NIL)
1250512588
{
1250612589
/* Reconstruct the columndef list, which is also the aliases */
1250712590
get_from_clause_coldeflist(rtfunc1, colinfo, context);
@@ -12827,6 +12910,10 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
1282712910
if (nargs++ > 0)
1282812911
appendStringInfoString(buf, ", ");
1282912912
get_rule_expr((Node *) lfirst(l), context, false);
12913+
const char *tsm_name = generate_function_name(tablesample->tsmhandler, 1,
12914+
NIL, argtypes,
12915+
false, NULL, EXPR_KIND_NONE);
12916+
pgduckdb_add_tablesample_percent(tsm_name, buf, list_length(tablesample->args));
1283012917
}
1283112918
appendStringInfoChar(buf, ')');
1283212919

@@ -13129,102 +13216,6 @@ get_relation_name(Oid relid)
1312913216
return relname;
1313013217
}
1313113218

13132-
/*
13133-
* generate_relation_name
13134-
* Compute the name to display for a relation specified by OID
13135-
*
13136-
* The result includes all necessary quoting and schema-prefixing.
13137-
*
13138-
* If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
13139-
* We will forcibly qualify the relation name if it equals any CTE name
13140-
* visible in the namespace list.
13141-
*/
13142-
static char *
13143-
generate_relation_name(Oid relid, List *namespaces)
13144-
{
13145-
HeapTuple tp;
13146-
Form_pg_class reltup;
13147-
bool need_qual;
13148-
ListCell *nslist;
13149-
char *relname;
13150-
char *nspname;
13151-
char *result;
13152-
13153-
tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
13154-
if (!HeapTupleIsValid(tp))
13155-
elog(ERROR, "cache lookup failed for relation %u", relid);
13156-
reltup = (Form_pg_class) GETSTRUCT(tp);
13157-
relname = NameStr(reltup->relname);
13158-
13159-
/* Check for conflicting CTE name */
13160-
need_qual = false;
13161-
foreach(nslist, namespaces)
13162-
{
13163-
deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
13164-
ListCell *ctlist;
13165-
13166-
foreach(ctlist, dpns->ctes)
13167-
{
13168-
CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
13169-
13170-
if (strcmp(cte->ctename, relname) == 0)
13171-
{
13172-
need_qual = true;
13173-
break;
13174-
}
13175-
}
13176-
if (need_qual)
13177-
break;
13178-
}
13179-
13180-
/* Otherwise, qualify the name if not visible in search path */
13181-
if (!need_qual)
13182-
need_qual = !RelationIsVisible(relid);
13183-
13184-
if (need_qual)
13185-
nspname = get_namespace_name_or_temp(reltup->relnamespace);
13186-
else
13187-
nspname = NULL;
13188-
13189-
result = quote_qualified_identifier(nspname, relname);
13190-
13191-
ReleaseSysCache(tp);
13192-
13193-
return result;
13194-
}
13195-
13196-
/*
13197-
* generate_qualified_relation_name
13198-
* Compute the name to display for a relation specified by OID
13199-
*
13200-
* As above, but unconditionally schema-qualify the name.
13201-
*/
13202-
static char *
13203-
generate_qualified_relation_name(Oid relid)
13204-
{
13205-
HeapTuple tp;
13206-
Form_pg_class reltup;
13207-
char *relname;
13208-
char *nspname;
13209-
char *result;
13210-
13211-
tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
13212-
if (!HeapTupleIsValid(tp))
13213-
elog(ERROR, "cache lookup failed for relation %u", relid);
13214-
reltup = (Form_pg_class) GETSTRUCT(tp);
13215-
relname = NameStr(reltup->relname);
13216-
13217-
nspname = get_namespace_name_or_temp(reltup->relnamespace);
13218-
if (!nspname)
13219-
elog(ERROR, "cache lookup failed for namespace %u",
13220-
reltup->relnamespace);
13221-
13222-
result = quote_qualified_identifier(nspname, relname);
13223-
13224-
ReleaseSysCache(tp);
13225-
13226-
return result;
13227-
}
1322813219

1322913220
/*
1323013221
* generate_function_name
@@ -13263,6 +13254,10 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
1326313254
Oid *p_true_typeids;
1326413255
bool force_qualify = false;
1326513256

13257+
result = pgduckdb_function_name(funcid, use_variadic_p);
13258+
if (result)
13259+
return result;
13260+
1326613261
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1326713262
if (!HeapTupleIsValid(proctup))
1326813263
elog(ERROR, "cache lookup failed for function %u", funcid);
@@ -13697,3 +13692,5 @@ get_range_partbound_string(List *bound_datums)
1369713692

1369813693
return buf->data;
1369913694
}
13695+
13696+
#endif

0 commit comments

Comments
 (0)