diff options
| author | vvvv <[email protected]> | 2025-10-24 14:59:50 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2025-10-24 15:29:24 +0300 |
| commit | 5b0d18921f2a509d8363c40a5ca208dfed026287 (patch) | |
| tree | d1369c696d3a9e9a65b68d9208e198269a48cfbc /yql/essentials/parser/pg_wrapper/postgresql/src/backend/optimizer/util | |
| parent | e7fbdb6e81ae4a296e710b133de7a2a04b31bbc4 (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')
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. |
