summaryrefslogtreecommitdiffstats
path: root/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util
diff options
context:
space:
mode:
authorvvvv <[email protected]>2025-10-24 14:59:50 +0300
committervvvv <[email protected]>2025-10-24 15:29:24 +0300
commit5b0d18921f2a509d8363c40a5ca208dfed026287 (patch)
treed1369c696d3a9e9a65b68d9208e198269a48cfbc /yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util
parente7fbdb6e81ae4a296e710b133de7a2a04b31bbc4 (diff)
YQL-20567 upgrade PG up to 16.10 & fix instructions
init commit_hash:81aba13295273281d19d2d332a48ff1c44977447
Diffstat (limited to 'yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util')
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/clauses.c28
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/inherit.c13
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/pathnode.c2
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/plancat.c75
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/predtest.c20
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/relnode.c4
6 files changed, 120 insertions, 22 deletions
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/clauses.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/clauses.c
index 62650995cb6..85ee860a136 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/clauses.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/clauses.c
@@ -2309,7 +2309,7 @@ convert_saop_to_hashed_saop_walker(Node *node, void *context)
/* Looks good. Fill in the hash functions */
saop->hashfuncid = lefthashfunc;
}
- return true;
+ return false;
}
}
else /* !saop->useOr */
@@ -2347,7 +2347,7 @@ convert_saop_to_hashed_saop_walker(Node *node, void *context)
*/
saop->negfuncid = get_opcode(negator);
}
- return true;
+ return false;
}
}
}
@@ -2897,13 +2897,25 @@ eval_const_expressions_mutator(Node *node,
case T_JsonValueExpr:
{
JsonValueExpr *jve = (JsonValueExpr *) node;
- Node *formatted;
+ Node *raw_expr = (Node *) jve->raw_expr;
+ Node *formatted_expr = (Node *) jve->formatted_expr;
- formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr,
- context);
- if (formatted && IsA(formatted, Const))
- return formatted;
- break;
+ /*
+ * If we can fold formatted_expr to a constant, we can elide
+ * the JsonValueExpr altogether. Otherwise we must process
+ * raw_expr too. But JsonFormat is a flat node and requires
+ * no simplification, only copying.
+ */
+ formatted_expr = eval_const_expressions_mutator(formatted_expr,
+ context);
+ if (formatted_expr && IsA(formatted_expr, Const))
+ return formatted_expr;
+
+ raw_expr = eval_const_expressions_mutator(raw_expr, context);
+
+ return (Node *) makeJsonValueExpr((Expr *) raw_expr,
+ (Expr *) formatted_expr,
+ copyObject(jve->format));
}
case T_SubPlan:
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/inherit.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/inherit.c
index f9d3ff1e7ac..f9a8bc5cd8f 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/inherit.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/inherit.c
@@ -386,8 +386,17 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo,
Index childRTindex;
RelOptInfo *childrelinfo;
- /* Open rel, acquiring required locks */
- childrel = table_open(childOID, lockmode);
+ /*
+ * Open rel, acquiring required locks. If a partition was recently
+ * detached and subsequently dropped, then opening it will fail. In
+ * this case, behave as though the partition had been pruned.
+ */
+ childrel = try_table_open(childOID, lockmode);
+ if (childrel == NULL)
+ {
+ relinfo->live_parts = bms_del_member(relinfo->live_parts, i);
+ continue;
+ }
/*
* Temporary partitions belonging to other sessions should have been
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/pathnode.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/pathnode.c
index bd232263b48..bd02b7b1cb3 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/pathnode.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/pathnode.c
@@ -1621,7 +1621,7 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
pathnode->param_exprs = param_exprs;
pathnode->singlerow = singlerow;
pathnode->binary_mode = binary_mode;
- pathnode->calls = calls;
+ pathnode->calls = clamp_row_est(calls);
/*
* For now we set est_entries to 0. cost_memoize_rescan() does all the
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/plancat.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/plancat.c
index dba503da1e6..7e7f636db52 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/plancat.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/plancat.c
@@ -47,6 +47,7 @@
#include "rewrite/rewriteManip.h"
#include "statistics/statistics.h"
#include "storage/bufmgr.h"
+#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
@@ -500,6 +501,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
/* Grab foreign-table info using the relcache, while we have it */
if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
{
+ /* Check if the access to foreign tables is restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0))
+ {
+ /* there must not be built-in foreign tables */
+ Assert(RelationGetRelid(relation) >= FirstNormalObjectId);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system foreign table is restricted")));
+ }
+
rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation));
rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
}
@@ -667,6 +679,7 @@ infer_arbiter_indexes(PlannerInfo *root)
OnConflictExpr *onconflict = root->parse->onConflict;
/* Iteration state */
+ Index varno;
RangeTblEntry *rte;
Relation relation;
Oid indexOidFromConstraint = InvalidOid;
@@ -695,7 +708,8 @@ infer_arbiter_indexes(PlannerInfo *root)
* the rewriter or when expand_inherited_rtentry() added it to the query's
* rangetable.
*/
- rte = rt_fetch(root->parse->resultRelation, root->parse->rtable);
+ varno = root->parse->resultRelation;
+ rte = rt_fetch(varno, root->parse->rtable);
relation = table_open(rte->relid, NoLock);
@@ -829,6 +843,9 @@ infer_arbiter_indexes(PlannerInfo *root)
/* Expression attributes (if any) must match */
idxExprs = RelationGetIndexExpressions(idxRel);
+ if (idxExprs && varno != 1)
+ ChangeVarNodes((Node *) idxExprs, 1, varno, 0);
+
foreach(el, onconflict->arbiterElems)
{
InferenceElem *elem = (InferenceElem *) lfirst(el);
@@ -880,6 +897,8 @@ infer_arbiter_indexes(PlannerInfo *root)
* CONFLICT's WHERE clause.
*/
predExprs = RelationGetIndexPredicate(idxRel);
+ if (predExprs && varno != 1)
+ ChangeVarNodes((Node *) predExprs, 1, varno, 0);
if (!predicate_implied_by(predExprs, (List *) onconflict->arbiterWhere, false))
goto next;
@@ -2234,6 +2253,60 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
}
/*
+ * has_transition_tables
+ *
+ * Detect whether the specified relation has any transition tables for event.
+ */
+bool
+has_transition_tables(PlannerInfo *root, Index rti, CmdType event)
+{
+ RangeTblEntry *rte = planner_rt_fetch(rti, root);
+ Relation relation;
+ TriggerDesc *trigDesc;
+ bool result = false;
+
+ Assert(rte->rtekind == RTE_RELATION);
+
+ /* Currently foreign tables cannot have transition tables */
+ if (rte->relkind == RELKIND_FOREIGN_TABLE)
+ return result;
+
+ /* Assume we already have adequate lock */
+ relation = table_open(rte->relid, NoLock);
+
+ trigDesc = relation->trigdesc;
+ switch (event)
+ {
+ case CMD_INSERT:
+ if (trigDesc &&
+ trigDesc->trig_insert_new_table)
+ result = true;
+ break;
+ case CMD_UPDATE:
+ if (trigDesc &&
+ (trigDesc->trig_update_old_table ||
+ trigDesc->trig_update_new_table))
+ result = true;
+ break;
+ case CMD_DELETE:
+ if (trigDesc &&
+ trigDesc->trig_delete_old_table)
+ result = true;
+ break;
+ /* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
+ case CMD_MERGE:
+ result = false;
+ break;
+ default:
+ elog(ERROR, "unrecognized CmdType: %d", (int) event);
+ break;
+ }
+
+ table_close(relation, NoLock);
+ return result;
+}
+
+/*
* has_stored_generated_columns
*
* Does table identified by RTI have any STORED GENERATED columns?
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/predtest.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/predtest.c
index c04380c32b1..13053b6ed07 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/predtest.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/predtest.c
@@ -948,7 +948,7 @@ boolexpr_startup_fn(Node *clause, PredIterInfo info)
typedef struct
{
OpExpr opexpr;
- Const constexpr;
+ Const const_expr;
int next_elem;
int num_elems;
Datum *elem_values;
@@ -992,13 +992,13 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info)
state->opexpr.args = list_copy(saop->args);
/* Set up a dummy Const node to hold the per-element values */
- state->constexpr.xpr.type = T_Const;
- state->constexpr.consttype = ARR_ELEMTYPE(arrayval);
- state->constexpr.consttypmod = -1;
- state->constexpr.constcollid = arrayconst->constcollid;
- state->constexpr.constlen = elmlen;
- state->constexpr.constbyval = elmbyval;
- lsecond(state->opexpr.args) = &state->constexpr;
+ state->const_expr.xpr.type = T_Const;
+ state->const_expr.consttype = ARR_ELEMTYPE(arrayval);
+ state->const_expr.consttypmod = -1;
+ state->const_expr.constcollid = arrayconst->constcollid;
+ state->const_expr.constlen = elmlen;
+ state->const_expr.constbyval = elmbyval;
+ lsecond(state->opexpr.args) = &state->const_expr;
/* Initialize iteration state */
state->next_elem = 0;
@@ -1011,8 +1011,8 @@ arrayconst_next_fn(PredIterInfo info)
if (state->next_elem >= state->num_elems)
return NULL;
- state->constexpr.constvalue = state->elem_values[state->next_elem];
- state->constexpr.constisnull = state->elem_nulls[state->next_elem];
+ state->const_expr.constvalue = state->elem_values[state->next_elem];
+ state->const_expr.constisnull = state->elem_nulls[state->next_elem];
state->next_elem++;
return (Node *) &(state->opexpr);
}
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/relnode.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/relnode.c
index e6d5cd8281a..a5a6daf7c87 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/relnode.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util/relnode.c
@@ -2163,6 +2163,10 @@ have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
if (ipk1 != ipk2)
continue;
+ /* Reject if the partition key collation differs from the clause's. */
+ if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
+ return false;
+
/*
* The clause allows partitionwise join only if it uses the same
* operator family as that specified by the partition key.