diff options
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 536ef187f9b..9965df1b965 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -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; +} |