0001-Reduce-ArrayExpr-into-const-array.patch
application/octet-stream
Filename: 0001-Reduce-ArrayExpr-into-const-array.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: Reduce ArrayExpr into const array
| File | + | − |
|---|---|---|
| src/backend/parser/parse_expr.c | 59 | 6 |
From 27973d144f592249e2b8d9a548be3d563f58b737 Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Mon, 10 Aug 2020 18:27:28 +0200
Subject: [PATCH] Reduce ArrayExpr into const array
In case if ArrayExpr generated for ScalarArrayOpExpr contains only
consts, reduce it to a const array. One of the advantages of that is
pg_stat_statements will consider this kind of array as a single entity
no matter how many elements are there, which will partially solve the
duplication problem (when the same query mentioned in pg_stat_statements
multiple times due to different number of elements in e.g. IN condition)
---
src/backend/parser/parse_expr.c | 65 ++++++++++++++++++++++++++++++---
1 file changed, 59 insertions(+), 6 deletions(-)
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index f69976cc8c..6aea674810 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -32,6 +32,7 @@
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_type.h"
+#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/lsyscache.h"
@@ -1301,6 +1302,7 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
*/
List *aexprs;
ArrayExpr *newa;
+ bool all_const = true;
aexprs = NIL;
foreach(l, rnonvars)
@@ -1310,6 +1312,10 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
rexpr = coerce_to_common_type(pstate, rexpr,
scalar_type,
"IN");
+
+ if (!IsA(rexpr, Const))
+ all_const = false;
+
aexprs = lappend(aexprs, rexpr);
}
newa = makeNode(ArrayExpr);
@@ -1320,12 +1326,59 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
newa->multidims = false;
newa->location = -1;
- result = (Node *) make_scalar_array_op(pstate,
- a->name,
- useOr,
- lexpr,
- (Node *) newa,
- a->location);
+ /* if all elements are const reduce ArrayExpr to a const as well */
+ if (all_const)
+ {
+ ArrayType *const_array;
+ Datum *elems = (Datum *) palloc(sizeof(Datum) * aexprs->length);
+ bool *nulls = (bool *) palloc(sizeof(bool) * aexprs->length);
+
+ int dims[1];
+ int lbs[1];
+
+ bool elembyval;
+ int16 elemlen;
+ char elemalign;
+ int i = 0;
+
+ foreach(l, aexprs)
+ {
+ Const *expr = (Const *) lfirst(l);
+
+ elems[i] = expr->constvalue;
+ nulls[i] = expr->constisnull;
+ i++;
+ }
+
+ /* ArrayExpr would have only one dimention */
+ dims[0] = aexprs->length;
+ lbs[0] = 1;
+
+ get_typlenbyvalalign(scalar_type, &elemlen,
+ &elembyval, &elemalign);
+ const_array = construct_md_array(elems, nulls, 1, dims, lbs,
+ scalar_type, elemlen,
+ elembyval, elemalign);
+
+ result = (Node *) makeConst(array_type, -1,
+ newa->array_collid, -1,
+ PointerGetDatum(const_array),
+ false, false);
+
+ result = (Node *) make_scalar_array_op(pstate,
+ a->name,
+ useOr,
+ lexpr,
+ (Node *) result,
+ a->location);
+ }
+ else
+ result = (Node *) make_scalar_array_op(pstate,
+ a->name,
+ useOr,
+ lexpr,
+ (Node *) newa,
+ a->location);
/* Consider only the Vars (if any) in the loop below */
rexprs = rvars;
--
2.21.0