mirror of
https://github.com/postgres/postgres.git
synced 2025-06-05 23:56:58 +03:00
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>
This commit is contained in:
parent
ee1ae8b99f
commit
d48d2e2dc8
@ -33,10 +33,8 @@
|
||||
#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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user