summaryrefslogtreecommitdiffstats
path: root/yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c
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/rewrite/rewriteHandler.c
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/rewrite/rewriteHandler.c')
-rw-r--r--yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c161
1 files changed, 109 insertions, 52 deletions
diff --git a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c
index 2510ce79c6e..57f075de394 100644
--- a/yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c
+++ b/yql/essentials/parser/pg_wrapper/postgresql/src/backend/rewrite/rewriteHandler.c
@@ -41,6 +41,7 @@
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSearchCycle.h"
#include "rewrite/rowsecurity.h"
+#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
@@ -58,6 +59,12 @@ typedef struct acquireLocksOnSubLinks_context
bool for_execute; /* AcquireRewriteLocks' forExecute param */
} acquireLocksOnSubLinks_context;
+typedef struct fireRIRonSubLink_context
+{
+ List *activeRIRs;
+ bool hasRowSecurity;
+} fireRIRonSubLink_context;
+
static bool acquireLocksOnSubLinks(Node *node,
acquireLocksOnSubLinks_context *context);
static Query *rewriteRuleAction(Query *parsetree,
@@ -997,23 +1004,11 @@ rewriteTargetListIU(List *targetList,
if (commandType == CMD_INSERT)
new_tle = NULL;
else
- {
- new_expr = (Node *) makeConst(att_tup->atttypid,
- -1,
- att_tup->attcollation,
- att_tup->attlen,
- (Datum) 0,
- true, /* isnull */
- att_tup->attbyval);
- /* this is to catch a NOT NULL domain constraint */
- new_expr = coerce_to_domain(new_expr,
- InvalidOid, -1,
- att_tup->atttypid,
- COERCION_IMPLICIT,
- COERCE_IMPLICIT_CAST,
- -1,
- false);
- }
+ new_expr = coerce_null_to_domain(att_tup->atttypid,
+ att_tup->atttypmod,
+ att_tup->attcollation,
+ att_tup->attlen,
+ att_tup->attbyval);
}
if (new_expr)
@@ -1575,21 +1570,11 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
continue;
}
- new_expr = (Node *) makeConst(att_tup->atttypid,
- -1,
- att_tup->attcollation,
- att_tup->attlen,
- (Datum) 0,
- true, /* isnull */
- att_tup->attbyval);
- /* this is to catch a NOT NULL domain constraint */
- new_expr = coerce_to_domain(new_expr,
- InvalidOid, -1,
- att_tup->atttypid,
- COERCION_IMPLICIT,
- COERCE_IMPLICIT_CAST,
- -1,
- false);
+ new_expr = coerce_null_to_domain(att_tup->atttypid,
+ att_tup->atttypmod,
+ att_tup->attcollation,
+ att_tup->attlen,
+ att_tup->attbyval);
}
newList = lappend(newList, new_expr);
}
@@ -1740,6 +1725,14 @@ ApplyRetrieveRule(Query *parsetree,
if (rule->qual != NULL)
elog(ERROR, "cannot handle qualified ON SELECT rule");
+ /* Check if the expansion of non-system views are restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
+ RelationGetRelid(relation) >= FirstNormalObjectId))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system view \"%s\" is restricted",
+ RelationGetRelationName(relation))));
+
if (rt_index == parsetree->resultRelation)
{
/*
@@ -1840,6 +1833,12 @@ ApplyRetrieveRule(Query *parsetree,
rule_action = fireRIRrules(rule_action, activeRIRs);
/*
+ * Make sure the query is marked as having row security if the view query
+ * does.
+ */
+ parsetree->hasRowSecurity |= rule_action->hasRowSecurity;
+
+ /*
* Now, plug the view query in as a subselect, converting the relation's
* original RTE to a subquery RTE.
*/
@@ -1952,7 +1951,7 @@ markQueryForLocking(Query *qry, Node *jtnode,
* the SubLink's subselect link with the possibly-rewritten subquery.
*/
static bool
-fireRIRonSubLink(Node *node, List *activeRIRs)
+fireRIRonSubLink(Node *node, fireRIRonSubLink_context *context)
{
if (node == NULL)
return false;
@@ -1962,7 +1961,13 @@ fireRIRonSubLink(Node *node, List *activeRIRs)
/* Do what we came for */
sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect,
- activeRIRs);
+ context->activeRIRs);
+
+ /*
+ * Remember if any of the sublinks have row security.
+ */
+ context->hasRowSecurity |= ((Query *) sub->subselect)->hasRowSecurity;
+
/* Fall through to process lefthand args of SubLink */
}
@@ -1971,7 +1976,7 @@ fireRIRonSubLink(Node *node, List *activeRIRs)
* subselects of subselects for us.
*/
return expression_tree_walker(node, fireRIRonSubLink,
- (void *) activeRIRs);
+ (void *) context);
}
@@ -2032,6 +2037,13 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
if (rte->rtekind == RTE_SUBQUERY)
{
rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
+
+ /*
+ * While we are here, make sure the query is marked as having row
+ * security if any of its subqueries do.
+ */
+ parsetree->hasRowSecurity |= rte->subquery->hasRowSecurity;
+
continue;
}
@@ -2145,6 +2157,12 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
cte->ctequery = (Node *)
fireRIRrules((Query *) cte->ctequery, activeRIRs);
+
+ /*
+ * While we are here, make sure the query is marked as having row
+ * security if any of its CTEs do.
+ */
+ parsetree->hasRowSecurity |= ((Query *) cte->ctequery)->hasRowSecurity;
}
/*
@@ -2152,9 +2170,22 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
* the rtable and cteList.
*/
if (parsetree->hasSubLinks)
- query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
+ {
+ fireRIRonSubLink_context context;
+
+ context.activeRIRs = activeRIRs;
+ context.hasRowSecurity = false;
+
+ query_tree_walker(parsetree, fireRIRonSubLink, (void *) &context,
QTW_IGNORE_RC_SUBQUERIES);
+ /*
+ * Make sure the query is marked as having row security if any of its
+ * sublinks do.
+ */
+ parsetree->hasRowSecurity |= context.hasRowSecurity;
+ }
+
/*
* Apply any row-level security policies. We do this last because it
* requires special recursion detection if the new quals have sublink
@@ -2193,6 +2224,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
if (hasSubLinks)
{
acquireLocksOnSubLinks_context context;
+ fireRIRonSubLink_context fire_context;
/*
* Recursively process the new quals, checking for infinite
@@ -2223,11 +2255,21 @@ fireRIRrules(Query *parsetree, List *activeRIRs)
* Now that we have the locks on anything added by
* get_row_security_policies, fire any RIR rules for them.
*/
+ fire_context.activeRIRs = activeRIRs;
+ fire_context.hasRowSecurity = false;
+
expression_tree_walker((Node *) securityQuals,
- fireRIRonSubLink, (void *) activeRIRs);
+ fireRIRonSubLink, (void *) &fire_context);
expression_tree_walker((Node *) withCheckOptions,
- fireRIRonSubLink, (void *) activeRIRs);
+ fireRIRonSubLink, (void *) &fire_context);
+
+ /*
+ * We can ignore the value of fire_context.hasRowSecurity
+ * since we only reach this code in cases where hasRowSecurity
+ * is already true.
+ */
+ Assert(hasRowSecurity);
activeRIRs = list_delete_last(activeRIRs);
}
@@ -2963,7 +3005,7 @@ relation_is_updatable(Oid reloid,
*
* This is used with simply-updatable views to map column-permissions sets for
* the view columns onto the matching columns in the underlying base relation.
- * The targetlist is expected to be a list of plain Vars of the underlying
+ * Relevant entries in the targetlist must be plain Vars of the underlying
* relation (as per the checks above in view_query_is_auto_updatable).
*/
static Bitmapset *
@@ -3063,6 +3105,10 @@ rewriteTargetView(Query *parsetree, Relation view)
*/
viewquery = copyObject(get_view_query(view));
+ /* Locate RTE and perminfo describing the view in the outer query */
+ view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);
+ view_perminfo = getRTEPermissionInfo(parsetree->rteperminfos, view_rte);
+
/* The view must be updatable, else fail */
auto_update_detail =
view_query_is_auto_updatable(viewquery,
@@ -3104,18 +3150,35 @@ rewriteTargetView(Query *parsetree, Relation view)
}
}
+ /* Check if the expansion of non-system views are restricted */
+ if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 &&
+ RelationGetRelid(view) >= FirstNormalObjectId))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("access to non-system view \"%s\" is restricted",
+ RelationGetRelationName(view))));
+
/*
- * For INSERT/UPDATE the modified columns must all be updatable. Note that
- * we get the modified columns from the query's targetlist, not from the
- * result RTE's insertedCols and/or updatedCols set, since
- * rewriteTargetListIU may have added additional targetlist entries for
- * view defaults, and these must also be updatable.
+ * For INSERT/UPDATE the modified columns must all be updatable.
*/
if (parsetree->commandType != CMD_DELETE)
{
- Bitmapset *modified_cols = NULL;
+ Bitmapset *modified_cols;
char *non_updatable_col;
+ /*
+ * Compute the set of modified columns as those listed in the result
+ * RTE's insertedCols and/or updatedCols sets plus those that are
+ * targets of the query's targetlist(s). We must consider the query's
+ * targetlist because rewriteTargetListIU may have added additional
+ * targetlist entries for view defaults, and these must also be
+ * updatable. But rewriteTargetListIU can also remove entries if they
+ * are DEFAULT markers and the column's default is NULL, so
+ * considering only the targetlist would also be wrong.
+ */
+ modified_cols = bms_union(view_perminfo->insertedCols,
+ view_perminfo->updatedCols);
+
foreach(lc, parsetree->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(lc);
@@ -3173,9 +3236,6 @@ rewriteTargetView(Query *parsetree, Relation view)
}
}
- /* Locate RTE describing the view in the outer query */
- view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);
-
/*
* If we get here, view_query_is_auto_updatable() has verified that the
* view contains a single base relation.
@@ -3270,10 +3330,7 @@ rewriteTargetView(Query *parsetree, Relation view)
* Note: the original view's RTEPermissionInfo remains in the query's
* rteperminfos so that the executor still performs appropriate
* permissions checks for the query caller's use of the view.
- */
- view_perminfo = getRTEPermissionInfo(parsetree->rteperminfos, view_rte);
-
- /*
+ *
* Disregard the perminfo in viewquery->rteperminfos that the base_rte
* would currently be pointing at, because we'd like it to point now to a
* new one that will be filled below. Must set perminfoindex to 0 to not