]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Extract make_SAOP_expr() function from match_orclause_to_indexcol()
authorAlexander Korotkov <akorotkov@postgresql.org>
Fri, 4 Apr 2025 13:01:28 +0000 (16:01 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Fri, 4 Apr 2025 13:01:28 +0000 (16:01 +0300)
This commit extracts the code to generate ScalarArrayOpExpr on top of the list
of expressions from match_orclause_to_indexcol() into a separate function
make_SAOP_expr().  This function was extracted to be used in optimization for
conversion of 'x IN (VALUES ...)' to 'x = ANY ...'.  make_SAOP_expr() is
placed in clauses.c file as only two additional headers were needed there
compared with other places.

Discussion: https://postgr.es/m/0184212d-1248-4f1f-a42d-f5cb1c1976d2%40tantorlabs.com
Author: Alena Rybakina <a.rybakina@postgrespro.ru>
Author: Andrei Lepikhov <lepihov@gmail.com>
Reviewed-by: Ivan Kush <ivan.kush@tantorlabs.com>
Reviewed-by: Alexander Korotkov <aekorotkov@gmail.com>
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/util/clauses.c
src/include/optimizer/optimizer.h

index d8865f8c0c6fe47cc3fd693e2f5c35dfe8f714a6..4cabb358abcc824571d02ac4a2189c4a4a332f15 100644 (file)
 #include "optimizer/paths.h"
 #include "optimizer/prep.h"
 #include "optimizer/restrictinfo.h"
-#include "utils/array.h"
 #include "utils/lsyscache.h"
 #include "utils/selfuncs.h"
-#include "utils/syscache.h"
 
 
 /* XXX see PartCollMatchesExprColl */
@@ -3304,7 +3302,6 @@ match_orclause_to_indexcol(PlannerInfo *root,
        BoolExpr   *orclause = (BoolExpr *) rinfo->orclause;
        Node       *indexExpr = NULL;
        List       *consts = NIL;
-       Node       *arrayNode = NULL;
        ScalarArrayOpExpr *saopexpr = NULL;
        Oid                     matchOpno = InvalidOid;
        IndexClause *iclause;
@@ -3475,63 +3472,8 @@ match_orclause_to_indexcol(PlannerInfo *root,
                return NULL;
        }
 
-       /*
-        * Assemble an array from the list of constants.  It seems more profitable
-        * to build a const array.  But in the presence of other nodes, we don't
-        * have a specific value here and must employ an ArrayExpr instead.
-        */
-       if (haveNonConst)
-       {
-               ArrayExpr  *arrayExpr = makeNode(ArrayExpr);
-
-               /* array_collid will be set by parse_collate.c */
-               arrayExpr->element_typeid = consttype;
-               arrayExpr->array_typeid = arraytype;
-               arrayExpr->multidims = false;
-               arrayExpr->elements = consts;
-               arrayExpr->location = -1;
-
-               arrayNode = (Node *) arrayExpr;
-       }
-       else
-       {
-               int16           typlen;
-               bool            typbyval;
-               char            typalign;
-               Datum      *elems;
-               int                     i = 0;
-               ArrayType  *arrayConst;
-
-               get_typlenbyvalalign(consttype, &typlen, &typbyval, &typalign);
-
-               elems = (Datum *) palloc(sizeof(Datum) * list_length(consts));
-               foreach_node(Const, value, consts)
-               {
-                       Assert(!value->constisnull);
-
-                       elems[i++] = value->constvalue;
-               }
-
-               arrayConst = construct_array(elems, i, consttype,
-                                                                        typlen, typbyval, typalign);
-               arrayNode = (Node *) makeConst(arraytype, -1, inputcollid,
-                                                                          -1, PointerGetDatum(arrayConst),
-                                                                          false, false);
-
-               pfree(elems);
-               list_free(consts);
-       }
-
-       /* Build the SAOP expression node */
-       saopexpr = makeNode(ScalarArrayOpExpr);
-       saopexpr->opno = matchOpno;
-       saopexpr->opfuncid = get_opcode(matchOpno);
-       saopexpr->hashfuncid = InvalidOid;
-       saopexpr->negfuncid = InvalidOid;
-       saopexpr->useOr = true;
-       saopexpr->inputcollid = inputcollid;
-       saopexpr->args = list_make2(indexExpr, arrayNode);
-       saopexpr->location = -1;
+       saopexpr = make_SAOP_expr(matchOpno, indexExpr, consttype, inputcollid,
+                                                         inputcollid, consts, haveNonConst);
 
        /*
         * Finally, build an IndexClause based on the SAOP node.  Use
index 536ef187f9bd5f3619edf6155bd09378586d3f51..9965df1b9653913e524d6e5aae3bafd8d0be2cb8 100644 (file)
@@ -40,7 +40,9 @@
 #include "optimizer/planmain.h"
 #include "parser/analyze.h"
 #include "parser/parse_coerce.h"
+#include "parser/parse_collate.h"
 #include "parser/parse_func.h"
+#include "parser/parse_oper.h"
 #include "rewrite/rewriteHandler.h"
 #include "rewrite/rewriteManip.h"
 #include "tcop/tcopprot.h"
@@ -5439,3 +5441,82 @@ pull_paramids_walker(Node *node, Bitmapset **context)
        }
        return expression_tree_walker(node, pull_paramids_walker, context);
 }
+
+/*
+ * Build ScalarArrayOpExpr on top of 'exprs.' 'haveNonConst' indicates
+ * whether at least one of the expressions is not Const.  When it's false,
+ * the array constant is built directly; otherwise, we have to build a child
+ * ArrayExpr. The 'exprs' list gets freed if not directly used in the output
+ * expression tree.
+ */
+ScalarArrayOpExpr *
+make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid,
+                          Oid inputcollid, List *exprs, bool haveNonConst)
+{
+       Node       *arrayNode = NULL;
+       ScalarArrayOpExpr *saopexpr = NULL;
+       Oid                     arraytype = get_array_type(coltype);
+
+       if (!OidIsValid(arraytype))
+               return NULL;
+
+       /*
+        * Assemble an array from the list of constants.  It seems more profitable
+        * to build a const array.  But in the presence of other nodes, we don't
+        * have a specific value here and must employ an ArrayExpr instead.
+        */
+       if (haveNonConst)
+       {
+               ArrayExpr  *arrayExpr = makeNode(ArrayExpr);
+
+               /* array_collid will be set by parse_collate.c */
+               arrayExpr->element_typeid = coltype;
+               arrayExpr->array_typeid = arraytype;
+               arrayExpr->multidims = false;
+               arrayExpr->elements = exprs;
+               arrayExpr->location = -1;
+
+               arrayNode = (Node *) arrayExpr;
+       }
+       else
+       {
+               int16           typlen;
+               bool            typbyval;
+               char            typalign;
+               Datum      *elems;
+               int                     i = 0;
+               ArrayType  *arrayConst;
+
+               get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
+
+               elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs));
+               foreach_node(Const, value, exprs)
+               {
+                       Assert(!value->constisnull);
+
+                       elems[i++] = value->constvalue;
+               }
+
+               arrayConst = construct_array(elems, i, coltype,
+                                                                        typlen, typbyval, typalign);
+               arrayNode = (Node *) makeConst(arraytype, -1, arraycollid,
+                                                                          -1, PointerGetDatum(arrayConst),
+                                                                          false, false);
+
+               pfree(elems);
+               list_free(exprs);
+       }
+
+       /* Build the SAOP expression node */
+       saopexpr = makeNode(ScalarArrayOpExpr);
+       saopexpr->opno = oper;
+       saopexpr->opfuncid = get_opcode(oper);
+       saopexpr->hashfuncid = InvalidOid;
+       saopexpr->negfuncid = InvalidOid;
+       saopexpr->useOr = true;
+       saopexpr->inputcollid = inputcollid;
+       saopexpr->args = list_make2(leftexpr, arrayNode);
+       saopexpr->location = -1;
+
+       return saopexpr;
+}
index 78e05d88c8ec88b49a1ae301adebecb95a4602ec..546828b54bd275c3e0761c3cf88dbca7e8f33984 100644 (file)
@@ -158,6 +158,11 @@ extern List *expand_function_arguments(List *args, bool include_out_arguments,
                                                                           Oid result_type,
                                                                           struct HeapTupleData *func_tuple);
 
+extern ScalarArrayOpExpr *make_SAOP_expr(Oid oper, Node *leftexpr,
+                                                                                Oid coltype, Oid arraycollid,
+                                                                                Oid inputcollid, List *exprs,
+                                                                                bool haveNonConst);
+
 /* in util/predtest.c: */
 
 extern bool predicate_implied_by(List *predicate_list, List *clause_list,