mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Fix squashing algorithm for query texts
The algorithm to squash lists of constants added by commit 62d712ecfd
was a bit too simplistic; we wanted to avoid adding unnecessary
complexity, but cases like direct function calls of typecasting
functions (and others) were missed, and bogus SQL syntax was being shown
in pg_stat_statements normalized query text field. To fix normalization
for those cases, we need the parser to transmit information about were
each list of constant values starts and ends, so add that to a couple of
nodes. Also add a few more test cases to make sure we're doing the
right thing.
The patch initially submitted by Sami added a new private struct in
gram.y to carry the start/end information for A_Expr, but I (Álvaro)
decided that a better fix was to remove the parser indirection via the
in_expr production, and instead create separate components in the a_expr
rule. I'm surprised that this works and doesn't require more changes,
but I assume (without checking) that the grammar used to be more complex
and got simplified at some point.
Bump catversion.
Author: Sami Imseih <samimseih@gmail.com>
Author: Dmitry Dolgov <9erthalion6@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAA5RZ0tRXoPG2y6bMgBCWNDt0Tn=unRerbzYM=oW0syi1=C1OA@mail.gmail.com
This commit is contained in:
@ -183,7 +183,7 @@ static void doNegateFloat(Float *v);
|
||||
static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location);
|
||||
static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location);
|
||||
static Node *makeNotExpr(Node *expr, int location);
|
||||
static Node *makeAArrayExpr(List *elements, int location);
|
||||
static Node *makeAArrayExpr(List *elements, int location, int end_location);
|
||||
static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod,
|
||||
int location);
|
||||
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
|
||||
@ -522,7 +522,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
%type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem
|
||||
%type <node> def_arg columnElem where_clause where_or_current_clause
|
||||
a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound
|
||||
columnref in_expr having_clause func_table xmltable array_expr
|
||||
columnref having_clause func_table xmltable array_expr
|
||||
OptWhereClause operator_def_arg
|
||||
%type <list> opt_column_and_period_list
|
||||
%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
|
||||
@ -15264,49 +15264,50 @@ a_expr: c_expr { $$ = $1; }
|
||||
(Node *) list_make2($5, $7),
|
||||
@2);
|
||||
}
|
||||
| a_expr IN_P in_expr
|
||||
| a_expr IN_P select_with_parens
|
||||
{
|
||||
/* in_expr returns a SubLink or a list of a_exprs */
|
||||
if (IsA($3, SubLink))
|
||||
{
|
||||
/* generate foo = ANY (subquery) */
|
||||
SubLink *n = (SubLink *) $3;
|
||||
/* generate foo = ANY (subquery) */
|
||||
SubLink *n = makeNode(SubLink);
|
||||
|
||||
n->subLinkType = ANY_SUBLINK;
|
||||
n->subLinkId = 0;
|
||||
n->testexpr = $1;
|
||||
n->operName = NIL; /* show it's IN not = ANY */
|
||||
n->location = @2;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* generate scalar IN expression */
|
||||
$$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2);
|
||||
}
|
||||
n->subselect = $3;
|
||||
n->subLinkType = ANY_SUBLINK;
|
||||
n->subLinkId = 0;
|
||||
n->testexpr = $1;
|
||||
n->operName = NIL; /* show it's IN not = ANY */
|
||||
n->location = @2;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| a_expr NOT_LA IN_P in_expr %prec NOT_LA
|
||||
| a_expr IN_P '(' expr_list ')'
|
||||
{
|
||||
/* in_expr returns a SubLink or a list of a_exprs */
|
||||
if (IsA($4, SubLink))
|
||||
{
|
||||
/* generate NOT (foo = ANY (subquery)) */
|
||||
/* Make an = ANY node */
|
||||
SubLink *n = (SubLink *) $4;
|
||||
/* generate scalar IN expression */
|
||||
A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "=", $1, (Node *) $4, @2);
|
||||
|
||||
n->subLinkType = ANY_SUBLINK;
|
||||
n->subLinkId = 0;
|
||||
n->testexpr = $1;
|
||||
n->operName = NIL; /* show it's IN not = ANY */
|
||||
n->location = @2;
|
||||
/* Stick a NOT on top; must have same parse location */
|
||||
$$ = makeNotExpr((Node *) n, @2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* generate scalar NOT IN expression */
|
||||
$$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2);
|
||||
}
|
||||
n->rexpr_list_start = @3;
|
||||
n->rexpr_list_end = @5;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| a_expr NOT_LA IN_P select_with_parens %prec NOT_LA
|
||||
{
|
||||
/* generate NOT (foo = ANY (subquery)) */
|
||||
SubLink *n = makeNode(SubLink);
|
||||
|
||||
n->subselect = $4;
|
||||
n->subLinkType = ANY_SUBLINK;
|
||||
n->subLinkId = 0;
|
||||
n->testexpr = $1;
|
||||
n->operName = NIL; /* show it's IN not = ANY */
|
||||
n->location = @2;
|
||||
/* Stick a NOT on top; must have same parse location */
|
||||
$$ = makeNotExpr((Node *) n, @2);
|
||||
}
|
||||
| a_expr NOT_LA IN_P '(' expr_list ')'
|
||||
{
|
||||
/* generate scalar NOT IN expression */
|
||||
A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "<>", $1, (Node *) $5, @2);
|
||||
|
||||
n->rexpr_list_start = @4;
|
||||
n->rexpr_list_end = @6;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| a_expr subquery_Op sub_type select_with_parens %prec Op
|
||||
{
|
||||
@ -16741,15 +16742,15 @@ type_list: Typename { $$ = list_make1($1); }
|
||||
|
||||
array_expr: '[' expr_list ']'
|
||||
{
|
||||
$$ = makeAArrayExpr($2, @1);
|
||||
$$ = makeAArrayExpr($2, @1, @3);
|
||||
}
|
||||
| '[' array_expr_list ']'
|
||||
{
|
||||
$$ = makeAArrayExpr($2, @1);
|
||||
$$ = makeAArrayExpr($2, @1, @3);
|
||||
}
|
||||
| '[' ']'
|
||||
{
|
||||
$$ = makeAArrayExpr(NIL, @1);
|
||||
$$ = makeAArrayExpr(NIL, @1, @2);
|
||||
}
|
||||
;
|
||||
|
||||
@ -16871,17 +16872,6 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); }
|
||||
| expr_list { $$ = $1; }
|
||||
;
|
||||
|
||||
in_expr: select_with_parens
|
||||
{
|
||||
SubLink *n = makeNode(SubLink);
|
||||
|
||||
n->subselect = $1;
|
||||
/* other fields will be filled later */
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| '(' expr_list ')' { $$ = (Node *) $2; }
|
||||
;
|
||||
|
||||
/*
|
||||
* Define SQL-style CASE clause.
|
||||
* - Full specification
|
||||
@ -19232,12 +19222,14 @@ makeNotExpr(Node *expr, int location)
|
||||
}
|
||||
|
||||
static Node *
|
||||
makeAArrayExpr(List *elements, int location)
|
||||
makeAArrayExpr(List *elements, int location, int location_end)
|
||||
{
|
||||
A_ArrayExpr *n = makeNode(A_ArrayExpr);
|
||||
|
||||
n->elements = elements;
|
||||
n->location = location;
|
||||
n->list_start = location;
|
||||
n->list_end = location_end;
|
||||
return (Node *) n;
|
||||
}
|
||||
|
||||
|
@ -1223,6 +1223,8 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
|
||||
newa->element_typeid = scalar_type;
|
||||
newa->elements = aexprs;
|
||||
newa->multidims = false;
|
||||
newa->list_start = a->rexpr_list_start;
|
||||
newa->list_end = a->rexpr_list_end;
|
||||
newa->location = -1;
|
||||
|
||||
result = (Node *) make_scalar_array_op(pstate,
|
||||
@ -2165,6 +2167,8 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
|
||||
/* array_collid will be set by parse_collate.c */
|
||||
newa->element_typeid = element_type;
|
||||
newa->elements = newcoercedelems;
|
||||
newa->list_start = a->list_start;
|
||||
newa->list_end = a->list_end;
|
||||
newa->location = a->location;
|
||||
|
||||
return (Node *) newa;
|
||||
|
Reference in New Issue
Block a user