Skip to content

Commit d48d2e2

Browse files
committed
Extract make_SAOP_expr() function from match_orclause_to_indexcol()
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>
1 parent ee1ae8b commit d48d2e2

File tree

3 files changed

+88
-60
lines changed

3 files changed

+88
-60
lines changed

src/backend/optimizer/path/indxpath.c

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@
3333
#include "optimizer/paths.h"
3434
#include "optimizer/prep.h"
3535
#include "optimizer/restrictinfo.h"
36-
#include "utils/array.h"
3736
#include "utils/lsyscache.h"
3837
#include "utils/selfuncs.h"
39-
#include "utils/syscache.h"
4038

4139

4240
/* XXX see PartCollMatchesExprColl */
@@ -3304,7 +3302,6 @@ match_orclause_to_indexcol(PlannerInfo *root,
33043302
BoolExpr *orclause = (BoolExpr *) rinfo->orclause;
33053303
Node *indexExpr = NULL;
33063304
List *consts = NIL;
3307-
Node *arrayNode = NULL;
33083305
ScalarArrayOpExpr *saopexpr = NULL;
33093306
Oid matchOpno = InvalidOid;
33103307
IndexClause *iclause;
@@ -3475,63 +3472,8 @@ match_orclause_to_indexcol(PlannerInfo *root,
34753472
return NULL;
34763473
}
34773474

3478-
/*
3479-
* Assemble an array from the list of constants. It seems more profitable
3480-
* to build a const array. But in the presence of other nodes, we don't
3481-
* have a specific value here and must employ an ArrayExpr instead.
3482-
*/
3483-
if (haveNonConst)
3484-
{
3485-
ArrayExpr *arrayExpr = makeNode(ArrayExpr);
3486-
3487-
/* array_collid will be set by parse_collate.c */
3488-
arrayExpr->element_typeid = consttype;
3489-
arrayExpr->array_typeid = arraytype;
3490-
arrayExpr->multidims = false;
3491-
arrayExpr->elements = consts;
3492-
arrayExpr->location = -1;
3493-
3494-
arrayNode = (Node *) arrayExpr;
3495-
}
3496-
else
3497-
{
3498-
int16 typlen;
3499-
bool typbyval;
3500-
char typalign;
3501-
Datum *elems;
3502-
int i = 0;
3503-
ArrayType *arrayConst;
3504-
3505-
get_typlenbyvalalign(consttype, &typlen, &typbyval, &typalign);
3506-
3507-
elems = (Datum *) palloc(sizeof(Datum) * list_length(consts));
3508-
foreach_node(Const, value, consts)
3509-
{
3510-
Assert(!value->constisnull);
3511-
3512-
elems[i++] = value->constvalue;
3513-
}
3514-
3515-
arrayConst = construct_array(elems, i, consttype,
3516-
typlen, typbyval, typalign);
3517-
arrayNode = (Node *) makeConst(arraytype, -1, inputcollid,
3518-
-1, PointerGetDatum(arrayConst),
3519-
false, false);
3520-
3521-
pfree(elems);
3522-
list_free(consts);
3523-
}
3524-
3525-
/* Build the SAOP expression node */
3526-
saopexpr = makeNode(ScalarArrayOpExpr);
3527-
saopexpr->opno = matchOpno;
3528-
saopexpr->opfuncid = get_opcode(matchOpno);
3529-
saopexpr->hashfuncid = InvalidOid;
3530-
saopexpr->negfuncid = InvalidOid;
3531-
saopexpr->useOr = true;
3532-
saopexpr->inputcollid = inputcollid;
3533-
saopexpr->args = list_make2(indexExpr, arrayNode);
3534-
saopexpr->location = -1;
3475+
saopexpr = make_SAOP_expr(matchOpno, indexExpr, consttype, inputcollid,
3476+
inputcollid, consts, haveNonConst);
35353477

35363478
/*
35373479
* Finally, build an IndexClause based on the SAOP node. Use

src/backend/optimizer/util/clauses.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
#include "optimizer/planmain.h"
4141
#include "parser/analyze.h"
4242
#include "parser/parse_coerce.h"
43+
#include "parser/parse_collate.h"
4344
#include "parser/parse_func.h"
45+
#include "parser/parse_oper.h"
4446
#include "rewrite/rewriteHandler.h"
4547
#include "rewrite/rewriteManip.h"
4648
#include "tcop/tcopprot.h"
@@ -5439,3 +5441,82 @@ pull_paramids_walker(Node *node, Bitmapset **context)
54395441
}
54405442
return expression_tree_walker(node, pull_paramids_walker, context);
54415443
}
5444+
5445+
/*
5446+
* Build ScalarArrayOpExpr on top of 'exprs.' 'haveNonConst' indicates
5447+
* whether at least one of the expressions is not Const. When it's false,
5448+
* the array constant is built directly; otherwise, we have to build a child
5449+
* ArrayExpr. The 'exprs' list gets freed if not directly used in the output
5450+
* expression tree.
5451+
*/
5452+
ScalarArrayOpExpr *
5453+
make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid,
5454+
Oid inputcollid, List *exprs, bool haveNonConst)
5455+
{
5456+
Node *arrayNode = NULL;
5457+
ScalarArrayOpExpr *saopexpr = NULL;
5458+
Oid arraytype = get_array_type(coltype);
5459+
5460+
if (!OidIsValid(arraytype))
5461+
return NULL;
5462+
5463+
/*
5464+
* Assemble an array from the list of constants. It seems more profitable
5465+
* to build a const array. But in the presence of other nodes, we don't
5466+
* have a specific value here and must employ an ArrayExpr instead.
5467+
*/
5468+
if (haveNonConst)
5469+
{
5470+
ArrayExpr *arrayExpr = makeNode(ArrayExpr);
5471+
5472+
/* array_collid will be set by parse_collate.c */
5473+
arrayExpr->element_typeid = coltype;
5474+
arrayExpr->array_typeid = arraytype;
5475+
arrayExpr->multidims = false;
5476+
arrayExpr->elements = exprs;
5477+
arrayExpr->location = -1;
5478+
5479+
arrayNode = (Node *) arrayExpr;
5480+
}
5481+
else
5482+
{
5483+
int16 typlen;
5484+
bool typbyval;
5485+
char typalign;
5486+
Datum *elems;
5487+
int i = 0;
5488+
ArrayType *arrayConst;
5489+
5490+
get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign);
5491+
5492+
elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs));
5493+
foreach_node(Const, value, exprs)
5494+
{
5495+
Assert(!value->constisnull);
5496+
5497+
elems[i++] = value->constvalue;
5498+
}
5499+
5500+
arrayConst = construct_array(elems, i, coltype,
5501+
typlen, typbyval, typalign);
5502+
arrayNode = (Node *) makeConst(arraytype, -1, arraycollid,
5503+
-1, PointerGetDatum(arrayConst),
5504+
false, false);
5505+
5506+
pfree(elems);
5507+
list_free(exprs);
5508+
}
5509+
5510+
/* Build the SAOP expression node */
5511+
saopexpr = makeNode(ScalarArrayOpExpr);
5512+
saopexpr->opno = oper;
5513+
saopexpr->opfuncid = get_opcode(oper);
5514+
saopexpr->hashfuncid = InvalidOid;
5515+
saopexpr->negfuncid = InvalidOid;
5516+
saopexpr->useOr = true;
5517+
saopexpr->inputcollid = inputcollid;
5518+
saopexpr->args = list_make2(leftexpr, arrayNode);
5519+
saopexpr->location = -1;
5520+
5521+
return saopexpr;
5522+
}

src/include/optimizer/optimizer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ extern List *expand_function_arguments(List *args, bool include_out_arguments,
158158
Oid result_type,
159159
struct HeapTupleData *func_tuple);
160160

161+
extern ScalarArrayOpExpr *make_SAOP_expr(Oid oper, Node *leftexpr,
162+
Oid coltype, Oid arraycollid,
163+
Oid inputcollid, List *exprs,
164+
bool haveNonConst);
165+
161166
/* in util/predtest.c: */
162167

163168
extern bool predicate_implied_by(List *predicate_list, List *clause_list,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy