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)