Hi, While debugging the pull-up sublink codes, I noticed the convert_VALUES_to_ANY(). The function is to convert "where colX in VALUES(xxx)" into SAOP. It firstly scans the values_list to make sure no volatile function is in this list, then it scans this values_list again to check that it only includes Const items.
We can merge the two scans into one. This can reduce the time complexity from 2O(n) to O(n). Also, add a brace for better/more consistent style in the attached patch. -- Thanks, Tender Wang
From 0eeb7487ba5bdacd260987514cd0a77eb8c88eaa Mon Sep 17 00:00:00 2001 From: Tender Wang <tndrw...@gmail.com> Date: Sun, 27 Jul 2025 15:26:20 +0800 Subject: [PATCH] A little cosmetic to convert_VALUES_to_ANY(). In original logic, we have to do two passes iteration over the values_lists. One is to check if have volatile functions, the other one is to check if have no Const. We can merge above two iterations into one. Also add a brace for better/more consistent style. --- src/backend/optimizer/plan/subselect.c | 9 ++++++--- src/backend/optimizer/prep/prepjointree.c | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index d71ed958e31..7a275f430f2 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -1255,11 +1255,10 @@ convert_VALUES_to_ANY(PlannerInfo *root, Node *testexpr, Query *values) /* * Also, check that only RTE corresponds to VALUES; the list of values has - * at least two items and no volatile functions. + * at least two items. */ if (rte->rtekind != RTE_VALUES || - list_length(rte->values_lists) < 2 || - contain_volatile_functions((Node *) rte->values_lists)) + list_length(rte->values_lists) < 2) return NULL; foreach(lc, rte->values_lists) @@ -1267,6 +1266,10 @@ convert_VALUES_to_ANY(PlannerInfo *root, Node *testexpr, Query *values) List *elem = lfirst(lc); Node *value = linitial(elem); + /* Must have no volatile functions */ + if (contain_volatile_functions(value)) + return NULL; + /* * Prepare an evaluation of the right side of the operator with * substitution of the given value. diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 35e8d3c183b..d9908d16d79 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -848,13 +848,13 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, if ((saop = convert_VALUES_to_ANY(root, sublink->testexpr, (Query *) sublink->subselect)) != NULL) - + { /* * The VALUES sequence was simplified. Nothing more to do * here. */ return (Node *) saop; - + } if ((j = convert_ANY_sublink_to_join(root, sublink, available_rels1)) != NULL) { -- 2.34.1