1997-11-25 23:07:18 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* parse_expr.c
|
|
|
|
* handle expressions in parser
|
|
|
|
*
|
2017-01-03 19:48:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1997-11-25 23:07:18 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/parser/parse_expr.c
|
1997-11-25 23:07:18 +01:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
1999-08-26 01:21:43 +02:00
|
|
|
|
2006-07-13 18:49:20 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2003-06-27 19:07:03 +02:00
|
|
|
#include "commands/dbcommands.h"
|
2002-03-21 17:02:16 +01:00
|
|
|
#include "miscadmin.h"
|
1997-11-25 23:07:18 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
2008-08-26 00:42:34 +02:00
|
|
|
#include "nodes/nodeFuncs.h"
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
#include "optimizer/tlist.h"
|
2008-10-25 19:19:09 +02:00
|
|
|
#include "optimizer/var.h"
|
1998-01-19 06:06:41 +01:00
|
|
|
#include "parser/analyze.h"
|
2013-07-17 02:15:36 +02:00
|
|
|
#include "parser/parse_clause.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "parser/parse_coerce.h"
|
2011-03-20 01:29:08 +01:00
|
|
|
#include "parser/parse_collate.h"
|
1997-11-25 23:07:18 +01:00
|
|
|
#include "parser/parse_expr.h"
|
|
|
|
#include "parser/parse_func.h"
|
1999-08-26 01:21:43 +02:00
|
|
|
#include "parser/parse_oper.h"
|
1997-11-25 23:07:18 +01:00
|
|
|
#include "parser/parse_relation.h"
|
2006-06-26 19:24:41 +02:00
|
|
|
#include "parser/parse_target.h"
|
2000-06-15 05:33:12 +02:00
|
|
|
#include "parser/parse_type.h"
|
Support GROUPING SETS, CUBE and ROLLUP.
This SQL standard functionality allows to aggregate data by different
GROUP BY clauses at once. Each grouping set returns rows with columns
grouped by in other sets set to NULL.
This could previously be achieved by doing each grouping as a separate
query, conjoined by UNION ALLs. Besides being considerably more concise,
grouping sets will in many cases be faster, requiring only one scan over
the underlying data.
The current implementation of grouping sets only supports using sorting
for input. Individual sets that share a sort order are computed in one
pass. If there are sets that don't share a sort order, additional sort &
aggregation steps are performed. These additional passes are sourced by
the previous sort step; thus avoiding repeated scans of the source data.
The code is structured in a way that adding support for purely using
hash aggregation or a mix of hashing and sorting is possible. Sorting
was chosen to be supported first, as it is the most generic method of
implementation.
Instead of, as in an earlier versions of the patch, representing the
chain of sort and aggregation steps as full blown planner and executor
nodes, all but the first sort are performed inside the aggregation node
itself. This avoids the need to do some unusual gymnastics to handle
having to return aggregated and non-aggregated tuples from underlying
nodes, as well as having to shut down underlying nodes early to limit
memory usage. The optimizer still builds Sort/Agg node to describe each
phase, but they're not part of the plan tree, but instead additional
data for the aggregation node. They're a convenient and preexisting way
to describe aggregation and sorting. The first (and possibly only) sort
step is still performed as a separate execution step. That retains
similarity with existing group by plans, makes rescans fairly simple,
avoids very deep plans (leading to slow explains) and easily allows to
avoid the sorting step if the underlying data is sorted by other means.
A somewhat ugly side of this patch is having to deal with a grammar
ambiguity between the new CUBE keyword and the cube extension/functions
named cube (and rollup). To avoid breaking existing deployments of the
cube extension it has not been renamed, neither has cube been made a
reserved keyword. Instead precedence hacking is used to make GROUP BY
cube(..) refer to the CUBE grouping sets feature, and not the function
cube(). To actually group by a function cube(), unlikely as that might
be, the function name has to be quoted.
Needs a catversion bump because stored rules may change.
Author: Andrew Gierth and Atri Sharma, with contributions from Andres Freund
Reviewed-By: Andres Freund, Noah Misch, Tom Lane, Svenne Krap, Tomas
Vondra, Erik Rijkers, Marti Raudsepp, Pavel Stehule
Discussion: CAOeZVidmVRe2jU6aMk_5qkxnB7dfmPROzM7Ur8JPW5j8Y5X-Lw@mail.gmail.com
2015-05-16 03:40:59 +02:00
|
|
|
#include "parser/parse_agg.h"
|
1997-11-25 23:07:18 +01:00
|
|
|
#include "utils/builtins.h"
|
2016-08-17 02:33:01 +02:00
|
|
|
#include "utils/date.h"
|
2002-05-13 01:43:04 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2016-08-17 02:33:01 +02:00
|
|
|
#include "utils/timestamp.h"
|
2006-12-21 17:05:16 +01:00
|
|
|
#include "utils/xml.h"
|
2005-12-28 02:30:02 +01:00
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
/* GUC parameters */
|
|
|
|
bool operator_precedence_warning = false;
|
2001-09-20 16:20:28 +02:00
|
|
|
bool Transform_null_equals = false;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
/*
|
|
|
|
* Node-type groups for operator precedence warnings
|
|
|
|
* We use zero for everything not otherwise classified
|
|
|
|
*/
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
#define PREC_GROUP_POSTFIX_IS 1 /* postfix IS tests (NullTest, etc) */
|
|
|
|
#define PREC_GROUP_INFIX_IS 2 /* infix IS (IS DISTINCT FROM, etc) */
|
|
|
|
#define PREC_GROUP_LESS 3 /* < > */
|
|
|
|
#define PREC_GROUP_EQUAL 4 /* = */
|
|
|
|
#define PREC_GROUP_LESS_EQUAL 5 /* <= >= <> */
|
|
|
|
#define PREC_GROUP_LIKE 6 /* LIKE ILIKE SIMILAR */
|
|
|
|
#define PREC_GROUP_BETWEEN 7 /* BETWEEN */
|
|
|
|
#define PREC_GROUP_IN 8 /* IN */
|
|
|
|
#define PREC_GROUP_NOT_LIKE 9 /* NOT LIKE/ILIKE/SIMILAR */
|
|
|
|
#define PREC_GROUP_NOT_BETWEEN 10 /* NOT BETWEEN */
|
|
|
|
#define PREC_GROUP_NOT_IN 11 /* NOT IN */
|
|
|
|
#define PREC_GROUP_POSTFIX_OP 12 /* generic postfix operators */
|
|
|
|
#define PREC_GROUP_INFIX_OP 13 /* generic infix operators */
|
|
|
|
#define PREC_GROUP_PREFIX_OP 14 /* generic prefix operators */
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Map precedence groupings to old precedence ordering
|
|
|
|
*
|
|
|
|
* Old precedence order:
|
|
|
|
* 1. NOT
|
|
|
|
* 2. =
|
|
|
|
* 3. < >
|
|
|
|
* 4. LIKE ILIKE SIMILAR
|
|
|
|
* 5. BETWEEN
|
|
|
|
* 6. IN
|
|
|
|
* 7. generic postfix Op
|
|
|
|
* 8. generic Op, including <= => <>
|
|
|
|
* 9. generic prefix Op
|
|
|
|
* 10. IS tests (NullTest, BooleanTest, etc)
|
|
|
|
*
|
|
|
|
* NOT BETWEEN etc map to BETWEEN etc when considered as being on the left,
|
|
|
|
* but to NOT when considered as being on the right, because of the buggy
|
|
|
|
* precedence handling of those productions in the old grammar.
|
|
|
|
*/
|
|
|
|
static const int oldprecedence_l[] = {
|
|
|
|
0, 10, 10, 3, 2, 8, 4, 5, 6, 4, 5, 6, 7, 8, 9
|
|
|
|
};
|
|
|
|
static const int oldprecedence_r[] = {
|
|
|
|
0, 10, 10, 3, 2, 8, 4, 5, 6, 1, 1, 1, 7, 8, 9
|
|
|
|
};
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
static Node *transformExprRecurse(ParseState *pstate, Node *expr);
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *transformParamRef(ParseState *pstate, ParamRef *pref);
|
|
|
|
static Node *transformAExprOp(ParseState *pstate, A_Expr *a);
|
|
|
|
static Node *transformAExprOpAny(ParseState *pstate, A_Expr *a);
|
|
|
|
static Node *transformAExprOpAll(ParseState *pstate, A_Expr *a);
|
|
|
|
static Node *transformAExprDistinct(ParseState *pstate, A_Expr *a);
|
|
|
|
static Node *transformAExprNullIf(ParseState *pstate, A_Expr *a);
|
|
|
|
static Node *transformAExprOf(ParseState *pstate, A_Expr *a);
|
2005-11-28 05:35:32 +01:00
|
|
|
static Node *transformAExprIn(ParseState *pstate, A_Expr *a);
|
2015-02-22 19:57:56 +01:00
|
|
|
static Node *transformAExprBetween(ParseState *pstate, A_Expr *a);
|
2014-06-16 21:55:05 +02:00
|
|
|
static Node *transformBoolExpr(ParseState *pstate, BoolExpr *a);
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *transformFuncCall(ParseState *pstate, FuncCall *fn);
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
static Node *transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref);
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *transformCaseExpr(ParseState *pstate, CaseExpr *c);
|
|
|
|
static Node *transformSubLink(ParseState *pstate, SubLink *sublink);
|
2008-03-20 22:42:48 +01:00
|
|
|
static Node *transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
|
|
|
|
Oid array_type, Oid element_type, int32 typmod);
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
static Node *transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault);
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
|
2005-06-27 00:05:42 +02:00
|
|
|
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
|
2016-08-17 02:33:01 +02:00
|
|
|
static Node *transformSQLValueFunction(ParseState *pstate,
|
|
|
|
SQLValueFunction *svf);
|
2007-11-15 23:25:18 +01:00
|
|
|
static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x);
|
|
|
|
static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs);
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
|
2007-11-15 23:25:18 +01:00
|
|
|
static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr);
|
2002-03-21 17:02:16 +01:00
|
|
|
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
2009-10-31 02:41:31 +01:00
|
|
|
static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte,
|
2010-02-26 03:01:40 +01:00
|
|
|
int location);
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
|
2008-08-29 01:09:48 +02:00
|
|
|
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
|
2011-02-08 22:04:18 +01:00
|
|
|
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
|
2005-12-28 02:30:02 +01:00
|
|
|
static Node *make_row_comparison_op(ParseState *pstate, List *opname,
|
2006-10-04 02:30:14 +02:00
|
|
|
List *largs, List *rargs, int location);
|
2004-05-11 00:44:49 +02:00
|
|
|
static Node *make_row_distinct_op(ParseState *pstate, List *opname,
|
2006-03-14 23:48:25 +01:00
|
|
|
RowExpr *lrow, RowExpr *rrow, int location);
|
2004-05-11 00:44:49 +02:00
|
|
|
static Expr *make_distinct_op(ParseState *pstate, List *opname,
|
2006-03-14 23:48:25 +01:00
|
|
|
Node *ltree, Node *rtree, int location);
|
2016-07-28 23:23:03 +02:00
|
|
|
static Node *make_nulltest_from_distinct(ParseState *pstate,
|
|
|
|
A_Expr *distincta, Node *arg);
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
static int operator_precedence_group(Node *node, const char **nodename);
|
|
|
|
static void emit_precedence_warnings(ParseState *pstate,
|
|
|
|
int opgroup, const char *opname,
|
|
|
|
Node *lchild, Node *rchild,
|
|
|
|
int location);
|
1997-11-25 23:07:18 +01:00
|
|
|
|
2000-03-17 06:29:07 +01:00
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
/*
|
|
|
|
* transformExpr -
|
2000-03-19 08:13:58 +01:00
|
|
|
* Analyze and transform expressions. Type checking and type casting is
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
* done here. This processing converts the raw grammar output into
|
|
|
|
* expression trees with fully determined semantics.
|
1997-11-25 23:07:18 +01:00
|
|
|
*/
|
|
|
|
Node *
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
|
1997-11-25 23:07:18 +01:00
|
|
|
{
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
Node *result;
|
|
|
|
ParseExprKind sv_expr_kind;
|
|
|
|
|
|
|
|
/* Save and restore identity of expression type we're parsing */
|
|
|
|
Assert(exprKind != EXPR_KIND_NONE);
|
|
|
|
sv_expr_kind = pstate->p_expr_kind;
|
|
|
|
pstate->p_expr_kind = exprKind;
|
|
|
|
|
|
|
|
result = transformExprRecurse(pstate, expr);
|
|
|
|
|
|
|
|
pstate->p_expr_kind = sv_expr_kind;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformExprRecurse(ParseState *pstate, Node *expr)
|
|
|
|
{
|
|
|
|
Node *result;
|
1997-11-25 23:07:18 +01:00
|
|
|
|
|
|
|
if (expr == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2004-03-24 23:40:29 +01:00
|
|
|
/* Guard against stack overflow due to overly complex expressions */
|
|
|
|
check_stack_depth();
|
2000-03-17 06:29:07 +01:00
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
switch (nodeTag(expr))
|
|
|
|
{
|
2002-03-21 17:02:16 +01:00
|
|
|
case T_ColumnRef:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformColumnRef(pstate, (ColumnRef *) expr);
|
|
|
|
break;
|
2003-04-30 00:13:11 +02:00
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
case T_ParamRef:
|
|
|
|
result = transformParamRef(pstate, (ParamRef *) expr);
|
|
|
|
break;
|
2003-04-30 00:13:11 +02:00
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
case T_A_Const:
|
|
|
|
{
|
|
|
|
A_Const *con = (A_Const *) expr;
|
|
|
|
Value *val = &con->val;
|
|
|
|
|
2008-09-01 22:42:46 +02:00
|
|
|
result = (Node *) make_const(pstate, val, con->location);
|
1997-11-25 23:07:18 +01:00
|
|
|
break;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2004-06-09 21:08:20 +02:00
|
|
|
case T_A_Indirection:
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
result = transformIndirection(pstate, (A_Indirection *) expr);
|
|
|
|
break;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
case T_A_ArrayExpr:
|
|
|
|
result = transformArrayExpr(pstate, (A_ArrayExpr *) expr,
|
|
|
|
InvalidOid, InvalidOid, -1);
|
|
|
|
break;
|
|
|
|
|
2000-01-17 01:14:49 +01:00
|
|
|
case T_TypeCast:
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
result = transformTypeCast(pstate, (TypeCast *) expr);
|
|
|
|
break;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
case T_CollateClause:
|
|
|
|
result = transformCollateClause(pstate, (CollateClause *) expr);
|
|
|
|
break;
|
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
case T_A_Expr:
|
|
|
|
{
|
|
|
|
A_Expr *a = (A_Expr *) expr;
|
|
|
|
|
2003-02-10 05:44:47 +01:00
|
|
|
switch (a->kind)
|
1997-11-25 23:07:18 +01:00
|
|
|
{
|
2003-02-10 05:44:47 +01:00
|
|
|
case AEXPR_OP:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprOp(pstate, a);
|
1997-11-25 23:07:18 +01:00
|
|
|
break;
|
2003-06-29 02:33:44 +02:00
|
|
|
case AEXPR_OP_ANY:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprOpAny(pstate, a);
|
2003-06-29 02:33:44 +02:00
|
|
|
break;
|
|
|
|
case AEXPR_OP_ALL:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprOpAll(pstate, a);
|
2003-06-29 02:33:44 +02:00
|
|
|
break;
|
2003-02-10 05:44:47 +01:00
|
|
|
case AEXPR_DISTINCT:
|
2016-07-28 23:23:03 +02:00
|
|
|
case AEXPR_NOT_DISTINCT:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprDistinct(pstate, a);
|
2002-08-04 08:46:12 +02:00
|
|
|
break;
|
2003-02-16 03:30:39 +01:00
|
|
|
case AEXPR_NULLIF:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprNullIf(pstate, a);
|
2003-02-16 03:30:39 +01:00
|
|
|
break;
|
2003-02-10 05:44:47 +01:00
|
|
|
case AEXPR_OF:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformAExprOf(pstate, a);
|
2002-08-04 08:46:12 +02:00
|
|
|
break;
|
2005-11-28 05:35:32 +01:00
|
|
|
case AEXPR_IN:
|
|
|
|
result = transformAExprIn(pstate, a);
|
|
|
|
break;
|
2015-02-23 18:46:46 +01:00
|
|
|
case AEXPR_LIKE:
|
|
|
|
case AEXPR_ILIKE:
|
|
|
|
case AEXPR_SIMILAR:
|
|
|
|
/* we can transform these just like AEXPR_OP */
|
|
|
|
result = transformAExprOp(pstate, a);
|
|
|
|
break;
|
2015-02-22 19:57:56 +01:00
|
|
|
case AEXPR_BETWEEN:
|
|
|
|
case AEXPR_NOT_BETWEEN:
|
|
|
|
case AEXPR_BETWEEN_SYM:
|
|
|
|
case AEXPR_NOT_BETWEEN_SYM:
|
|
|
|
result = transformAExprBetween(pstate, a);
|
|
|
|
break;
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
case AEXPR_PAREN:
|
|
|
|
result = transformExprRecurse(pstate, a->lexpr);
|
|
|
|
break;
|
2005-01-20 00:45:24 +01:00
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
|
2013-05-29 22:58:43 +02:00
|
|
|
result = NULL; /* keep compiler quiet */
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
break;
|
1997-11-25 23:07:18 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2014-06-16 21:55:05 +02:00
|
|
|
case T_BoolExpr:
|
|
|
|
result = transformBoolExpr(pstate, (BoolExpr *) expr);
|
|
|
|
break;
|
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
case T_FuncCall:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformFuncCall(pstate, (FuncCall *) expr);
|
|
|
|
break;
|
1997-11-25 23:07:18 +01:00
|
|
|
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
case T_MultiAssignRef:
|
|
|
|
result = transformMultiAssignRef(pstate, (MultiAssignRef *) expr);
|
|
|
|
break;
|
|
|
|
|
Support GROUPING SETS, CUBE and ROLLUP.
This SQL standard functionality allows to aggregate data by different
GROUP BY clauses at once. Each grouping set returns rows with columns
grouped by in other sets set to NULL.
This could previously be achieved by doing each grouping as a separate
query, conjoined by UNION ALLs. Besides being considerably more concise,
grouping sets will in many cases be faster, requiring only one scan over
the underlying data.
The current implementation of grouping sets only supports using sorting
for input. Individual sets that share a sort order are computed in one
pass. If there are sets that don't share a sort order, additional sort &
aggregation steps are performed. These additional passes are sourced by
the previous sort step; thus avoiding repeated scans of the source data.
The code is structured in a way that adding support for purely using
hash aggregation or a mix of hashing and sorting is possible. Sorting
was chosen to be supported first, as it is the most generic method of
implementation.
Instead of, as in an earlier versions of the patch, representing the
chain of sort and aggregation steps as full blown planner and executor
nodes, all but the first sort are performed inside the aggregation node
itself. This avoids the need to do some unusual gymnastics to handle
having to return aggregated and non-aggregated tuples from underlying
nodes, as well as having to shut down underlying nodes early to limit
memory usage. The optimizer still builds Sort/Agg node to describe each
phase, but they're not part of the plan tree, but instead additional
data for the aggregation node. They're a convenient and preexisting way
to describe aggregation and sorting. The first (and possibly only) sort
step is still performed as a separate execution step. That retains
similarity with existing group by plans, makes rescans fairly simple,
avoids very deep plans (leading to slow explains) and easily allows to
avoid the sorting step if the underlying data is sorted by other means.
A somewhat ugly side of this patch is having to deal with a grammar
ambiguity between the new CUBE keyword and the cube extension/functions
named cube (and rollup). To avoid breaking existing deployments of the
cube extension it has not been renamed, neither has cube been made a
reserved keyword. Instead precedence hacking is used to make GROUP BY
cube(..) refer to the CUBE grouping sets feature, and not the function
cube(). To actually group by a function cube(), unlikely as that might
be, the function name has to be quoted.
Needs a catversion bump because stored rules may change.
Author: Andrew Gierth and Atri Sharma, with contributions from Andres Freund
Reviewed-By: Andres Freund, Noah Misch, Tom Lane, Svenne Krap, Tomas
Vondra, Erik Rijkers, Marti Raudsepp, Pavel Stehule
Discussion: CAOeZVidmVRe2jU6aMk_5qkxnB7dfmPROzM7Ur8JPW5j8Y5X-Lw@mail.gmail.com
2015-05-16 03:40:59 +02:00
|
|
|
case T_GroupingFunc:
|
|
|
|
result = transformGroupingFunc(pstate, (GroupingFunc *) expr);
|
|
|
|
break;
|
|
|
|
|
2009-10-08 04:39:25 +02:00
|
|
|
case T_NamedArgExpr:
|
|
|
|
{
|
|
|
|
NamedArgExpr *na = (NamedArgExpr *) expr;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
na->arg = (Expr *) transformExprRecurse(pstate, (Node *) na->arg);
|
2009-10-08 04:39:25 +02:00
|
|
|
result = expr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1998-01-19 06:06:41 +01:00
|
|
|
case T_SubLink:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformSubLink(pstate, (SubLink *) expr);
|
|
|
|
break;
|
1998-05-10 01:31:34 +02:00
|
|
|
|
1998-12-04 16:34:49 +01:00
|
|
|
case T_CaseExpr:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformCaseExpr(pstate, (CaseExpr *) expr);
|
|
|
|
break;
|
1998-12-04 16:34:49 +01:00
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
case T_RowExpr:
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
result = transformRowExpr(pstate, (RowExpr *) expr, false);
|
2005-01-20 00:45:24 +01:00
|
|
|
break;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2003-02-16 03:30:39 +01:00
|
|
|
case T_CoalesceExpr:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr);
|
|
|
|
break;
|
2003-02-16 03:30:39 +01:00
|
|
|
|
2005-06-27 00:05:42 +02:00
|
|
|
case T_MinMaxExpr:
|
|
|
|
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
|
|
|
|
break;
|
|
|
|
|
2016-08-17 02:33:01 +02:00
|
|
|
case T_SQLValueFunction:
|
|
|
|
result = transformSQLValueFunction(pstate,
|
|
|
|
(SQLValueFunction *) expr);
|
|
|
|
break;
|
|
|
|
|
2006-12-24 01:29:20 +01:00
|
|
|
case T_XmlExpr:
|
|
|
|
result = transformXmlExpr(pstate, (XmlExpr *) expr);
|
|
|
|
break;
|
|
|
|
|
2007-02-03 15:06:56 +01:00
|
|
|
case T_XmlSerialize:
|
|
|
|
result = transformXmlSerialize(pstate, (XmlSerialize *) expr);
|
|
|
|
break;
|
|
|
|
|
2001-06-20 00:39:12 +02:00
|
|
|
case T_NullTest:
|
|
|
|
{
|
|
|
|
NullTest *n = (NullTest *) expr;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
|
|
|
|
(Node *) n->arg, NULL,
|
|
|
|
n->location);
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg);
|
2001-06-20 00:39:12 +02:00
|
|
|
/* the argument can be any type, so don't coerce it */
|
2010-01-02 00:03:10 +01:00
|
|
|
n->argisrow = type_is_rowtype(exprType((Node *) n->arg));
|
2001-06-20 00:39:12 +02:00
|
|
|
result = expr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case T_BooleanTest:
|
2005-01-20 00:45:24 +01:00
|
|
|
result = transformBooleanTest(pstate, (BooleanTest *) expr);
|
|
|
|
break;
|
2001-06-20 00:39:12 +02:00
|
|
|
|
2007-06-11 03:16:30 +02:00
|
|
|
case T_CurrentOfExpr:
|
2007-06-12 00:22:42 +02:00
|
|
|
result = transformCurrentOfExpr(pstate, (CurrentOfExpr *) expr);
|
|
|
|
break;
|
2007-06-11 03:16:30 +02:00
|
|
|
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
/*
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
* In all places where DEFAULT is legal, the caller should have
|
|
|
|
* processed it rather than passing it to transformExpr().
|
|
|
|
*/
|
|
|
|
case T_SetToDefault:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("DEFAULT is not allowed in this context"),
|
|
|
|
parser_errposition(pstate,
|
|
|
|
((SetToDefault *) expr)->location)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CaseTestExpr doesn't require any processing; it is only
|
|
|
|
* injected into parse trees in a fully-formed state.
|
2002-09-04 22:31:48 +02:00
|
|
|
*
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
* Ordinarily we should not see a Var here, but it is convenient
|
|
|
|
* for transformJoinUsingClause() to create untransformed operator
|
|
|
|
* trees containing already-transformed Vars. The best
|
|
|
|
* alternative would be to deconstruct and reconstruct column
|
|
|
|
* references, which seems expensively pointless. So allow it.
|
|
|
|
*/
|
2004-03-17 21:48:43 +01:00
|
|
|
case T_CaseTestExpr:
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
case T_Var:
|
1998-03-26 22:08:10 +01:00
|
|
|
{
|
|
|
|
result = (Node *) expr;
|
|
|
|
break;
|
|
|
|
}
|
2002-07-18 19:14:20 +02:00
|
|
|
|
1997-11-25 23:07:18 +01:00
|
|
|
default:
|
|
|
|
/* should not reach here */
|
2003-07-19 22:20:53 +02:00
|
|
|
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
result = NULL; /* keep compiler quiet */
|
1997-11-25 23:07:18 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/*
|
|
|
|
* helper routine for delivering "column does not exist" error message
|
|
|
|
*
|
|
|
|
* (Usually we don't have to work this hard, but the general case of field
|
|
|
|
* selection from an arbitrary node needs it.)
|
|
|
|
*/
|
|
|
|
static void
|
2017-10-31 15:34:31 +01:00
|
|
|
unknown_attribute(ParseState *pstate, Node *relref, const char *attname,
|
2009-10-31 02:41:31 +01:00
|
|
|
int location)
|
|
|
|
{
|
|
|
|
RangeTblEntry *rte;
|
|
|
|
|
|
|
|
if (IsA(relref, Var) &&
|
|
|
|
((Var *) relref)->varattno == InvalidAttrNumber)
|
|
|
|
{
|
|
|
|
/* Reference the RTE by alias not by actual table name */
|
|
|
|
rte = GetRTEByRangeTablePosn(pstate,
|
|
|
|
((Var *) relref)->varno,
|
|
|
|
((Var *) relref)->varlevelsup);
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
|
|
|
errmsg("column %s.%s does not exist",
|
|
|
|
rte->eref->aliasname, attname),
|
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Have to do it by reference to the type of the expression */
|
|
|
|
Oid relTypeId = exprType(relref);
|
|
|
|
|
|
|
|
if (ISCOMPLEX(relTypeId))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
|
|
|
errmsg("column \"%s\" not found in data type %s",
|
|
|
|
attname, format_type_be(relTypeId)),
|
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
else if (relTypeId == RECORDOID)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("could not identify column \"%s\" in record data type",
|
|
|
|
attname),
|
2009-10-31 02:41:31 +01:00
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("column notation .%s applied to type %s, "
|
|
|
|
"which is not a composite type",
|
|
|
|
attname, format_type_be(relTypeId)),
|
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-26 14:57:23 +02:00
|
|
|
static Node *
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
transformIndirection(ParseState *pstate, A_Indirection *ind)
|
1997-11-25 23:07:18 +01:00
|
|
|
{
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
Node *last_srf = pstate->p_last_srf;
|
|
|
|
Node *result = transformExprRecurse(pstate, ind->arg);
|
2004-06-09 21:08:20 +02:00
|
|
|
List *subscripts = NIL;
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
int location = exprLocation(result);
|
2004-06-09 21:08:20 +02:00
|
|
|
ListCell *i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to split any field-selection operations apart from
|
2005-10-15 04:49:52 +02:00
|
|
|
* subscripting. Adjacent A_Indices nodes have to be treated as a single
|
|
|
|
* multidimensional subscript operation.
|
2004-06-09 21:08:20 +02:00
|
|
|
*/
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
foreach(i, ind->indirection)
|
2004-06-09 21:08:20 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Node *n = lfirst(i);
|
2004-06-09 21:08:20 +02:00
|
|
|
|
|
|
|
if (IsA(n, A_Indices))
|
|
|
|
subscripts = lappend(subscripts, n);
|
2008-08-30 03:39:14 +02:00
|
|
|
else if (IsA(n, A_Star))
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("row expansion via \"*\" is not supported here"),
|
2009-10-31 02:41:31 +01:00
|
|
|
parser_errposition(pstate, location)));
|
2008-08-30 03:39:14 +02:00
|
|
|
}
|
2004-06-09 21:08:20 +02:00
|
|
|
else
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
Node *newresult;
|
|
|
|
|
2004-06-09 21:08:20 +02:00
|
|
|
Assert(IsA(n, String));
|
|
|
|
|
|
|
|
/* process subscripts before this field selection */
|
|
|
|
if (subscripts)
|
|
|
|
result = (Node *) transformArraySubscripts(pstate,
|
|
|
|
result,
|
2005-10-15 04:49:52 +02:00
|
|
|
exprType(result),
|
2004-06-09 21:08:20 +02:00
|
|
|
InvalidOid,
|
2007-03-17 01:11:05 +01:00
|
|
|
exprTypmod(result),
|
2004-06-09 21:08:20 +02:00
|
|
|
subscripts,
|
|
|
|
NULL);
|
|
|
|
subscripts = NIL;
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
newresult = ParseFuncOrColumn(pstate,
|
|
|
|
list_make1(n),
|
|
|
|
list_make1(result),
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
last_srf,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NULL,
|
2017-11-30 14:46:13 +01:00
|
|
|
false,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
location);
|
2009-10-31 02:41:31 +01:00
|
|
|
if (newresult == NULL)
|
|
|
|
unknown_attribute(pstate, result, strVal(n), location);
|
|
|
|
result = newresult;
|
2004-06-09 21:08:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* process trailing subscripts, if any */
|
|
|
|
if (subscripts)
|
|
|
|
result = (Node *) transformArraySubscripts(pstate,
|
|
|
|
result,
|
|
|
|
exprType(result),
|
|
|
|
InvalidOid,
|
2007-03-17 01:11:05 +01:00
|
|
|
exprTypmod(result),
|
2004-06-09 21:08:20 +02:00
|
|
|
subscripts,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return result;
|
1999-07-17 00:32:25 +02:00
|
|
|
}
|
1997-11-25 23:07:18 +01:00
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/*
|
|
|
|
* Transform a ColumnRef.
|
|
|
|
*
|
|
|
|
* If you find yourself changing this code, see also ExpandColumnRefStar.
|
|
|
|
*/
|
1999-07-17 00:32:25 +02:00
|
|
|
static Node *
|
2002-03-21 17:02:16 +01:00
|
|
|
transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
1999-07-17 00:32:25 +02:00
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
Node *node = NULL;
|
|
|
|
char *nspname = NULL;
|
|
|
|
char *relname = NULL;
|
|
|
|
char *colname = NULL;
|
|
|
|
RangeTblEntry *rte;
|
2002-12-12 21:35:16 +01:00
|
|
|
int levels_up;
|
2010-02-26 03:01:40 +01:00
|
|
|
enum
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
CRERR_NO_COLUMN,
|
|
|
|
CRERR_NO_RTE,
|
|
|
|
CRERR_WRONG_DB,
|
|
|
|
CRERR_TOO_MANY
|
|
|
|
} crerr = CRERR_NO_COLUMN;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Give the PreParseColumnRefHook, if any, first shot. If it returns
|
2009-10-31 02:41:31 +01:00
|
|
|
* non-null then that's all, folks.
|
|
|
|
*/
|
|
|
|
if (pstate->p_pre_columnref_hook != NULL)
|
|
|
|
{
|
2017-09-07 18:06:23 +02:00
|
|
|
node = pstate->p_pre_columnref_hook(pstate, cref);
|
2009-10-31 02:41:31 +01:00
|
|
|
if (node != NULL)
|
|
|
|
return node;
|
|
|
|
}
|
2002-03-21 17:02:16 +01:00
|
|
|
|
|
|
|
/*----------
|
|
|
|
* The allowed syntaxes are:
|
|
|
|
*
|
|
|
|
* A First try to resolve as unqualified column name;
|
2004-04-02 21:07:02 +02:00
|
|
|
* if no luck, try to resolve as unqualified table name (A.*).
|
|
|
|
* A.B A is an unqualified table name; B is either a
|
2002-03-21 17:02:16 +01:00
|
|
|
* column or function name (trying column name first).
|
|
|
|
* A.B.C schema A, table B, col or func name C.
|
|
|
|
* A.B.C.D catalog A, schema B, table C, col or func D.
|
2004-04-02 21:07:02 +02:00
|
|
|
* A.* A is an unqualified table name; means whole-row value.
|
2002-03-21 17:02:16 +01:00
|
|
|
* A.B.* whole-row value of table B in schema A.
|
|
|
|
* A.B.C.* whole-row value of table C in schema B in catalog A.
|
|
|
|
*
|
|
|
|
* We do not need to cope with bare "*"; that will only be accepted by
|
|
|
|
* the grammar at the top level of a SELECT list, and transformTargetList
|
2004-04-02 21:07:02 +02:00
|
|
|
* will take care of it before it ever gets here. Also, "A.*" etc will
|
|
|
|
* be expanded by transformTargetList if they appear at SELECT top level,
|
|
|
|
* so here we are only going to see them as function or operator inputs.
|
2002-03-21 17:02:16 +01:00
|
|
|
*
|
|
|
|
* Currently, if a catalog name is given then it must equal the current
|
|
|
|
* database name; we check it here and then discard it.
|
|
|
|
*----------
|
|
|
|
*/
|
2009-10-31 02:41:31 +01:00
|
|
|
switch (list_length(cref->fields))
|
2002-03-21 17:02:16 +01:00
|
|
|
{
|
|
|
|
case 1:
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
2008-08-30 03:39:14 +02:00
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
colname = strVal(field1);
|
1999-07-17 00:32:25 +02:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/* Try to identify as an unqualified column */
|
2009-10-31 02:41:31 +01:00
|
|
|
node = colNameToVar(pstate, colname, false, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
if (node == NULL)
|
|
|
|
{
|
|
|
|
/*
|
2002-12-12 21:35:16 +01:00
|
|
|
* Not known as a column of any range-table entry.
|
|
|
|
*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Try to find the name as a relation. Note that only
|
2005-10-15 04:49:52 +02:00
|
|
|
* relations already entered into the rangetable will be
|
|
|
|
* recognized.
|
2002-09-04 22:31:48 +02:00
|
|
|
*
|
|
|
|
* This is a hack for backwards compatibility with
|
2005-10-15 04:49:52 +02:00
|
|
|
* PostQUEL-inspired syntax. The preferred form now is
|
|
|
|
* "rel.*".
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2009-10-31 02:41:31 +01:00
|
|
|
rte = refnameRangeTblEntry(pstate, NULL, colname,
|
|
|
|
cref->location,
|
|
|
|
&levels_up);
|
|
|
|
if (rte)
|
|
|
|
node = transformWholeRowRef(pstate, rte,
|
2006-03-14 23:48:25 +01:00
|
|
|
cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
2002-03-21 17:02:16 +01:00
|
|
|
{
|
2008-08-30 03:39:14 +02:00
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
Node *field2 = (Node *) lsecond(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
relname = strVal(field1);
|
|
|
|
|
|
|
|
/* Locate the referenced RTE */
|
|
|
|
rte = refnameRangeTblEntry(pstate, nspname, relname,
|
|
|
|
cref->location,
|
|
|
|
&levels_up);
|
|
|
|
if (rte == NULL)
|
|
|
|
{
|
|
|
|
crerr = CRERR_NO_RTE;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-17 00:32:25 +02:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/* Whole-row reference? */
|
2008-08-30 03:39:14 +02:00
|
|
|
if (IsA(field2, A_Star))
|
2002-03-21 17:02:16 +01:00
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
break;
|
2002-03-21 17:02:16 +01:00
|
|
|
}
|
1999-07-17 00:32:25 +02:00
|
|
|
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field2, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
colname = strVal(field2);
|
2008-08-30 03:39:14 +02:00
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try to identify as a column of the RTE */
|
2015-03-11 15:44:04 +01:00
|
|
|
node = scanRTEForColumn(pstate, rte, colname, cref->location,
|
|
|
|
0, NULL);
|
2002-09-04 22:31:48 +02:00
|
|
|
if (node == NULL)
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try it as a function call on the whole row */
|
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
node = ParseFuncOrColumn(pstate,
|
2009-10-31 02:41:31 +01:00
|
|
|
list_make1(makeString(colname)),
|
2004-05-31 01:40:41 +02:00
|
|
|
list_make1(node),
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
pstate->p_last_srf,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NULL,
|
2017-11-30 14:46:13 +01:00
|
|
|
false,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
2002-03-21 17:02:16 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3:
|
|
|
|
{
|
2008-08-30 03:39:14 +02:00
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
Node *field2 = (Node *) lsecond(cref->fields);
|
|
|
|
Node *field3 = (Node *) lthird(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
nspname = strVal(field1);
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field2, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
relname = strVal(field2);
|
|
|
|
|
|
|
|
/* Locate the referenced RTE */
|
|
|
|
rte = refnameRangeTblEntry(pstate, nspname, relname,
|
|
|
|
cref->location,
|
|
|
|
&levels_up);
|
|
|
|
if (rte == NULL)
|
|
|
|
{
|
|
|
|
crerr = CRERR_NO_RTE;
|
|
|
|
break;
|
|
|
|
}
|
2002-03-21 17:02:16 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/* Whole-row reference? */
|
2008-08-30 03:39:14 +02:00
|
|
|
if (IsA(field3, A_Star))
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field3, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
colname = strVal(field3);
|
2008-08-30 03:39:14 +02:00
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try to identify as a column of the RTE */
|
2015-03-11 15:44:04 +01:00
|
|
|
node = scanRTEForColumn(pstate, rte, colname, cref->location,
|
|
|
|
0, NULL);
|
2002-09-04 22:31:48 +02:00
|
|
|
if (node == NULL)
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try it as a function call on the whole row */
|
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
node = ParseFuncOrColumn(pstate,
|
2009-10-31 02:41:31 +01:00
|
|
|
list_make1(makeString(colname)),
|
2004-05-31 01:40:41 +02:00
|
|
|
list_make1(node),
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
pstate->p_last_srf,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NULL,
|
2017-11-30 14:46:13 +01:00
|
|
|
false,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2002-03-21 17:02:16 +01:00
|
|
|
}
|
|
|
|
case 4:
|
|
|
|
{
|
2008-08-30 03:39:14 +02:00
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
Node *field2 = (Node *) lsecond(cref->fields);
|
|
|
|
Node *field3 = (Node *) lthird(cref->fields);
|
|
|
|
Node *field4 = (Node *) lfourth(cref->fields);
|
2009-10-31 02:41:31 +01:00
|
|
|
char *catname;
|
2008-08-30 03:39:14 +02:00
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
catname = strVal(field1);
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field2, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
nspname = strVal(field2);
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field3, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
relname = strVal(field3);
|
2002-03-21 17:02:16 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
|
|
|
* We check the catalog name and then ignore it.
|
|
|
|
*/
|
2009-10-31 02:41:31 +01:00
|
|
|
if (strcmp(catname, get_database_name(MyDatabaseId)) != 0)
|
|
|
|
{
|
|
|
|
crerr = CRERR_WRONG_DB;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Locate the referenced RTE */
|
|
|
|
rte = refnameRangeTblEntry(pstate, nspname, relname,
|
|
|
|
cref->location,
|
|
|
|
&levels_up);
|
|
|
|
if (rte == NULL)
|
|
|
|
{
|
|
|
|
crerr = CRERR_NO_RTE;
|
|
|
|
break;
|
|
|
|
}
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/* Whole-row reference? */
|
2008-08-30 03:39:14 +02:00
|
|
|
if (IsA(field4, A_Star))
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-08-30 03:39:14 +02:00
|
|
|
Assert(IsA(field4, String));
|
2009-10-31 02:41:31 +01:00
|
|
|
colname = strVal(field4);
|
2008-08-30 03:39:14 +02:00
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try to identify as a column of the RTE */
|
2015-03-11 15:44:04 +01:00
|
|
|
node = scanRTEForColumn(pstate, rte, colname, cref->location,
|
|
|
|
0, NULL);
|
2002-09-04 22:31:48 +02:00
|
|
|
if (node == NULL)
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Try it as a function call on the whole row */
|
|
|
|
node = transformWholeRowRef(pstate, rte, cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
node = ParseFuncOrColumn(pstate,
|
2009-10-31 02:41:31 +01:00
|
|
|
list_make1(makeString(colname)),
|
2004-05-31 01:40:41 +02:00
|
|
|
list_make1(node),
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
pstate->p_last_srf,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NULL,
|
2017-11-30 14:46:13 +01:00
|
|
|
false,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
cref->location);
|
2002-09-04 22:31:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2002-03-21 17:02:16 +01:00
|
|
|
}
|
|
|
|
default:
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
crerr = CRERR_TOO_MANY; /* too many dotted names */
|
2002-03-21 17:02:16 +01:00
|
|
|
break;
|
1997-11-25 23:07:18 +01:00
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
/*
|
2009-10-31 02:41:31 +01:00
|
|
|
* Now give the PostParseColumnRefHook, if any, a chance. We pass the
|
|
|
|
* translation-so-far so that it can throw an error if it wishes in the
|
2010-02-26 03:01:40 +01:00
|
|
|
* case that it has a conflicting interpretation of the ColumnRef. (If it
|
|
|
|
* just translates anyway, we'll throw an error, because we can't undo
|
|
|
|
* whatever effects the preceding steps may have had on the pstate.) If it
|
|
|
|
* returns NULL, use the standard translation, or throw a suitable error
|
|
|
|
* if there is none.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2009-10-31 02:41:31 +01:00
|
|
|
if (pstate->p_post_columnref_hook != NULL)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
2010-02-26 03:01:40 +01:00
|
|
|
Node *hookresult;
|
2009-10-31 02:41:31 +01:00
|
|
|
|
2017-09-07 18:06:23 +02:00
|
|
|
hookresult = pstate->p_post_columnref_hook(pstate, cref, node);
|
2009-10-31 02:41:31 +01:00
|
|
|
if (node == NULL)
|
|
|
|
node = hookresult;
|
|
|
|
else if (hookresult != NULL)
|
2005-01-20 00:45:24 +01:00
|
|
|
ereport(ERROR,
|
2009-10-31 02:41:31 +01:00
|
|
|
(errcode(ERRCODE_AMBIGUOUS_COLUMN),
|
|
|
|
errmsg("column reference \"%s\" is ambiguous",
|
|
|
|
NameListToString(cref->fields)),
|
|
|
|
parser_errposition(pstate, cref->location)));
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
2007-06-12 00:22:42 +02:00
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/*
|
|
|
|
* Throw error if no translation found.
|
|
|
|
*/
|
|
|
|
if (node == NULL)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
switch (crerr)
|
|
|
|
{
|
|
|
|
case CRERR_NO_COLUMN:
|
2012-08-08 01:02:54 +02:00
|
|
|
errorMissingColumn(pstate, relname, colname, cref->location);
|
2009-10-31 02:41:31 +01:00
|
|
|
break;
|
|
|
|
case CRERR_NO_RTE:
|
|
|
|
errorMissingRTE(pstate, makeRangeVar(nspname, relname,
|
|
|
|
cref->location));
|
|
|
|
break;
|
|
|
|
case CRERR_WRONG_DB:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("cross-database references are not implemented: %s",
|
|
|
|
NameListToString(cref->fields)),
|
2009-10-31 02:41:31 +01:00
|
|
|
parser_errposition(pstate, cref->location)));
|
|
|
|
break;
|
|
|
|
case CRERR_TOO_MANY:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("improper qualified name (too many dotted names): %s",
|
|
|
|
NameListToString(cref->fields)),
|
2009-10-31 02:41:31 +01:00
|
|
|
parser_errposition(pstate, cref->location)));
|
|
|
|
break;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
return node;
|
2007-06-12 00:22:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformParamRef(ParseState *pstate, ParamRef *pref)
|
|
|
|
{
|
2009-10-31 02:41:31 +01:00
|
|
|
Node *result;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* The core parser knows nothing about Params. If a hook is supplied,
|
2009-10-31 02:41:31 +01:00
|
|
|
* call it. If not, or if the hook returns NULL, throw a generic error.
|
|
|
|
*/
|
|
|
|
if (pstate->p_paramref_hook != NULL)
|
2017-09-07 18:06:23 +02:00
|
|
|
result = pstate->p_paramref_hook(pstate, pref);
|
2009-10-31 02:41:31 +01:00
|
|
|
else
|
|
|
|
result = NULL;
|
|
|
|
|
|
|
|
if (result == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
|
|
|
errmsg("there is no parameter $%d", pref->number),
|
|
|
|
parser_errposition(pstate, pref->location)));
|
|
|
|
|
|
|
|
return result;
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
2007-10-29 20:40:40 +01:00
|
|
|
/* Test whether an a_expr is a plain NULL constant or not */
|
|
|
|
static bool
|
|
|
|
exprIsNullConstant(Node *arg)
|
|
|
|
{
|
|
|
|
if (arg && IsA(arg, A_Const))
|
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
A_Const *con = (A_Const *) arg;
|
2007-10-29 20:40:40 +01:00
|
|
|
|
2008-04-29 16:59:17 +02:00
|
|
|
if (con->val.type == T_Null)
|
2007-10-29 20:40:40 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
|
|
|
transformAExprOp(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
|
|
|
Node *lexpr = a->lexpr;
|
|
|
|
Node *rexpr = a->rexpr;
|
|
|
|
Node *result;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
{
|
|
|
|
int opgroup;
|
|
|
|
const char *opname;
|
|
|
|
|
|
|
|
opgroup = operator_precedence_group((Node *) a, &opname);
|
|
|
|
if (opgroup > 0)
|
|
|
|
emit_precedence_warnings(pstate, opgroup, opname,
|
|
|
|
lexpr, rexpr,
|
|
|
|
a->location);
|
2016-04-22 05:17:36 +02:00
|
|
|
|
|
|
|
/* Look through AEXPR_PAREN nodes so they don't affect tests below */
|
|
|
|
while (lexpr && IsA(lexpr, A_Expr) &&
|
|
|
|
((A_Expr *) lexpr)->kind == AEXPR_PAREN)
|
|
|
|
lexpr = ((A_Expr *) lexpr)->lexpr;
|
|
|
|
while (rexpr && IsA(rexpr, A_Expr) &&
|
|
|
|
((A_Expr *) rexpr)->kind == AEXPR_PAREN)
|
|
|
|
rexpr = ((A_Expr *) rexpr)->lexpr;
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Special-case "foo = NULL" and "NULL = foo" for compatibility with
|
|
|
|
* standards-broken products (like Microsoft's). Turn these into IS NULL
|
2011-10-08 10:17:40 +02:00
|
|
|
* exprs. (If either side is a CaseTestExpr, then the expression was
|
|
|
|
* generated internally from a CASE-WHEN expression, and
|
|
|
|
* transform_null_equals does not apply.)
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
|
|
|
if (Transform_null_equals &&
|
|
|
|
list_length(a->name) == 1 &&
|
|
|
|
strcmp(strVal(linitial(a->name)), "=") == 0 &&
|
2011-10-08 10:17:40 +02:00
|
|
|
(exprIsNullConstant(lexpr) || exprIsNullConstant(rexpr)) &&
|
2012-06-10 21:20:04 +02:00
|
|
|
(!IsA(lexpr, CaseTestExpr) &&!IsA(rexpr, CaseTestExpr)))
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
|
|
|
NullTest *n = makeNode(NullTest);
|
|
|
|
|
|
|
|
n->nulltesttype = IS_NULL;
|
2015-02-22 20:40:27 +01:00
|
|
|
n->location = a->location;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
if (exprIsNullConstant(lexpr))
|
|
|
|
n->arg = (Expr *) rexpr;
|
|
|
|
else
|
|
|
|
n->arg = (Expr *) lexpr;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
result = transformExprRecurse(pstate, (Node *) n);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
else if (lexpr && IsA(lexpr, RowExpr) &&
|
|
|
|
rexpr && IsA(rexpr, SubLink) &&
|
|
|
|
((SubLink *) rexpr)->subLinkType == EXPR_SUBLINK)
|
|
|
|
{
|
|
|
|
/*
|
2005-12-28 02:30:02 +01:00
|
|
|
* Convert "row op subselect" into a ROWCOMPARE sublink. Formerly the
|
2005-10-15 04:49:52 +02:00
|
|
|
* grammar did this, but now that a row construct is allowed anywhere
|
|
|
|
* in expressions, it's easier to do it here.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
|
|
|
SubLink *s = (SubLink *) rexpr;
|
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
s->subLinkType = ROWCOMPARE_SUBLINK;
|
|
|
|
s->testexpr = lexpr;
|
2005-01-20 00:45:24 +01:00
|
|
|
s->operName = a->name;
|
2008-08-29 01:09:48 +02:00
|
|
|
s->location = a->location;
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
result = transformExprRecurse(pstate, (Node *) s);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
else if (lexpr && IsA(lexpr, RowExpr) &&
|
|
|
|
rexpr && IsA(rexpr, RowExpr))
|
|
|
|
{
|
2013-06-10 00:39:20 +02:00
|
|
|
/* ROW() op ROW() is handled specially */
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
rexpr = transformExprRecurse(pstate, rexpr);
|
2005-11-28 05:35:32 +01:00
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
result = make_row_comparison_op(pstate,
|
|
|
|
a->name,
|
2017-02-21 17:33:07 +01:00
|
|
|
castNode(RowExpr, lexpr)->args,
|
|
|
|
castNode(RowExpr, rexpr)->args,
|
2006-03-14 23:48:25 +01:00
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Ordinary scalar operator */
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
Node *last_srf = pstate->p_last_srf;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
rexpr = transformExprRecurse(pstate, rexpr);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
result = (Node *) make_op(pstate,
|
|
|
|
a->name,
|
|
|
|
lexpr,
|
2006-03-14 23:48:25 +01:00
|
|
|
rexpr,
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
last_srf,
|
2006-03-14 23:48:25 +01:00
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformAExprOpAny(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
Node *lexpr = a->lexpr;
|
|
|
|
Node *rexpr = a->rexpr;
|
|
|
|
|
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP,
|
|
|
|
strVal(llast(a->name)),
|
|
|
|
lexpr, NULL,
|
|
|
|
a->location);
|
|
|
|
|
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
rexpr = transformExprRecurse(pstate, rexpr);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
return (Node *) make_scalar_array_op(pstate,
|
|
|
|
a->name,
|
|
|
|
true,
|
|
|
|
lexpr,
|
2006-03-14 23:48:25 +01:00
|
|
|
rexpr,
|
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformAExprOpAll(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
Node *lexpr = a->lexpr;
|
|
|
|
Node *rexpr = a->rexpr;
|
|
|
|
|
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP,
|
|
|
|
strVal(llast(a->name)),
|
|
|
|
lexpr, NULL,
|
|
|
|
a->location);
|
|
|
|
|
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
rexpr = transformExprRecurse(pstate, rexpr);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
return (Node *) make_scalar_array_op(pstate,
|
|
|
|
a->name,
|
|
|
|
false,
|
|
|
|
lexpr,
|
2006-03-14 23:48:25 +01:00
|
|
|
rexpr,
|
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformAExprDistinct(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
Node *lexpr = a->lexpr;
|
|
|
|
Node *rexpr = a->rexpr;
|
2016-07-28 23:23:03 +02:00
|
|
|
Node *result;
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
|
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_INFIX_IS, "IS",
|
|
|
|
lexpr, rexpr,
|
|
|
|
a->location);
|
|
|
|
|
2016-07-28 23:23:03 +02:00
|
|
|
/*
|
|
|
|
* If either input is an undecorated NULL literal, transform to a NullTest
|
|
|
|
* on the other input. That's simpler to process than a full DistinctExpr,
|
|
|
|
* and it avoids needing to require that the datatype have an = operator.
|
|
|
|
*/
|
|
|
|
if (exprIsNullConstant(rexpr))
|
|
|
|
return make_nulltest_from_distinct(pstate, a, lexpr);
|
|
|
|
if (exprIsNullConstant(lexpr))
|
|
|
|
return make_nulltest_from_distinct(pstate, a, rexpr);
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
rexpr = transformExprRecurse(pstate, rexpr);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
if (lexpr && IsA(lexpr, RowExpr) &&
|
|
|
|
rexpr && IsA(rexpr, RowExpr))
|
|
|
|
{
|
2013-06-10 00:39:20 +02:00
|
|
|
/* ROW() op ROW() is handled specially */
|
2016-07-28 23:23:03 +02:00
|
|
|
result = make_row_distinct_op(pstate, a->name,
|
|
|
|
(RowExpr *) lexpr,
|
|
|
|
(RowExpr *) rexpr,
|
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Ordinary scalar operator */
|
2016-07-28 23:23:03 +02:00
|
|
|
result = (Node *) make_distinct_op(pstate,
|
|
|
|
a->name,
|
|
|
|
lexpr,
|
|
|
|
rexpr,
|
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
2016-07-28 23:23:03 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If it's NOT DISTINCT, we first build a DistinctExpr and then stick a
|
|
|
|
* NOT on top.
|
|
|
|
*/
|
|
|
|
if (a->kind == AEXPR_NOT_DISTINCT)
|
|
|
|
result = (Node *) makeBoolExpr(NOT_EXPR,
|
|
|
|
list_make1(result),
|
|
|
|
a->location);
|
|
|
|
|
|
|
|
return result;
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformAExprNullIf(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
Node *lexpr = transformExprRecurse(pstate, a->lexpr);
|
|
|
|
Node *rexpr = transformExprRecurse(pstate, a->rexpr);
|
2011-03-20 01:29:08 +01:00
|
|
|
OpExpr *result;
|
|
|
|
|
|
|
|
result = (OpExpr *) make_op(pstate,
|
|
|
|
a->name,
|
|
|
|
lexpr,
|
|
|
|
rexpr,
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
pstate->p_last_srf,
|
2011-03-20 01:29:08 +01:00
|
|
|
a->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2011-03-20 01:29:08 +01:00
|
|
|
/*
|
|
|
|
* The comparison operator itself should yield boolean ...
|
|
|
|
*/
|
|
|
|
if (result->opresulttype != BOOLOID)
|
2005-01-20 00:45:24 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2006-03-14 23:48:25 +01:00
|
|
|
errmsg("NULLIF requires = operator to yield boolean"),
|
|
|
|
parser_errposition(pstate, a->location)));
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
if (result->opretset)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
/* translator: %s is name of a SQL construct, eg NULLIF */
|
|
|
|
errmsg("%s must not return a set", "NULLIF"),
|
|
|
|
parser_errposition(pstate, a->location)));
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2011-03-20 01:29:08 +01:00
|
|
|
/*
|
|
|
|
* ... but the NullIfExpr will yield the first operand's type.
|
|
|
|
*/
|
|
|
|
result->opresulttype = exprType((Node *) linitial(result->args));
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
/*
|
|
|
|
* We rely on NullIfExpr and OpExpr being the same struct
|
|
|
|
*/
|
|
|
|
NodeSetTag(result, T_NullIfExpr);
|
|
|
|
|
2011-03-20 01:29:08 +01:00
|
|
|
return (Node *) result;
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
/*
|
|
|
|
* Checking an expression for match to a list of type names. Will result
|
|
|
|
* in a boolean constant node.
|
|
|
|
*/
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
|
|
|
transformAExprOf(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
Node *lexpr = a->lexpr;
|
2008-08-29 01:09:48 +02:00
|
|
|
Const *result;
|
2005-01-20 00:45:24 +01:00
|
|
|
ListCell *telem;
|
|
|
|
Oid ltype,
|
|
|
|
rtype;
|
|
|
|
bool matched = false;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
|
|
|
|
lexpr, NULL,
|
|
|
|
a->location);
|
|
|
|
|
|
|
|
lexpr = transformExprRecurse(pstate, lexpr);
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
ltype = exprType(lexpr);
|
|
|
|
foreach(telem, (List *) a->rexpr)
|
|
|
|
{
|
2010-10-25 20:40:46 +02:00
|
|
|
rtype = typenameTypeId(pstate, lfirst(telem));
|
2005-01-20 00:45:24 +01:00
|
|
|
matched = (rtype == ltype);
|
|
|
|
if (matched)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We have two forms: equals or not equals. Flip the sense of the result
|
2005-10-15 04:49:52 +02:00
|
|
|
* for not equals.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2005-11-28 05:35:32 +01:00
|
|
|
if (strcmp(strVal(linitial(a->name)), "<>") == 0)
|
2005-01-20 00:45:24 +01:00
|
|
|
matched = (!matched);
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
result = (Const *) makeBoolConst(matched, false);
|
|
|
|
|
|
|
|
/* Make the result have the original input's parse location */
|
|
|
|
result->location = exprLocation((Node *) a);
|
|
|
|
|
|
|
|
return (Node *) result;
|
2005-11-28 05:35:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformAExprIn(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
2008-10-26 03:46:25 +01:00
|
|
|
Node *result = NULL;
|
2005-11-28 05:35:32 +01:00
|
|
|
Node *lexpr;
|
|
|
|
List *rexprs;
|
2008-10-26 03:46:25 +01:00
|
|
|
List *rvars;
|
|
|
|
List *rnonvars;
|
2005-11-28 05:35:32 +01:00
|
|
|
bool useOr;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the operator is <>, combine with AND not OR.
|
|
|
|
*/
|
|
|
|
if (strcmp(strVal(linitial(a->name)), "<>") == 0)
|
|
|
|
useOr = false;
|
|
|
|
else
|
|
|
|
useOr = true;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate,
|
|
|
|
useOr ? PREC_GROUP_IN : PREC_GROUP_NOT_IN,
|
|
|
|
"IN",
|
|
|
|
a->lexpr, NULL,
|
|
|
|
a->location);
|
|
|
|
|
2005-11-28 05:35:32 +01:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
|
2013-06-10 00:39:20 +02:00
|
|
|
* possible if there is a suitable array type available. If not, we fall
|
|
|
|
* back to a boolean condition tree with multiple copies of the lefthand
|
2014-05-06 18:12:18 +02:00
|
|
|
* expression. Also, any IN-list items that contain Vars are handled as
|
2013-06-10 00:39:20 +02:00
|
|
|
* separate boolean conditions, because that gives the planner more scope
|
|
|
|
* for optimization on such clauses.
|
2005-11-28 05:35:32 +01:00
|
|
|
*
|
2013-06-10 00:39:20 +02:00
|
|
|
* First step: transform all the inputs, and detect whether any contain
|
|
|
|
* Vars.
|
2005-11-28 05:35:32 +01:00
|
|
|
*/
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
lexpr = transformExprRecurse(pstate, a->lexpr);
|
2008-10-26 03:46:25 +01:00
|
|
|
rexprs = rvars = rnonvars = NIL;
|
2005-11-28 05:35:32 +01:00
|
|
|
foreach(l, (List *) a->rexpr)
|
|
|
|
{
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
Node *rexpr = transformExprRecurse(pstate, lfirst(l));
|
2005-11-28 05:35:32 +01:00
|
|
|
|
|
|
|
rexprs = lappend(rexprs, rexpr);
|
2008-10-26 03:46:25 +01:00
|
|
|
if (contain_vars_of_level(rexpr, 0))
|
|
|
|
rvars = lappend(rvars, rexpr);
|
|
|
|
else
|
|
|
|
rnonvars = lappend(rnonvars, rexpr);
|
2005-11-28 05:35:32 +01:00
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2005-11-28 05:35:32 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* ScalarArrayOpExpr is only going to be useful if there's more than one
|
2013-06-10 00:39:20 +02:00
|
|
|
* non-Var righthand item.
|
2005-11-28 05:35:32 +01:00
|
|
|
*/
|
2013-06-10 00:39:20 +02:00
|
|
|
if (list_length(rnonvars) > 1)
|
2005-11-28 05:35:32 +01:00
|
|
|
{
|
2008-08-29 01:09:48 +02:00
|
|
|
List *allexprs;
|
2005-11-28 05:35:32 +01:00
|
|
|
Oid scalar_type;
|
|
|
|
Oid array_type;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Try to select a common type for the array elements. Note that
|
2008-10-25 19:19:09 +02:00
|
|
|
* since the LHS' type is first in the list, it will be preferred when
|
|
|
|
* there is doubt (eg, when all the RHS items are unknown literals).
|
2008-08-29 01:09:48 +02:00
|
|
|
*
|
2008-10-26 03:46:25 +01:00
|
|
|
* Note: use list_concat here not lcons, to avoid damaging rnonvars.
|
2005-11-28 05:35:32 +01:00
|
|
|
*/
|
2008-10-26 03:46:25 +01:00
|
|
|
allexprs = list_concat(list_make1(lexpr), rnonvars);
|
2008-10-25 19:19:09 +02:00
|
|
|
scalar_type = select_common_type(pstate, allexprs, NULL, NULL);
|
2005-11-28 05:35:32 +01:00
|
|
|
|
2013-06-10 00:39:20 +02:00
|
|
|
/*
|
|
|
|
* Do we have an array type to use? Aside from the case where there
|
|
|
|
* isn't one, we don't risk using ScalarArrayOpExpr when the common
|
|
|
|
* type is RECORD, because the RowExpr comparison logic below can cope
|
|
|
|
* with some cases of non-identical row types.
|
|
|
|
*/
|
|
|
|
if (OidIsValid(scalar_type) && scalar_type != RECORDOID)
|
2008-10-25 19:19:09 +02:00
|
|
|
array_type = get_array_type(scalar_type);
|
|
|
|
else
|
|
|
|
array_type = InvalidOid;
|
2005-11-28 05:35:32 +01:00
|
|
|
if (array_type != InvalidOid)
|
|
|
|
{
|
|
|
|
/*
|
2008-10-26 03:46:25 +01:00
|
|
|
* OK: coerce all the right-hand non-Var inputs to the common type
|
|
|
|
* and build an ArrayExpr for them.
|
2005-11-28 05:35:32 +01:00
|
|
|
*/
|
|
|
|
List *aexprs;
|
|
|
|
ArrayExpr *newa;
|
|
|
|
|
|
|
|
aexprs = NIL;
|
2008-10-26 03:46:25 +01:00
|
|
|
foreach(l, rnonvars)
|
2005-11-28 05:35:32 +01:00
|
|
|
{
|
|
|
|
Node *rexpr = (Node *) lfirst(l);
|
|
|
|
|
|
|
|
rexpr = coerce_to_common_type(pstate, rexpr,
|
|
|
|
scalar_type,
|
|
|
|
"IN");
|
|
|
|
aexprs = lappend(aexprs, rexpr);
|
|
|
|
}
|
|
|
|
newa = makeNode(ArrayExpr);
|
|
|
|
newa->array_typeid = array_type;
|
2011-03-20 01:29:08 +01:00
|
|
|
/* array_collid will be set by parse_collate.c */
|
2005-11-28 05:35:32 +01:00
|
|
|
newa->element_typeid = scalar_type;
|
|
|
|
newa->elements = aexprs;
|
|
|
|
newa->multidims = false;
|
2008-08-29 01:09:48 +02:00
|
|
|
newa->location = -1;
|
2005-11-28 05:35:32 +01:00
|
|
|
|
2008-10-26 03:46:25 +01:00
|
|
|
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;
|
2005-11-28 05:35:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must do it the hard way, ie, with a boolean expression tree.
|
|
|
|
*/
|
|
|
|
foreach(l, rexprs)
|
|
|
|
{
|
|
|
|
Node *rexpr = (Node *) lfirst(l);
|
|
|
|
Node *cmp;
|
|
|
|
|
2013-06-10 00:39:20 +02:00
|
|
|
if (IsA(lexpr, RowExpr) &&
|
|
|
|
IsA(rexpr, RowExpr))
|
2005-11-28 05:35:32 +01:00
|
|
|
{
|
2013-06-10 00:39:20 +02:00
|
|
|
/* ROW() op ROW() is handled specially */
|
2005-12-28 02:30:02 +01:00
|
|
|
cmp = make_row_comparison_op(pstate,
|
|
|
|
a->name,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
copyObject(((RowExpr *) lexpr)->args),
|
2006-03-14 23:48:25 +01:00
|
|
|
((RowExpr *) rexpr)->args,
|
|
|
|
a->location);
|
2005-11-28 05:35:32 +01:00
|
|
|
}
|
|
|
|
else
|
2013-06-10 00:39:20 +02:00
|
|
|
{
|
|
|
|
/* Ordinary scalar operator */
|
2005-11-28 05:35:32 +01:00
|
|
|
cmp = (Node *) make_op(pstate,
|
|
|
|
a->name,
|
|
|
|
copyObject(lexpr),
|
2006-03-14 23:48:25 +01:00
|
|
|
rexpr,
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
pstate->p_last_srf,
|
2006-03-14 23:48:25 +01:00
|
|
|
a->location);
|
2013-06-10 00:39:20 +02:00
|
|
|
}
|
2005-11-28 05:35:32 +01:00
|
|
|
|
|
|
|
cmp = coerce_to_boolean(pstate, cmp, "IN");
|
|
|
|
if (result == NULL)
|
|
|
|
result = cmp;
|
|
|
|
else
|
|
|
|
result = (Node *) makeBoolExpr(useOr ? OR_EXPR : AND_EXPR,
|
2008-08-29 01:09:48 +02:00
|
|
|
list_make2(result, cmp),
|
|
|
|
a->location);
|
2005-11-28 05:35:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
2015-02-22 19:57:56 +01:00
|
|
|
static Node *
|
|
|
|
transformAExprBetween(ParseState *pstate, A_Expr *a)
|
|
|
|
{
|
|
|
|
Node *aexpr;
|
|
|
|
Node *bexpr;
|
|
|
|
Node *cexpr;
|
|
|
|
Node *result;
|
|
|
|
Node *sub1;
|
|
|
|
Node *sub2;
|
|
|
|
List *args;
|
|
|
|
|
|
|
|
/* Deconstruct A_Expr into three subexprs */
|
|
|
|
aexpr = a->lexpr;
|
2017-02-21 17:33:07 +01:00
|
|
|
args = castNode(List, a->rexpr);
|
2015-02-22 19:57:56 +01:00
|
|
|
Assert(list_length(args) == 2);
|
|
|
|
bexpr = (Node *) linitial(args);
|
|
|
|
cexpr = (Node *) lsecond(args);
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
{
|
|
|
|
int opgroup;
|
|
|
|
const char *opname;
|
|
|
|
|
|
|
|
opgroup = operator_precedence_group((Node *) a, &opname);
|
|
|
|
emit_precedence_warnings(pstate, opgroup, opname,
|
|
|
|
aexpr, cexpr,
|
|
|
|
a->location);
|
|
|
|
/* We can ignore bexpr thanks to syntactic restrictions */
|
|
|
|
/* Wrap subexpressions to prevent extra warnings */
|
|
|
|
aexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, aexpr, NULL, -1);
|
|
|
|
bexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, bexpr, NULL, -1);
|
|
|
|
cexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, cexpr, NULL, -1);
|
|
|
|
}
|
|
|
|
|
2015-02-22 19:57:56 +01:00
|
|
|
/*
|
|
|
|
* Build the equivalent comparison expression. Make copies of
|
|
|
|
* multiply-referenced subexpressions for safety. (XXX this is really
|
|
|
|
* wrong since it results in multiple runtime evaluations of what may be
|
|
|
|
* volatile expressions ...)
|
|
|
|
*
|
|
|
|
* Ideally we would not use hard-wired operators here but instead use
|
|
|
|
* opclasses. However, mixed data types and other issues make this
|
|
|
|
* difficult:
|
|
|
|
* http://archives.postgresql.org/pgsql-hackers/2008-08/msg01142.php
|
|
|
|
*/
|
|
|
|
switch (a->kind)
|
|
|
|
{
|
|
|
|
case AEXPR_BETWEEN:
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=",
|
|
|
|
aexpr, bexpr,
|
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, "<=",
|
|
|
|
copyObject(aexpr), cexpr,
|
|
|
|
a->location));
|
|
|
|
result = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
|
|
|
|
break;
|
|
|
|
case AEXPR_NOT_BETWEEN:
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<",
|
|
|
|
aexpr, bexpr,
|
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, ">",
|
|
|
|
copyObject(aexpr), cexpr,
|
|
|
|
a->location));
|
|
|
|
result = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
|
|
|
|
break;
|
|
|
|
case AEXPR_BETWEEN_SYM:
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=",
|
|
|
|
aexpr, bexpr,
|
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, "<=",
|
|
|
|
copyObject(aexpr), cexpr,
|
|
|
|
a->location));
|
|
|
|
sub1 = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
copyObject(aexpr), copyObject(cexpr),
|
2015-02-22 19:57:56 +01:00
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, "<=",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
copyObject(aexpr), copyObject(bexpr),
|
2015-02-22 19:57:56 +01:00
|
|
|
a->location));
|
|
|
|
sub2 = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
|
|
|
|
args = list_make2(sub1, sub2);
|
|
|
|
result = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
|
|
|
|
break;
|
|
|
|
case AEXPR_NOT_BETWEEN_SYM:
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<",
|
|
|
|
aexpr, bexpr,
|
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, ">",
|
|
|
|
copyObject(aexpr), cexpr,
|
|
|
|
a->location));
|
|
|
|
sub1 = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
|
|
|
|
args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
copyObject(aexpr), copyObject(cexpr),
|
2015-02-22 19:57:56 +01:00
|
|
|
a->location),
|
|
|
|
makeSimpleA_Expr(AEXPR_OP, ">",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
copyObject(aexpr), copyObject(bexpr),
|
2015-02-22 19:57:56 +01:00
|
|
|
a->location));
|
|
|
|
sub2 = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
|
|
|
|
args = list_make2(sub1, sub2);
|
|
|
|
result = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
|
|
|
|
result = NULL; /* keep compiler quiet */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return transformExprRecurse(pstate, result);
|
|
|
|
}
|
|
|
|
|
2014-06-16 21:55:05 +02:00
|
|
|
static Node *
|
|
|
|
transformBoolExpr(ParseState *pstate, BoolExpr *a)
|
|
|
|
{
|
|
|
|
List *args = NIL;
|
|
|
|
const char *opname;
|
|
|
|
ListCell *lc;
|
|
|
|
|
|
|
|
switch (a->boolop)
|
|
|
|
{
|
|
|
|
case AND_EXPR:
|
|
|
|
opname = "AND";
|
|
|
|
break;
|
|
|
|
case OR_EXPR:
|
|
|
|
opname = "OR";
|
|
|
|
break;
|
|
|
|
case NOT_EXPR:
|
|
|
|
opname = "NOT";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized boolop: %d", (int) a->boolop);
|
|
|
|
opname = NULL; /* keep compiler quiet */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach(lc, a->args)
|
|
|
|
{
|
|
|
|
Node *arg = (Node *) lfirst(lc);
|
|
|
|
|
|
|
|
arg = transformExprRecurse(pstate, arg);
|
|
|
|
arg = coerce_to_boolean(pstate, arg, opname);
|
|
|
|
args = lappend(args, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Node *) makeBoolExpr(a->boolop, args, a->location);
|
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
|
|
|
transformFuncCall(ParseState *pstate, FuncCall *fn)
|
|
|
|
{
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
Node *last_srf = pstate->p_last_srf;
|
2005-01-20 00:45:24 +01:00
|
|
|
List *targs;
|
|
|
|
ListCell *args;
|
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
/* Transform the list of arguments ... */
|
|
|
|
targs = NIL;
|
|
|
|
foreach(args, fn->args)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
targs = lappend(targs, transformExprRecurse(pstate,
|
|
|
|
(Node *) lfirst(args)));
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
2013-07-17 02:15:36 +02:00
|
|
|
/*
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
* When WITHIN GROUP is used, we treat its ORDER BY expressions as
|
|
|
|
* additional arguments to the function, for purposes of function lookup
|
2014-05-06 18:12:18 +02:00
|
|
|
* and argument type coercion. So, transform each such expression and add
|
|
|
|
* them to the targs list. We don't explicitly mark where each argument
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
* came from, but ParseFuncOrColumn can tell what's what by reference to
|
|
|
|
* list_length(fn->agg_order).
|
2013-07-17 02:15:36 +02:00
|
|
|
*/
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
if (fn->agg_within_group)
|
|
|
|
{
|
|
|
|
Assert(fn->agg_order != NIL);
|
|
|
|
foreach(args, fn->agg_order)
|
|
|
|
{
|
|
|
|
SortBy *arg = (SortBy *) lfirst(args);
|
|
|
|
|
|
|
|
targs = lappend(targs, transformExpr(pstate, arg->node,
|
|
|
|
EXPR_KIND_ORDER_BY));
|
|
|
|
}
|
|
|
|
}
|
2013-07-17 02:15:36 +02:00
|
|
|
|
2008-07-16 03:30:23 +02:00
|
|
|
/* ... and hand off to ParseFuncOrColumn */
|
2010-07-30 01:16:33 +02:00
|
|
|
return ParseFuncOrColumn(pstate,
|
|
|
|
fn->funcname,
|
|
|
|
targs,
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
last_srf,
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
fn,
|
2017-11-30 14:46:13 +01:00
|
|
|
false,
|
2010-07-30 01:16:33 +02:00
|
|
|
fn->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
static Node *
|
|
|
|
transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
|
|
|
|
{
|
|
|
|
SubLink *sublink;
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
RowExpr *rexpr;
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
Query *qtree;
|
|
|
|
TargetEntry *tle;
|
|
|
|
|
|
|
|
/* We should only see this in first-stage processing of UPDATE tlists */
|
|
|
|
Assert(pstate->p_expr_kind == EXPR_KIND_UPDATE_SOURCE);
|
|
|
|
|
|
|
|
/* We only need to transform the source if this is the first column */
|
|
|
|
if (maref->colno == 1)
|
|
|
|
{
|
|
|
|
/*
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
* For now, we only allow EXPR SubLinks and RowExprs as the source of
|
|
|
|
* an UPDATE multiassignment. This is sufficient to cover interesting
|
|
|
|
* cases; at worst, someone would have to write (SELECT * FROM expr)
|
|
|
|
* to expand a composite-returning expression of another form.
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
*/
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
if (IsA(maref->source, SubLink) &&
|
|
|
|
((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK)
|
|
|
|
{
|
|
|
|
/* Relabel it as a MULTIEXPR_SUBLINK */
|
|
|
|
sublink = (SubLink *) maref->source;
|
|
|
|
sublink->subLinkType = MULTIEXPR_SUBLINK;
|
|
|
|
/* And transform it */
|
|
|
|
sublink = (SubLink *) transformExprRecurse(pstate,
|
|
|
|
(Node *) sublink);
|
|
|
|
|
2017-01-27 04:09:34 +01:00
|
|
|
qtree = castNode(Query, sublink->subselect);
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
|
|
|
|
/* Check subquery returns required number of columns */
|
|
|
|
if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("number of columns does not match number of values"),
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
parser_errposition(pstate, sublink->location)));
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
/*
|
|
|
|
* Build a resjunk tlist item containing the MULTIEXPR SubLink,
|
|
|
|
* and add it to pstate->p_multiassign_exprs, whence it will later
|
|
|
|
* get appended to the completed targetlist. We needn't worry
|
|
|
|
* about selecting a resno for it; transformUpdateStmt will do
|
|
|
|
* that.
|
|
|
|
*/
|
|
|
|
tle = makeTargetEntry((Expr *) sublink, 0, NULL, true);
|
|
|
|
pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs,
|
|
|
|
tle);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assign a unique-within-this-targetlist ID to the MULTIEXPR
|
|
|
|
* SubLink. We can just use its position in the
|
|
|
|
* p_multiassign_exprs list.
|
|
|
|
*/
|
|
|
|
sublink->subLinkId = list_length(pstate->p_multiassign_exprs);
|
|
|
|
}
|
|
|
|
else if (IsA(maref->source, RowExpr))
|
|
|
|
{
|
|
|
|
/* Transform the RowExpr, allowing SetToDefault items */
|
|
|
|
rexpr = (RowExpr *) transformRowExpr(pstate,
|
|
|
|
(RowExpr *) maref->source,
|
|
|
|
true);
|
|
|
|
|
|
|
|
/* Check it returns required number of columns */
|
|
|
|
if (list_length(rexpr->args) != maref->ncolumns)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("number of columns does not match number of values"),
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
parser_errposition(pstate, rexpr->location)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Temporarily append it to p_multiassign_exprs, so we can get it
|
|
|
|
* back when we come back here for additional columns.
|
|
|
|
*/
|
|
|
|
tle = makeTargetEntry((Expr *) rexpr, 0, NULL, true);
|
|
|
|
pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs,
|
|
|
|
tle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression"),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
parser_errposition(pstate, exprLocation(maref->source))));
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Second or later column in a multiassignment. Re-fetch the
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
* transformed SubLink or RowExpr, which we assume is still the last
|
|
|
|
* entry in p_multiassign_exprs.
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
*/
|
|
|
|
Assert(pstate->p_multiassign_exprs != NIL);
|
|
|
|
tle = (TargetEntry *) llast(pstate->p_multiassign_exprs);
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit the appropriate output expression for the current column
|
|
|
|
*/
|
|
|
|
if (IsA(tle->expr, SubLink))
|
|
|
|
{
|
|
|
|
Param *param;
|
|
|
|
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
sublink = (SubLink *) tle->expr;
|
|
|
|
Assert(sublink->subLinkType == MULTIEXPR_SUBLINK);
|
2017-01-27 04:09:34 +01:00
|
|
|
qtree = castNode(Query, sublink->subselect);
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
|
|
|
|
/* Build a Param representing the current subquery output column */
|
|
|
|
tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
|
|
|
|
Assert(!tle->resjunk);
|
|
|
|
|
|
|
|
param = makeNode(Param);
|
|
|
|
param->paramkind = PARAM_MULTIEXPR;
|
|
|
|
param->paramid = (sublink->subLinkId << 16) | maref->colno;
|
|
|
|
param->paramtype = exprType((Node *) tle->expr);
|
|
|
|
param->paramtypmod = exprTypmod((Node *) tle->expr);
|
|
|
|
param->paramcollid = exprCollation((Node *) tle->expr);
|
|
|
|
param->location = exprLocation((Node *) tle->expr);
|
|
|
|
|
|
|
|
return (Node *) param;
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
}
|
|
|
|
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
if (IsA(tle->expr, RowExpr))
|
|
|
|
{
|
|
|
|
Node *result;
|
|
|
|
|
|
|
|
rexpr = (RowExpr *) tle->expr;
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
/* Just extract and return the next element of the RowExpr */
|
|
|
|
result = (Node *) list_nth(rexpr->args, maref->colno - 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're at the last column, delete the RowExpr from
|
|
|
|
* p_multiassign_exprs; we don't need it anymore, and don't want it in
|
|
|
|
* the finished UPDATE tlist.
|
|
|
|
*/
|
|
|
|
if (maref->colno == maref->ncolumns)
|
|
|
|
pstate->p_multiassign_exprs =
|
|
|
|
list_delete_ptr(pstate->p_multiassign_exprs, tle);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
elog(ERROR, "unexpected expr type in multiassign list");
|
|
|
|
return NULL; /* keep compiler quiet */
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
|
|
|
transformCaseExpr(ParseState *pstate, CaseExpr *c)
|
|
|
|
{
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
CaseExpr *newc = makeNode(CaseExpr);
|
|
|
|
Node *last_srf = pstate->p_last_srf;
|
2005-01-20 00:45:24 +01:00
|
|
|
Node *arg;
|
|
|
|
CaseTestExpr *placeholder;
|
|
|
|
List *newargs;
|
2008-08-29 01:09:48 +02:00
|
|
|
List *resultexprs;
|
2005-01-20 00:45:24 +01:00
|
|
|
ListCell *l;
|
|
|
|
Node *defresult;
|
|
|
|
Oid ptype;
|
|
|
|
|
|
|
|
/* transform the test expression, if any */
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
arg = transformExprRecurse(pstate, (Node *) c->arg);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/* generate placeholder for test expression */
|
|
|
|
if (arg)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If test expression is an untyped literal, force it to text. We have
|
|
|
|
* to do something now because we won't be able to do this coercion on
|
|
|
|
* the placeholder. This is not as flexible as what was done in 7.4
|
|
|
|
* and before, but it's good enough to handle the sort of silly coding
|
|
|
|
* commonly seen.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
|
|
|
if (exprType(arg) == UNKNOWNOID)
|
|
|
|
arg = coerce_to_common_type(pstate, arg, TEXTOID, "CASE");
|
|
|
|
|
2011-03-20 01:29:08 +01:00
|
|
|
/*
|
|
|
|
* Run collation assignment on the test expression so that we know
|
2011-04-10 17:42:00 +02:00
|
|
|
* what collation to mark the placeholder with. In principle we could
|
|
|
|
* leave it to parse_collate.c to do that later, but propagating the
|
|
|
|
* result to the CaseTestExpr would be unnecessarily complicated.
|
2011-03-20 01:29:08 +01:00
|
|
|
*/
|
|
|
|
assign_expr_collations(pstate, arg);
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
placeholder = makeNode(CaseTestExpr);
|
|
|
|
placeholder->typeId = exprType(arg);
|
|
|
|
placeholder->typeMod = exprTypmod(arg);
|
2011-02-08 22:04:18 +01:00
|
|
|
placeholder->collation = exprCollation(arg);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
placeholder = NULL;
|
|
|
|
|
|
|
|
newc->arg = (Expr *) arg;
|
|
|
|
|
|
|
|
/* transform the list of arguments */
|
|
|
|
newargs = NIL;
|
2008-08-29 01:09:48 +02:00
|
|
|
resultexprs = NIL;
|
2005-01-20 00:45:24 +01:00
|
|
|
foreach(l, c->args)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
CaseWhen *w = lfirst_node(CaseWhen, l);
|
2005-01-20 00:45:24 +01:00
|
|
|
CaseWhen *neww = makeNode(CaseWhen);
|
|
|
|
Node *warg;
|
|
|
|
|
|
|
|
warg = (Node *) w->expr;
|
|
|
|
if (placeholder)
|
|
|
|
{
|
|
|
|
/* shorthand form was specified, so expand... */
|
|
|
|
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
|
|
|
|
(Node *) placeholder,
|
2006-03-14 23:48:25 +01:00
|
|
|
warg,
|
2008-08-29 01:09:48 +02:00
|
|
|
w->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
neww->expr = (Expr *) transformExprRecurse(pstate, warg);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
neww->expr = (Expr *) coerce_to_boolean(pstate,
|
|
|
|
(Node *) neww->expr,
|
|
|
|
"CASE/WHEN");
|
|
|
|
|
|
|
|
warg = (Node *) w->result;
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
neww->result = (Expr *) transformExprRecurse(pstate, warg);
|
2008-08-29 01:09:48 +02:00
|
|
|
neww->location = w->location;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
newargs = lappend(newargs, neww);
|
2008-08-29 01:09:48 +02:00
|
|
|
resultexprs = lappend(resultexprs, neww->result);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
newc->args = newargs;
|
|
|
|
|
|
|
|
/* transform the default clause */
|
|
|
|
defresult = (Node *) c->defresult;
|
|
|
|
if (defresult == NULL)
|
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
|
|
|
|
n->val.type = T_Null;
|
2008-08-29 01:09:48 +02:00
|
|
|
n->location = -1;
|
2005-01-20 00:45:24 +01:00
|
|
|
defresult = (Node *) n;
|
|
|
|
}
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newc->defresult = (Expr *) transformExprRecurse(pstate, defresult);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: default result is considered the most significant type in
|
2005-10-15 04:49:52 +02:00
|
|
|
* determining preferred type. This is how the code worked before, but it
|
|
|
|
* seems a little bogus to me --- tgl
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2008-08-29 01:09:48 +02:00
|
|
|
resultexprs = lcons(newc->defresult, resultexprs);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
ptype = select_common_type(pstate, resultexprs, "CASE", NULL);
|
2005-01-20 00:45:24 +01:00
|
|
|
Assert(OidIsValid(ptype));
|
|
|
|
newc->casetype = ptype;
|
2011-03-20 01:29:08 +01:00
|
|
|
/* casecollid will be set by parse_collate.c */
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/* Convert default result clause, if necessary */
|
|
|
|
newc->defresult = (Expr *)
|
|
|
|
coerce_to_common_type(pstate,
|
|
|
|
(Node *) newc->defresult,
|
|
|
|
ptype,
|
|
|
|
"CASE/ELSE");
|
|
|
|
|
|
|
|
/* Convert when-clause results, if necessary */
|
|
|
|
foreach(l, newc->args)
|
|
|
|
{
|
|
|
|
CaseWhen *w = (CaseWhen *) lfirst(l);
|
|
|
|
|
|
|
|
w->result = (Expr *)
|
|
|
|
coerce_to_common_type(pstate,
|
|
|
|
(Node *) w->result,
|
|
|
|
ptype,
|
|
|
|
"CASE/WHEN");
|
|
|
|
}
|
|
|
|
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
/* if any subexpression contained a SRF, complain */
|
|
|
|
if (pstate->p_last_srf != last_srf)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
/* translator: %s is name of a SQL construct, eg GROUP BY */
|
|
|
|
errmsg("set-returning functions are not allowed in %s",
|
|
|
|
"CASE"),
|
|
|
|
errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
|
|
|
|
parser_errposition(pstate,
|
|
|
|
exprLocation(pstate->p_last_srf))));
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
newc->location = c->location;
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
return (Node *) newc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformSubLink(ParseState *pstate, SubLink *sublink)
|
|
|
|
{
|
|
|
|
Node *result = (Node *) sublink;
|
2007-06-24 00:12:52 +02:00
|
|
|
Query *qtree;
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
const char *err;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
/*
|
2013-05-29 22:58:43 +02:00
|
|
|
* Check to see if the sublink is in an invalid place within the query. We
|
|
|
|
* allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE, but generally
|
|
|
|
* not in utility statements.
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
*/
|
|
|
|
err = NULL;
|
|
|
|
switch (pstate->p_expr_kind)
|
|
|
|
{
|
|
|
|
case EXPR_KIND_NONE:
|
|
|
|
Assert(false); /* can't happen */
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_OTHER:
|
|
|
|
/* Accept sublink here; caller must throw error if wanted */
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_JOIN_ON:
|
|
|
|
case EXPR_KIND_JOIN_USING:
|
|
|
|
case EXPR_KIND_FROM_SUBSELECT:
|
|
|
|
case EXPR_KIND_FROM_FUNCTION:
|
|
|
|
case EXPR_KIND_WHERE:
|
2015-07-30 00:37:48 +02:00
|
|
|
case EXPR_KIND_POLICY:
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
case EXPR_KIND_HAVING:
|
2013-07-17 02:15:36 +02:00
|
|
|
case EXPR_KIND_FILTER:
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
case EXPR_KIND_WINDOW_PARTITION:
|
|
|
|
case EXPR_KIND_WINDOW_ORDER:
|
|
|
|
case EXPR_KIND_WINDOW_FRAME_RANGE:
|
|
|
|
case EXPR_KIND_WINDOW_FRAME_ROWS:
|
|
|
|
case EXPR_KIND_SELECT_TARGET:
|
|
|
|
case EXPR_KIND_INSERT_TARGET:
|
|
|
|
case EXPR_KIND_UPDATE_SOURCE:
|
|
|
|
case EXPR_KIND_UPDATE_TARGET:
|
|
|
|
case EXPR_KIND_GROUP_BY:
|
|
|
|
case EXPR_KIND_ORDER_BY:
|
|
|
|
case EXPR_KIND_DISTINCT_ON:
|
|
|
|
case EXPR_KIND_LIMIT:
|
|
|
|
case EXPR_KIND_OFFSET:
|
|
|
|
case EXPR_KIND_RETURNING:
|
|
|
|
case EXPR_KIND_VALUES:
|
2017-01-16 21:23:11 +01:00
|
|
|
case EXPR_KIND_VALUES_SINGLE:
|
2017-11-30 14:46:13 +01:00
|
|
|
case EXPR_KIND_CALL:
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
/* okay */
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
|
|
|
case EXPR_KIND_DOMAIN_CHECK:
|
2013-01-05 14:25:21 +01:00
|
|
|
err = _("cannot use subquery in check constraint");
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
break;
|
|
|
|
case EXPR_KIND_COLUMN_DEFAULT:
|
|
|
|
case EXPR_KIND_FUNCTION_DEFAULT:
|
|
|
|
err = _("cannot use subquery in DEFAULT expression");
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_INDEX_EXPRESSION:
|
|
|
|
err = _("cannot use subquery in index expression");
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_INDEX_PREDICATE:
|
|
|
|
err = _("cannot use subquery in index predicate");
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_ALTER_COL_TRANSFORM:
|
|
|
|
err = _("cannot use subquery in transform expression");
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_EXECUTE_PARAMETER:
|
|
|
|
err = _("cannot use subquery in EXECUTE parameter");
|
|
|
|
break;
|
|
|
|
case EXPR_KIND_TRIGGER_WHEN:
|
|
|
|
err = _("cannot use subquery in trigger WHEN condition");
|
|
|
|
break;
|
Implement table partitioning.
Table partitioning is like table inheritance and reuses much of the
existing infrastructure, but there are some important differences.
The parent is called a partitioned table and is always empty; it may
not have indexes or non-inherited constraints, since those make no
sense for a relation with no data of its own. The children are called
partitions and contain all of the actual data. Each partition has an
implicit partitioning constraint. Multiple inheritance is not
allowed, and partitioning and inheritance can't be mixed. Partitions
can't have extra columns and may not allow nulls unless the parent
does. Tuples inserted into the parent are automatically routed to the
correct partition, so tuple-routing ON INSERT triggers are not needed.
Tuple routing isn't yet supported for partitions which are foreign
tables, and it doesn't handle updates that cross partition boundaries.
Currently, tables can be range-partitioned or list-partitioned. List
partitioning is limited to a single column, but range partitioning can
involve multiple columns. A partitioning "column" can be an
expression.
Because table partitioning is less general than table inheritance, it
is hoped that it will be easier to reason about properties of
partitions, and therefore that this will serve as a better foundation
for a variety of possible optimizations, including query planner
optimizations. The tuple routing based which this patch does based on
the implicit partitioning constraints is an example of this, but it
seems likely that many other useful optimizations are also possible.
Amit Langote, reviewed and tested by Robert Haas, Ashutosh Bapat,
Amit Kapila, Rajkumar Raghuwanshi, Corey Huinker, Jaime Casanova,
Rushabh Lathia, Erik Rijkers, among others. Minor revisions by me.
2016-12-07 19:17:43 +01:00
|
|
|
case EXPR_KIND_PARTITION_EXPRESSION:
|
|
|
|
err = _("cannot use subquery in partition key expression");
|
|
|
|
break;
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is intentionally no default: case here, so that the
|
|
|
|
* compiler will warn if we add a new ParseExprKind without
|
|
|
|
* extending this switch. If we do see an unrecognized value at
|
|
|
|
* runtime, the behavior will be the same as for EXPR_KIND_OTHER,
|
|
|
|
* which is sane anyway.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
if (err)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg_internal("%s", err),
|
|
|
|
parser_errposition(pstate, sublink->location)));
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
pstate->p_hasSubLinks = true;
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, let's transform the sub-SELECT.
|
|
|
|
*/
|
Change unknown-type literals to type text in SELECT and RETURNING lists.
Previously, we left such literals alone if the query or subquery had
no properties forcing a type decision to be made (such as an ORDER BY or
DISTINCT clause using that output column). This meant that "unknown" could
be an exposed output column type, which has never been a great idea because
it could result in strange failures later on. For example, an outer query
that tried to do any operations on an unknown-type subquery output would
generally fail with some weird error like "failed to find conversion
function from unknown to text" or "could not determine which collation to
use for string comparison". Also, if the case occurred in a CREATE VIEW's
query then the view would have an unknown-type column, causing similar
failures in queries trying to use the view.
To fix, at the tail end of parse analysis of a query, forcibly convert any
remaining "unknown" literals in its SELECT or RETURNING list to type text.
However, provide a switch to suppress that, and use it in the cases of
SELECT inside a set operation or INSERT command. In those cases we already
had type resolution rules that make use of context information from outside
the subquery proper, and we don't want to change that behavior.
Also, change creation of an unknown-type column in a relation from a
warning to a hard error. The error should be unreachable now in CREATE
VIEW or CREATE MATVIEW, but it's still possible to explicitly say "unknown"
in CREATE TABLE or CREATE (composite) TYPE. We want to forbid that because
it's nothing but a foot-gun.
This change creates a pg_upgrade failure case: a matview that contains an
unknown-type column can't be pg_upgraded, because reparsing the matview's
defining query will now decide that the column is of type text, which
doesn't match the cstring-like storage that the old materialized column
would actually have. Add a checking pass to detect that. While at it,
we can detect tables or composite types that would fail, essentially
for free. Those would fail safely anyway later on, but we might as
well fail earlier.
This patch is by me, but it owes something to previous investigations
by Rahila Syed. Also thanks to Ashutosh Bapat and Michael Paquier for
review.
Discussion: https://postgr.es/m/CAH2L28uwwbL9HUM-WR=hromW1Cvamkn7O-g8fPY2m=_7muJ0oA@mail.gmail.com
2017-01-25 15:17:18 +01:00
|
|
|
qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true);
|
2008-09-01 22:42:46 +02:00
|
|
|
|
|
|
|
/*
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
* Check that we got a SELECT. Anything else should be impossible given
|
|
|
|
* restrictions of the grammar, but check anyway.
|
2008-09-01 22:42:46 +02:00
|
|
|
*/
|
|
|
|
if (!IsA(qtree, Query) ||
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
qtree->commandType != CMD_SELECT)
|
2008-09-01 22:42:46 +02:00
|
|
|
elog(ERROR, "unexpected non-SELECT command in SubLink");
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
sublink->subselect = (Node *) qtree;
|
|
|
|
|
|
|
|
if (sublink->subLinkType == EXISTS_SUBLINK)
|
|
|
|
{
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* EXISTS needs no test expression or combining operator. These fields
|
|
|
|
* should be null already, but make sure.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2005-12-28 02:30:02 +01:00
|
|
|
sublink->testexpr = NULL;
|
2005-01-20 00:45:24 +01:00
|
|
|
sublink->operName = NIL;
|
|
|
|
}
|
|
|
|
else if (sublink->subLinkType == EXPR_SUBLINK ||
|
|
|
|
sublink->subLinkType == ARRAY_SUBLINK)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Make sure the subselect delivers a single column (ignoring resjunk
|
|
|
|
* targets).
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
if (count_nonjunk_tlist_entries(qtree->targetList) != 1)
|
2005-01-20 00:45:24 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
errmsg("subquery must return only one column"),
|
2008-08-29 01:09:48 +02:00
|
|
|
parser_errposition(pstate, sublink->location)));
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* EXPR and ARRAY need no test expression or combining operator. These
|
|
|
|
* fields should be null already, but make sure.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2005-12-28 02:30:02 +01:00
|
|
|
sublink->testexpr = NULL;
|
2005-01-20 00:45:24 +01:00
|
|
|
sublink->operName = NIL;
|
|
|
|
}
|
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns
(but only one row) to be used to compute the new values of several columns
to be updated. While the same results can be had with an independent
sub-SELECT per column, such a workaround can require a great deal of
duplicated computation.
The standard actually says that the source for a multi-column assignment
could be any row-valued expression. The implementation used here is
tightly tied to our existing sub-SELECT support and can't handle other
cases; the Bison grammar would have some issues with them too. However,
I don't feel too bad about this since other cases can be converted into
sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could
be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
2014-06-18 19:22:25 +02:00
|
|
|
else if (sublink->subLinkType == MULTIEXPR_SUBLINK)
|
|
|
|
{
|
|
|
|
/* Same as EXPR case, except no restriction on number of columns */
|
|
|
|
sublink->testexpr = NULL;
|
|
|
|
sublink->operName = NIL;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
else
|
|
|
|
{
|
2005-12-28 02:30:02 +01:00
|
|
|
/* ALL, ANY, or ROWCOMPARE: generate row-comparing expression */
|
|
|
|
Node *lefthand;
|
|
|
|
List *left_list;
|
|
|
|
List *right_list;
|
2005-01-20 00:45:24 +01:00
|
|
|
ListCell *l;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
{
|
|
|
|
if (sublink->operName == NIL)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_IN, "IN",
|
|
|
|
sublink->testexpr, NULL,
|
|
|
|
sublink->location);
|
|
|
|
else
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP,
|
|
|
|
strVal(llast(sublink->operName)),
|
|
|
|
sublink->testexpr, NULL,
|
|
|
|
sublink->location);
|
|
|
|
}
|
|
|
|
|
2015-02-23 18:46:46 +01:00
|
|
|
/*
|
|
|
|
* If the source was "x IN (select)", convert to "x = ANY (select)".
|
|
|
|
*/
|
|
|
|
if (sublink->operName == NIL)
|
|
|
|
sublink->operName = list_make1(makeString("="));
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
/*
|
2005-12-28 02:30:02 +01:00
|
|
|
* Transform lefthand expression, and convert to a list
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
lefthand = transformExprRecurse(pstate, sublink->testexpr);
|
2005-12-28 02:30:02 +01:00
|
|
|
if (lefthand && IsA(lefthand, RowExpr))
|
|
|
|
left_list = ((RowExpr *) lefthand)->args;
|
2005-01-20 00:45:24 +01:00
|
|
|
else
|
2005-12-28 02:30:02 +01:00
|
|
|
left_list = list_make1(lefthand);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Build a list of PARAM_SUBLINK nodes representing the output columns
|
|
|
|
* of the subquery.
|
2005-01-20 00:45:24 +01:00
|
|
|
*/
|
2005-12-28 02:30:02 +01:00
|
|
|
right_list = NIL;
|
|
|
|
foreach(l, qtree->targetList)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
|
|
|
TargetEntry *tent = (TargetEntry *) lfirst(l);
|
2005-12-28 02:30:02 +01:00
|
|
|
Param *param;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2005-04-06 18:34:07 +02:00
|
|
|
if (tent->resjunk)
|
2005-01-20 00:45:24 +01:00
|
|
|
continue;
|
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
param = makeNode(Param);
|
|
|
|
param->paramkind = PARAM_SUBLINK;
|
2006-04-22 03:26:01 +02:00
|
|
|
param->paramid = tent->resno;
|
2005-12-28 02:30:02 +01:00
|
|
|
param->paramtype = exprType((Node *) tent->expr);
|
2006-12-10 23:13:27 +01:00
|
|
|
param->paramtypmod = exprTypmod((Node *) tent->expr);
|
2011-03-20 01:29:08 +01:00
|
|
|
param->paramcollid = exprCollation((Node *) tent->expr);
|
2008-08-29 01:09:48 +02:00
|
|
|
param->location = -1;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
right_list = lappend(right_list, param);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
2005-12-28 02:30:02 +01:00
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We could rely on make_row_comparison_op to complain if the list
|
|
|
|
* lengths differ, but we prefer to generate a more specific error
|
|
|
|
* message.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
if (list_length(left_list) < list_length(right_list))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2008-08-29 01:09:48 +02:00
|
|
|
errmsg("subquery has too many columns"),
|
|
|
|
parser_errposition(pstate, sublink->location)));
|
2005-12-28 02:30:02 +01:00
|
|
|
if (list_length(left_list) > list_length(right_list))
|
2005-01-20 00:45:24 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2008-08-29 01:09:48 +02:00
|
|
|
errmsg("subquery has too few columns"),
|
|
|
|
parser_errposition(pstate, sublink->location)));
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
/*
|
|
|
|
* Identify the combining operator(s) and generate a suitable
|
|
|
|
* row-comparison expression.
|
|
|
|
*/
|
|
|
|
sublink->testexpr = make_row_comparison_op(pstate,
|
|
|
|
sublink->operName,
|
|
|
|
left_list,
|
2006-03-14 23:48:25 +01:00
|
|
|
right_list,
|
2008-08-29 01:09:48 +02:00
|
|
|
sublink->location);
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
/*
|
|
|
|
* transformArrayExpr
|
|
|
|
*
|
|
|
|
* If the caller specifies the target type, the resulting array will
|
|
|
|
* be of exactly that type. Otherwise we try to infer a common type
|
|
|
|
* for the elements using select_common_type().
|
|
|
|
*/
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
2008-03-20 22:42:48 +01:00
|
|
|
transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
|
|
|
|
Oid array_type, Oid element_type, int32 typmod)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
|
|
|
ArrayExpr *newa = makeNode(ArrayExpr);
|
|
|
|
List *newelems = NIL;
|
|
|
|
List *newcoercedelems = NIL;
|
|
|
|
ListCell *element;
|
2008-03-20 22:42:48 +01:00
|
|
|
Oid coerce_type;
|
|
|
|
bool coerce_hard;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
/*
|
|
|
|
* Transform the element expressions
|
2008-03-20 22:42:48 +01:00
|
|
|
*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Assume that the array is one-dimensional unless we find an array-type
|
|
|
|
* element expression.
|
|
|
|
*/
|
2008-03-20 22:42:48 +01:00
|
|
|
newa->multidims = false;
|
2005-01-20 00:45:24 +01:00
|
|
|
foreach(element, a->elements)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(element);
|
|
|
|
Node *newe;
|
2008-03-20 22:42:48 +01:00
|
|
|
|
2016-04-22 05:17:36 +02:00
|
|
|
/* Look through AEXPR_PAREN nodes so they don't affect test below */
|
|
|
|
while (e && IsA(e, A_Expr) &&
|
|
|
|
((A_Expr *) e)->kind == AEXPR_PAREN)
|
|
|
|
e = ((A_Expr *) e)->lexpr;
|
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* If an element is itself an A_ArrayExpr, recurse directly so that we
|
|
|
|
* can pass down any target type we were given.
|
2008-03-20 22:42:48 +01:00
|
|
|
*/
|
|
|
|
if (IsA(e, A_ArrayExpr))
|
|
|
|
{
|
|
|
|
newe = transformArrayExpr(pstate,
|
|
|
|
(A_ArrayExpr *) e,
|
|
|
|
array_type,
|
|
|
|
element_type,
|
|
|
|
typmod);
|
|
|
|
/* we certainly have an array here */
|
2008-08-29 01:09:48 +02:00
|
|
|
Assert(array_type == InvalidOid || array_type == exprType(newe));
|
2008-03-20 22:42:48 +01:00
|
|
|
newa->multidims = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newe = transformExprRecurse(pstate, e);
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Check for sub-array expressions, if we haven't already found
|
|
|
|
* one.
|
2008-03-20 22:42:48 +01:00
|
|
|
*/
|
2008-08-29 01:09:48 +02:00
|
|
|
if (!newa->multidims && type_is_array(exprType(newe)))
|
2008-03-20 22:42:48 +01:00
|
|
|
newa->multidims = true;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
newelems = lappend(newelems, newe);
|
|
|
|
}
|
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
/*
|
2008-03-20 22:42:48 +01:00
|
|
|
* Select a target type for the elements.
|
|
|
|
*
|
|
|
|
* If we haven't been given a target array type, we must try to deduce a
|
|
|
|
* common type based on the types of the individual elements present.
|
|
|
|
*/
|
|
|
|
if (OidIsValid(array_type))
|
|
|
|
{
|
|
|
|
/* Caller must ensure array_type matches element_type */
|
|
|
|
Assert(OidIsValid(element_type));
|
|
|
|
coerce_type = (newa->multidims ? array_type : element_type);
|
|
|
|
coerce_hard = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Can't handle an empty array without a target type */
|
2008-08-29 01:09:48 +02:00
|
|
|
if (newelems == NIL)
|
2008-03-20 22:42:48 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_DATATYPE),
|
|
|
|
errmsg("cannot determine type of empty array"),
|
|
|
|
errhint("Explicitly cast to the desired type, "
|
2008-08-29 01:09:48 +02:00
|
|
|
"for example ARRAY[]::integer[]."),
|
|
|
|
parser_errposition(pstate, a->location)));
|
2008-03-20 22:42:48 +01:00
|
|
|
|
|
|
|
/* Select a common type for the elements */
|
2008-08-29 01:09:48 +02:00
|
|
|
coerce_type = select_common_type(pstate, newelems, "ARRAY", NULL);
|
2008-03-20 22:42:48 +01:00
|
|
|
|
|
|
|
if (newa->multidims)
|
|
|
|
{
|
|
|
|
array_type = coerce_type;
|
|
|
|
element_type = get_element_type(array_type);
|
|
|
|
if (!OidIsValid(element_type))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("could not find element type for data type %s",
|
|
|
|
format_type_be(array_type)),
|
2008-09-01 22:42:46 +02:00
|
|
|
parser_errposition(pstate, a->location)));
|
2008-03-20 22:42:48 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
element_type = coerce_type;
|
|
|
|
array_type = get_array_type(element_type);
|
|
|
|
if (!OidIsValid(array_type))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("could not find array type for data type %s",
|
2008-09-01 22:42:46 +02:00
|
|
|
format_type_be(element_type)),
|
|
|
|
parser_errposition(pstate, a->location)));
|
2008-03-20 22:42:48 +01:00
|
|
|
}
|
|
|
|
coerce_hard = false;
|
|
|
|
}
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Coerce elements to target type
|
2008-03-20 22:42:48 +01:00
|
|
|
*
|
|
|
|
* If the array has been explicitly cast, then the elements are in turn
|
|
|
|
* explicitly coerced.
|
|
|
|
*
|
|
|
|
* If the array's type was merely derived from the common type of its
|
|
|
|
* elements, then the elements are implicitly coerced to the common type.
|
|
|
|
* This is consistent with other uses of select_common_type().
|
2009-06-11 16:49:15 +02:00
|
|
|
*/
|
2005-01-20 00:45:24 +01:00
|
|
|
foreach(element, newelems)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(element);
|
|
|
|
Node *newe;
|
|
|
|
|
2008-03-20 22:42:48 +01:00
|
|
|
if (coerce_hard)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
newe = coerce_to_target_type(pstate, e,
|
2008-03-20 22:42:48 +01:00
|
|
|
exprType(e),
|
2009-06-11 16:49:15 +02:00
|
|
|
coerce_type,
|
2008-03-20 22:42:48 +01:00
|
|
|
typmod,
|
|
|
|
COERCION_EXPLICIT,
|
2008-08-29 01:09:48 +02:00
|
|
|
COERCE_EXPLICIT_CAST,
|
|
|
|
-1);
|
2008-03-20 22:42:48 +01:00
|
|
|
if (newe == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(exprType(e)),
|
2008-08-29 01:09:48 +02:00
|
|
|
format_type_be(coerce_type)),
|
|
|
|
parser_errposition(pstate, exprLocation(e))));
|
2008-03-20 22:42:48 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
newe = coerce_to_common_type(pstate, e,
|
|
|
|
coerce_type,
|
|
|
|
"ARRAY");
|
2005-01-20 00:45:24 +01:00
|
|
|
newcoercedelems = lappend(newcoercedelems, newe);
|
|
|
|
}
|
|
|
|
|
|
|
|
newa->array_typeid = array_type;
|
2011-03-20 01:29:08 +01:00
|
|
|
/* array_collid will be set by parse_collate.c */
|
2005-01-20 00:45:24 +01:00
|
|
|
newa->element_typeid = element_type;
|
|
|
|
newa->elements = newcoercedelems;
|
2008-08-29 01:09:48 +02:00
|
|
|
newa->location = a->location;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
return (Node *) newa;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault)
|
2005-01-20 00:45:24 +01:00
|
|
|
{
|
2012-12-23 20:07:24 +01:00
|
|
|
RowExpr *newr;
|
2012-02-14 23:34:19 +01:00
|
|
|
char fname[16];
|
|
|
|
int fnum;
|
|
|
|
ListCell *lc;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
2012-12-23 20:07:24 +01:00
|
|
|
newr = makeNode(RowExpr);
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
/* Transform the field expressions */
|
Improve handling of "UPDATE ... SET (column_list) = row_constructor".
Previously, the right-hand side of a multiple-column assignment, if it
wasn't a sub-SELECT, had to be a simple parenthesized expression list,
because gram.y was responsible for "bursting" the construct into
independent column assignments. This had the minor defect that you
couldn't write ROW (though you should be able to, since the standard says
this is a row constructor), and the rather larger defect that unlike other
uses of row constructors, we would not expand a "foo.*" item into multiple
columns.
Fix that by changing the RHS to be just "a_expr" in the grammar, leaving
it to transformMultiAssignRef to separate the elements of a RowExpr;
which it will do only after performing standard transformation of the
RowExpr, so that "foo.*" behaves as expected.
The key reason we didn't do that before was the hard-wired handling of
DEFAULT tokens (SetToDefault nodes). This patch deals with that issue by
allowing DEFAULT in any a_expr and having parse analysis throw an error
if SetToDefault is found in an unexpected place. That's an improvement
anyway since the error can be more specific than just "syntax error".
The SQL standard suggests that the RHS could be any a_expr yielding a
suitable row value. This patch doesn't really move the goal posts in that
respect --- you're still limited to RowExpr or a sub-SELECT --- but it does
fix the grammar restriction, so it provides some tangible progress towards
a full implementation. And the limitation is now documented by an explicit
error message rather than an unhelpful "syntax error".
Discussion: <8542.1479742008@sss.pgh.pa.us>
2016-11-22 21:19:57 +01:00
|
|
|
newr->args = transformExpressionList(pstate, r->args,
|
|
|
|
pstate->p_expr_kind, allowDefault);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/* Barring later casting, we consider the type RECORD */
|
|
|
|
newr->row_typeid = RECORDOID;
|
|
|
|
newr->row_format = COERCE_IMPLICIT_CAST;
|
2012-02-14 23:34:19 +01:00
|
|
|
|
|
|
|
/* ROW() has anonymous columns, so invent some field names */
|
|
|
|
newr->colnames = NIL;
|
|
|
|
fnum = 1;
|
|
|
|
foreach(lc, newr->args)
|
|
|
|
{
|
|
|
|
snprintf(fname, sizeof(fname), "f%d", fnum++);
|
|
|
|
newr->colnames = lappend(newr->colnames, makeString(pstrdup(fname)));
|
|
|
|
}
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
newr->location = r->location;
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
return (Node *) newr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Node *
|
|
|
|
transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
|
|
|
|
{
|
|
|
|
CoalesceExpr *newc = makeNode(CoalesceExpr);
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
Node *last_srf = pstate->p_last_srf;
|
2005-01-20 00:45:24 +01:00
|
|
|
List *newargs = NIL;
|
|
|
|
List *newcoercedargs = NIL;
|
|
|
|
ListCell *args;
|
|
|
|
|
|
|
|
foreach(args, c->args)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(args);
|
|
|
|
Node *newe;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newe = transformExprRecurse(pstate, e);
|
2005-01-20 00:45:24 +01:00
|
|
|
newargs = lappend(newargs, newe);
|
|
|
|
}
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
newc->coalescetype = select_common_type(pstate, newargs, "COALESCE", NULL);
|
2011-03-20 01:29:08 +01:00
|
|
|
/* coalescecollid will be set by parse_collate.c */
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
/* Convert arguments if necessary */
|
|
|
|
foreach(args, newargs)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(args);
|
|
|
|
Node *newe;
|
|
|
|
|
|
|
|
newe = coerce_to_common_type(pstate, e,
|
|
|
|
newc->coalescetype,
|
|
|
|
"COALESCE");
|
|
|
|
newcoercedargs = lappend(newcoercedargs, newe);
|
|
|
|
}
|
|
|
|
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
/* if any subexpression contained a SRF, complain */
|
|
|
|
if (pstate->p_last_srf != last_srf)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
/* translator: %s is name of a SQL construct, eg GROUP BY */
|
|
|
|
errmsg("set-returning functions are not allowed in %s",
|
|
|
|
"COALESCE"),
|
|
|
|
errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
|
|
|
|
parser_errposition(pstate,
|
|
|
|
exprLocation(pstate->p_last_srf))));
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
newc->args = newcoercedargs;
|
2008-08-29 01:09:48 +02:00
|
|
|
newc->location = c->location;
|
2005-01-20 00:45:24 +01:00
|
|
|
return (Node *) newc;
|
|
|
|
}
|
|
|
|
|
2005-06-27 00:05:42 +02:00
|
|
|
static Node *
|
|
|
|
transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
|
|
|
|
{
|
|
|
|
MinMaxExpr *newm = makeNode(MinMaxExpr);
|
|
|
|
List *newargs = NIL;
|
|
|
|
List *newcoercedargs = NIL;
|
2008-08-29 01:09:48 +02:00
|
|
|
const char *funcname = (m->op == IS_GREATEST) ? "GREATEST" : "LEAST";
|
2005-06-27 00:05:42 +02:00
|
|
|
ListCell *args;
|
|
|
|
|
|
|
|
newm->op = m->op;
|
|
|
|
foreach(args, m->args)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(args);
|
|
|
|
Node *newe;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newe = transformExprRecurse(pstate, e);
|
2005-06-27 00:05:42 +02:00
|
|
|
newargs = lappend(newargs, newe);
|
|
|
|
}
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
newm->minmaxtype = select_common_type(pstate, newargs, funcname, NULL);
|
2011-03-20 01:29:08 +01:00
|
|
|
/* minmaxcollid and inputcollid will be set by parse_collate.c */
|
2005-06-27 00:05:42 +02:00
|
|
|
|
|
|
|
/* Convert arguments if necessary */
|
|
|
|
foreach(args, newargs)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(args);
|
|
|
|
Node *newe;
|
|
|
|
|
|
|
|
newe = coerce_to_common_type(pstate, e,
|
|
|
|
newm->minmaxtype,
|
2008-08-29 01:09:48 +02:00
|
|
|
funcname);
|
2005-06-27 00:05:42 +02:00
|
|
|
newcoercedargs = lappend(newcoercedargs, newe);
|
|
|
|
}
|
|
|
|
|
|
|
|
newm->args = newcoercedargs;
|
2008-08-29 01:09:48 +02:00
|
|
|
newm->location = m->location;
|
2005-06-27 00:05:42 +02:00
|
|
|
return (Node *) newm;
|
|
|
|
}
|
|
|
|
|
2016-08-17 02:33:01 +02:00
|
|
|
static Node *
|
|
|
|
transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* All we need to do is insert the correct result type and (where needed)
|
|
|
|
* validate the typmod, so we just modify the node in-place.
|
|
|
|
*/
|
|
|
|
switch (svf->op)
|
|
|
|
{
|
|
|
|
case SVFOP_CURRENT_DATE:
|
|
|
|
svf->type = DATEOID;
|
|
|
|
break;
|
|
|
|
case SVFOP_CURRENT_TIME:
|
|
|
|
svf->type = TIMETZOID;
|
|
|
|
break;
|
|
|
|
case SVFOP_CURRENT_TIME_N:
|
|
|
|
svf->type = TIMETZOID;
|
|
|
|
svf->typmod = anytime_typmod_check(true, svf->typmod);
|
|
|
|
break;
|
|
|
|
case SVFOP_CURRENT_TIMESTAMP:
|
|
|
|
svf->type = TIMESTAMPTZOID;
|
|
|
|
break;
|
|
|
|
case SVFOP_CURRENT_TIMESTAMP_N:
|
|
|
|
svf->type = TIMESTAMPTZOID;
|
|
|
|
svf->typmod = anytimestamp_typmod_check(true, svf->typmod);
|
|
|
|
break;
|
|
|
|
case SVFOP_LOCALTIME:
|
|
|
|
svf->type = TIMEOID;
|
|
|
|
break;
|
|
|
|
case SVFOP_LOCALTIME_N:
|
|
|
|
svf->type = TIMEOID;
|
|
|
|
svf->typmod = anytime_typmod_check(false, svf->typmod);
|
|
|
|
break;
|
|
|
|
case SVFOP_LOCALTIMESTAMP:
|
|
|
|
svf->type = TIMESTAMPOID;
|
|
|
|
break;
|
|
|
|
case SVFOP_LOCALTIMESTAMP_N:
|
|
|
|
svf->type = TIMESTAMPOID;
|
|
|
|
svf->typmod = anytimestamp_typmod_check(false, svf->typmod);
|
|
|
|
break;
|
|
|
|
case SVFOP_CURRENT_ROLE:
|
|
|
|
case SVFOP_CURRENT_USER:
|
|
|
|
case SVFOP_USER:
|
|
|
|
case SVFOP_SESSION_USER:
|
|
|
|
case SVFOP_CURRENT_CATALOG:
|
|
|
|
case SVFOP_CURRENT_SCHEMA:
|
|
|
|
svf->type = NAMEOID;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Node *) svf;
|
|
|
|
}
|
|
|
|
|
2006-12-24 01:29:20 +01:00
|
|
|
static Node *
|
2007-11-15 23:25:18 +01:00
|
|
|
transformXmlExpr(ParseState *pstate, XmlExpr *x)
|
2006-12-24 01:29:20 +01:00
|
|
|
{
|
2012-12-23 20:07:24 +01:00
|
|
|
XmlExpr *newx;
|
2007-11-15 22:14:46 +01:00
|
|
|
ListCell *lc;
|
2006-12-24 01:29:20 +01:00
|
|
|
int i;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning && x->op == IS_DOCUMENT)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
|
|
|
|
(Node *) linitial(x->args), NULL,
|
|
|
|
x->location);
|
|
|
|
|
2012-12-23 20:07:24 +01:00
|
|
|
newx = makeNode(XmlExpr);
|
2006-12-24 01:29:20 +01:00
|
|
|
newx->op = x->op;
|
|
|
|
if (x->name)
|
2007-02-11 23:18:16 +01:00
|
|
|
newx->name = map_sql_identifier_to_xml_name(x->name, false, false);
|
2006-12-24 01:29:20 +01:00
|
|
|
else
|
|
|
|
newx->name = NULL;
|
2008-08-29 01:09:48 +02:00
|
|
|
newx->xmloption = x->xmloption;
|
2012-12-23 20:07:24 +01:00
|
|
|
newx->type = XMLOID; /* this just marks the node as transformed */
|
|
|
|
newx->typmod = -1;
|
2008-08-29 01:09:48 +02:00
|
|
|
newx->location = x->location;
|
2006-12-24 01:29:20 +01:00
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* gram.y built the named args as a list of ResTarget. Transform each,
|
2006-12-24 01:29:20 +01:00
|
|
|
* and break the names out as a separate list.
|
|
|
|
*/
|
|
|
|
newx->named_args = NIL;
|
|
|
|
newx->arg_names = NIL;
|
|
|
|
|
|
|
|
foreach(lc, x->named_args)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
ResTarget *r = lfirst_node(ResTarget, lc);
|
2007-11-15 22:14:46 +01:00
|
|
|
Node *expr;
|
|
|
|
char *argname;
|
2006-12-24 01:29:20 +01:00
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
expr = transformExprRecurse(pstate, r->val);
|
2006-12-24 01:29:20 +01:00
|
|
|
|
|
|
|
if (r->name)
|
2007-02-11 23:18:16 +01:00
|
|
|
argname = map_sql_identifier_to_xml_name(r->name, false, false);
|
2006-12-24 01:29:20 +01:00
|
|
|
else if (IsA(r->val, ColumnRef))
|
|
|
|
argname = map_sql_identifier_to_xml_name(FigureColname(r->val),
|
2007-02-11 23:18:16 +01:00
|
|
|
true, false);
|
2006-12-24 01:29:20 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
x->op == IS_XMLELEMENT
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
? errmsg("unnamed XML attribute value must be a column reference")
|
|
|
|
: errmsg("unnamed XML element value must be a column reference"),
|
2008-08-29 01:09:48 +02:00
|
|
|
parser_errposition(pstate, r->location)));
|
2006-12-24 01:29:20 +01:00
|
|
|
argname = NULL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
/* reject duplicate argnames in XMLELEMENT only */
|
|
|
|
if (x->op == IS_XMLELEMENT)
|
2007-01-09 00:41:57 +01:00
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
ListCell *lc2;
|
2007-01-09 00:41:57 +01:00
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
foreach(lc2, newx->arg_names)
|
2007-01-09 00:41:57 +01:00
|
|
|
{
|
2008-08-29 01:09:48 +02:00
|
|
|
if (strcmp(argname, strVal(lfirst(lc2))) == 0)
|
2007-01-09 00:41:57 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("XML attribute name \"%s\" appears more than once",
|
|
|
|
argname),
|
2008-08-29 01:09:48 +02:00
|
|
|
parser_errposition(pstate, r->location)));
|
2007-01-09 00:41:57 +01:00
|
|
|
}
|
|
|
|
}
|
2008-08-29 01:09:48 +02:00
|
|
|
|
|
|
|
newx->named_args = lappend(newx->named_args, expr);
|
|
|
|
newx->arg_names = lappend(newx->arg_names, makeString(argname));
|
2007-01-09 00:41:57 +01:00
|
|
|
}
|
|
|
|
|
2006-12-24 01:29:20 +01:00
|
|
|
/* The other arguments are of varying types depending on the function */
|
|
|
|
newx->args = NIL;
|
|
|
|
i = 0;
|
|
|
|
foreach(lc, x->args)
|
|
|
|
{
|
|
|
|
Node *e = (Node *) lfirst(lc);
|
|
|
|
Node *newe;
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newe = transformExprRecurse(pstate, e);
|
2006-12-24 01:29:20 +01:00
|
|
|
switch (x->op)
|
|
|
|
{
|
|
|
|
case IS_XMLCONCAT:
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
|
|
|
"XMLCONCAT");
|
|
|
|
break;
|
2007-01-12 23:09:49 +01:00
|
|
|
case IS_XMLELEMENT:
|
|
|
|
/* no coercion necessary */
|
|
|
|
break;
|
2006-12-24 01:29:20 +01:00
|
|
|
case IS_XMLFOREST:
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
|
|
|
"XMLFOREST");
|
|
|
|
break;
|
|
|
|
case IS_XMLPARSE:
|
|
|
|
if (i == 0)
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, TEXTOID,
|
|
|
|
"XMLPARSE");
|
|
|
|
else
|
|
|
|
newe = coerce_to_boolean(pstate, newe, "XMLPARSE");
|
|
|
|
break;
|
|
|
|
case IS_XMLPI:
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, TEXTOID,
|
|
|
|
"XMLPI");
|
|
|
|
break;
|
|
|
|
case IS_XMLROOT:
|
|
|
|
if (i == 0)
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
|
|
|
"XMLROOT");
|
|
|
|
else if (i == 1)
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, TEXTOID,
|
|
|
|
"XMLROOT");
|
|
|
|
else
|
2007-01-25 12:53:52 +01:00
|
|
|
newe = coerce_to_specific_type(pstate, newe, INT4OID,
|
|
|
|
"XMLROOT");
|
2006-12-24 01:29:20 +01:00
|
|
|
break;
|
2007-02-03 15:06:56 +01:00
|
|
|
case IS_XMLSERIALIZE:
|
|
|
|
/* not handled here */
|
2008-08-29 01:09:48 +02:00
|
|
|
Assert(false);
|
2007-02-03 15:06:56 +01:00
|
|
|
break;
|
2007-01-14 14:11:54 +01:00
|
|
|
case IS_DOCUMENT:
|
|
|
|
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
|
|
|
"IS DOCUMENT");
|
|
|
|
break;
|
2006-12-24 01:29:20 +01:00
|
|
|
}
|
|
|
|
newx->args = lappend(newx->args, newe);
|
|
|
|
i++;
|
|
|
|
}
|
2007-01-12 17:29:24 +01:00
|
|
|
|
2006-12-24 01:29:20 +01:00
|
|
|
return (Node *) newx;
|
|
|
|
}
|
|
|
|
|
2007-02-03 15:06:56 +01:00
|
|
|
static Node *
|
2007-11-15 23:25:18 +01:00
|
|
|
transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
|
2007-02-03 15:06:56 +01:00
|
|
|
{
|
2008-08-29 01:09:48 +02:00
|
|
|
Node *result;
|
|
|
|
XmlExpr *xexpr;
|
2007-02-03 15:06:56 +01:00
|
|
|
Oid targetType;
|
|
|
|
int32 targetTypmod;
|
|
|
|
|
|
|
|
xexpr = makeNode(XmlExpr);
|
|
|
|
xexpr->op = IS_XMLSERIALIZE;
|
|
|
|
xexpr->args = list_make1(coerce_to_specific_type(pstate,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
transformExprRecurse(pstate, xs->expr),
|
2007-02-03 15:06:56 +01:00
|
|
|
XMLOID,
|
|
|
|
"XMLSERIALIZE"));
|
|
|
|
|
2010-10-25 20:40:46 +02:00
|
|
|
typenameTypeIdAndMod(pstate, xs->typeName, &targetType, &targetTypmod);
|
2007-02-03 15:06:56 +01:00
|
|
|
|
|
|
|
xexpr->xmloption = xs->xmloption;
|
2008-08-29 01:09:48 +02:00
|
|
|
xexpr->location = xs->location;
|
2007-02-03 15:06:56 +01:00
|
|
|
/* We actually only need these to be able to parse back the expression. */
|
|
|
|
xexpr->type = targetType;
|
|
|
|
xexpr->typmod = targetTypmod;
|
|
|
|
|
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* The actual target type is determined this way. SQL allows char and
|
|
|
|
* varchar as target types. We allow anything that can be cast implicitly
|
|
|
|
* from text. This way, user-defined text-like data types automatically
|
|
|
|
* fit in.
|
2007-02-03 15:06:56 +01:00
|
|
|
*/
|
2008-08-29 01:09:48 +02:00
|
|
|
result = coerce_to_target_type(pstate, (Node *) xexpr,
|
|
|
|
TEXTOID, targetType, targetTypmod,
|
|
|
|
COERCION_IMPLICIT,
|
|
|
|
COERCE_IMPLICIT_CAST,
|
|
|
|
-1);
|
|
|
|
if (result == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast XMLSERIALIZE result to %s",
|
|
|
|
format_type_be(targetType)),
|
|
|
|
parser_errposition(pstate, xexpr->location)));
|
|
|
|
return result;
|
2007-02-03 15:06:56 +01:00
|
|
|
}
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
static Node *
|
|
|
|
transformBooleanTest(ParseState *pstate, BooleanTest *b)
|
|
|
|
{
|
|
|
|
const char *clausename;
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
if (operator_precedence_warning)
|
|
|
|
emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS",
|
|
|
|
(Node *) b->arg, NULL,
|
|
|
|
b->location);
|
|
|
|
|
2005-01-20 00:45:24 +01:00
|
|
|
switch (b->booltesttype)
|
|
|
|
{
|
|
|
|
case IS_TRUE:
|
|
|
|
clausename = "IS TRUE";
|
|
|
|
break;
|
|
|
|
case IS_NOT_TRUE:
|
|
|
|
clausename = "IS NOT TRUE";
|
|
|
|
break;
|
|
|
|
case IS_FALSE:
|
|
|
|
clausename = "IS FALSE";
|
|
|
|
break;
|
|
|
|
case IS_NOT_FALSE:
|
|
|
|
clausename = "IS NOT FALSE";
|
|
|
|
break;
|
|
|
|
case IS_UNKNOWN:
|
|
|
|
clausename = "IS UNKNOWN";
|
|
|
|
break;
|
|
|
|
case IS_NOT_UNKNOWN:
|
|
|
|
clausename = "IS NOT UNKNOWN";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized booltesttype: %d",
|
|
|
|
(int) b->booltesttype);
|
2005-10-15 04:49:52 +02:00
|
|
|
clausename = NULL; /* keep compiler quiet */
|
2005-01-20 00:45:24 +01:00
|
|
|
}
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
b->arg = (Expr *) transformExprRecurse(pstate, (Node *) b->arg);
|
2005-01-20 00:45:24 +01:00
|
|
|
|
|
|
|
b->arg = (Expr *) coerce_to_boolean(pstate,
|
|
|
|
(Node *) b->arg,
|
|
|
|
clausename);
|
|
|
|
|
|
|
|
return (Node *) b;
|
|
|
|
}
|
|
|
|
|
2007-06-12 00:22:42 +02:00
|
|
|
static Node *
|
2007-11-15 23:25:18 +01:00
|
|
|
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
|
2007-06-12 00:22:42 +02:00
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
int sublevels_up;
|
2007-06-12 00:22:42 +02:00
|
|
|
|
|
|
|
/* CURRENT OF can only appear at top level of UPDATE/DELETE */
|
|
|
|
Assert(pstate->p_target_rangetblentry != NULL);
|
|
|
|
cexpr->cvarno = RTERangeTablePosn(pstate,
|
|
|
|
pstate->p_target_rangetblentry,
|
|
|
|
&sublevels_up);
|
|
|
|
Assert(sublevels_up == 0);
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/*
|
2009-11-09 03:36:59 +01:00
|
|
|
* Check to see if the cursor name matches a parameter of type REFCURSOR.
|
2010-02-26 03:01:40 +01:00
|
|
|
* If so, replace the raw name reference with a parameter reference. (This
|
|
|
|
* is a hack for the convenience of plpgsql.)
|
2009-10-31 02:41:31 +01:00
|
|
|
*/
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
if (cexpr->cursor_name != NULL) /* in case already transformed */
|
2007-06-12 00:22:42 +02:00
|
|
|
{
|
2009-11-09 03:36:59 +01:00
|
|
|
ColumnRef *cref = makeNode(ColumnRef);
|
|
|
|
Node *node = NULL;
|
|
|
|
|
|
|
|
/* Build an unqualified ColumnRef with the given name */
|
|
|
|
cref->fields = list_make1(makeString(cexpr->cursor_name));
|
|
|
|
cref->location = -1;
|
|
|
|
|
|
|
|
/* See if there is a translation available from a parser hook */
|
|
|
|
if (pstate->p_pre_columnref_hook != NULL)
|
2017-09-07 18:06:23 +02:00
|
|
|
node = pstate->p_pre_columnref_hook(pstate, cref);
|
2009-11-09 03:36:59 +01:00
|
|
|
if (node == NULL && pstate->p_post_columnref_hook != NULL)
|
2017-09-07 18:06:23 +02:00
|
|
|
node = pstate->p_post_columnref_hook(pstate, cref, NULL);
|
2009-11-09 03:36:59 +01:00
|
|
|
|
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* XXX Should we throw an error if we get a translation that isn't a
|
|
|
|
* refcursor Param? For now it seems best to silently ignore false
|
|
|
|
* matches.
|
2009-11-09 03:36:59 +01:00
|
|
|
*/
|
|
|
|
if (node != NULL && IsA(node, Param))
|
|
|
|
{
|
2010-02-26 03:01:40 +01:00
|
|
|
Param *p = (Param *) node;
|
2009-11-09 03:36:59 +01:00
|
|
|
|
|
|
|
if (p->paramkind == PARAM_EXTERN &&
|
|
|
|
p->paramtype == REFCURSOROID)
|
|
|
|
{
|
|
|
|
/* Matches, so convert CURRENT OF to a param reference */
|
|
|
|
cexpr->cursor_name = NULL;
|
|
|
|
cexpr->cursor_param = p->paramid;
|
|
|
|
}
|
|
|
|
}
|
2007-06-12 00:22:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return (Node *) cexpr;
|
|
|
|
}
|
|
|
|
|
2004-04-02 21:07:02 +02:00
|
|
|
/*
|
|
|
|
* Construct a whole-row reference to represent the notation "relation.*".
|
|
|
|
*/
|
|
|
|
static Node *
|
2009-10-31 02:41:31 +01:00
|
|
|
transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
|
2004-04-02 21:07:02 +02:00
|
|
|
{
|
2008-08-29 01:09:48 +02:00
|
|
|
Var *result;
|
2004-04-02 21:07:02 +02:00
|
|
|
int vnum;
|
|
|
|
int sublevels_up;
|
|
|
|
|
2009-10-31 02:41:31 +01:00
|
|
|
/* Find the RTE's rangetable location */
|
2004-04-02 21:07:02 +02:00
|
|
|
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
|
|
|
|
|
2011-11-28 04:27:24 +01:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Build the appropriate referencing node. Note that if the RTE is a
|
2011-11-28 04:27:24 +01:00
|
|
|
* function returning scalar, we create just a plain reference to the
|
2014-05-06 18:12:18 +02:00
|
|
|
* function value, not a composite containing a single column. This is
|
2011-11-28 04:27:24 +01:00
|
|
|
* pretty inconsistent at first sight, but it's what we've done
|
|
|
|
* historically. One argument for it is that "rel" and "rel.*" mean the
|
|
|
|
* same thing for composite relations, so why not for scalar functions...
|
|
|
|
*/
|
|
|
|
result = makeWholeRowVar(rte, vnum, sublevels_up, true);
|
2004-04-02 21:07:02 +02:00
|
|
|
|
2010-10-19 21:08:37 +02:00
|
|
|
/* location is not filled in by makeWholeRowVar */
|
2008-08-29 01:09:48 +02:00
|
|
|
result->location = location;
|
|
|
|
|
2009-01-22 21:16:10 +01:00
|
|
|
/* mark relation as requiring whole-row SELECT access */
|
|
|
|
markVarForSelectPriv(pstate, result, rte);
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
return (Node *) result;
|
2004-04-02 21:07:02 +02:00
|
|
|
}
|
|
|
|
|
1999-08-05 04:33:54 +02:00
|
|
|
/*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* Handle an explicit CAST construct.
|
2000-01-17 01:14:49 +01:00
|
|
|
*
|
2016-04-22 05:17:36 +02:00
|
|
|
* Transform the argument, look up the type name, and apply any necessary
|
2008-08-29 01:09:48 +02:00
|
|
|
* coercion function(s).
|
2000-01-17 01:14:49 +01:00
|
|
|
*/
|
|
|
|
static Node *
|
2008-08-29 01:09:48 +02:00
|
|
|
transformTypeCast(ParseState *pstate, TypeCast *tc)
|
2000-01-17 01:14:49 +01:00
|
|
|
{
|
2008-08-29 01:09:48 +02:00
|
|
|
Node *result;
|
2016-04-22 05:17:36 +02:00
|
|
|
Node *arg = tc->arg;
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
Node *expr;
|
|
|
|
Oid inputType;
|
2000-01-17 01:14:49 +01:00
|
|
|
Oid targetType;
|
2006-12-30 22:21:56 +01:00
|
|
|
int32 targetTypmod;
|
2008-08-29 01:09:48 +02:00
|
|
|
int location;
|
2000-01-17 01:14:49 +01:00
|
|
|
|
2016-04-22 05:17:36 +02:00
|
|
|
/* Look up the type name first */
|
2010-10-25 20:40:46 +02:00
|
|
|
typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
|
2000-01-17 01:14:49 +01:00
|
|
|
|
2016-04-22 05:17:36 +02:00
|
|
|
/*
|
|
|
|
* Look through any AEXPR_PAREN nodes that may have been inserted thanks
|
|
|
|
* to operator_precedence_warning. Otherwise, ARRAY[]::foo[] behaves
|
|
|
|
* differently from (ARRAY[])::foo[].
|
|
|
|
*/
|
|
|
|
while (arg && IsA(arg, A_Expr) &&
|
|
|
|
((A_Expr *) arg)->kind == AEXPR_PAREN)
|
|
|
|
arg = ((A_Expr *) arg)->lexpr;
|
|
|
|
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
/*
|
|
|
|
* If the subject of the typecast is an ARRAY[] construct and the target
|
|
|
|
* type is an array type, we invoke transformArrayExpr() directly so that
|
|
|
|
* we can pass down the type information. This avoids some cases where
|
|
|
|
* transformArrayExpr() might not infer the correct type. Otherwise, just
|
|
|
|
* transform the argument normally.
|
|
|
|
*/
|
2016-04-22 05:17:36 +02:00
|
|
|
if (IsA(arg, A_ArrayExpr))
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
{
|
|
|
|
Oid targetBaseType;
|
|
|
|
int32 targetBaseTypmod;
|
|
|
|
Oid elementType;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If target is a domain over array, work with the base array type
|
|
|
|
* here. Below, we'll cast the array type to the domain. In the
|
|
|
|
* usual case that the target is not a domain, the remaining steps
|
|
|
|
* will be a no-op.
|
|
|
|
*/
|
|
|
|
targetBaseTypmod = targetTypmod;
|
|
|
|
targetBaseType = getBaseTypeAndTypmod(targetType, &targetBaseTypmod);
|
|
|
|
elementType = get_element_type(targetBaseType);
|
|
|
|
if (OidIsValid(elementType))
|
|
|
|
{
|
|
|
|
expr = transformArrayExpr(pstate,
|
2016-04-22 05:17:36 +02:00
|
|
|
(A_ArrayExpr *) arg,
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
targetBaseType,
|
|
|
|
elementType,
|
|
|
|
targetBaseTypmod);
|
|
|
|
}
|
|
|
|
else
|
2016-04-22 05:17:36 +02:00
|
|
|
expr = transformExprRecurse(pstate, arg);
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
}
|
|
|
|
else
|
2016-04-22 05:17:36 +02:00
|
|
|
expr = transformExprRecurse(pstate, arg);
|
Get rid of multiple applications of transformExpr() to the same tree.
transformExpr() has for many years had provisions to do nothing when
applied to an already-transformed expression tree. However, this was
always ugly and of dubious reliability, so we'd be much better off without
it. The primary historical reason for it was that gram.y sometimes
returned multiple links to the same subexpression, which is no longer true
as of my BETWEEN fixes. We'd also grown some lazy hacks in CREATE TABLE
LIKE (failing to distinguish between raw and already-transformed index
specifications) and one or two other places.
This patch removes the need for and support for re-transforming already
transformed expressions. The index case is dealt with by adding a flag
to struct IndexStmt to indicate that it's already been transformed;
which has some benefit anyway in that tablecmds.c can now Assert that
transformation has happened rather than just assuming. The other main
reason was some rather sloppy code for array type coercion, which can
be fixed (and its performance improved too) by refactoring.
I did leave transformJoinUsingClause() still constructing expressions
containing untransformed operator nodes being applied to Vars, so that
transformExpr() still has to allow Var inputs. But that's a much narrower,
and safer, special case than before, since Vars will never appear in a raw
parse tree, and they don't have any substructure to worry about.
In passing fix some oversights in the patch that added CREATE INDEX
IF NOT EXISTS (missing processing of IndexStmt.if_not_exists). These
appear relatively harmless, but still sloppy coding practice.
2015-02-22 19:59:09 +01:00
|
|
|
|
|
|
|
inputType = exprType(expr);
|
2000-01-17 01:14:49 +01:00
|
|
|
if (inputType == InvalidOid)
|
|
|
|
return expr; /* do nothing if NULL input */
|
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
/*
|
|
|
|
* Location of the coercion is preferentially the location of the :: or
|
|
|
|
* CAST symbol, but if there is none then use the location of the type
|
|
|
|
* name (this can happen in TypeName 'string' syntax, for instance).
|
|
|
|
*/
|
|
|
|
location = tc->location;
|
|
|
|
if (location < 0)
|
2009-07-16 08:33:46 +02:00
|
|
|
location = tc->typeName->location;
|
2008-08-29 01:09:48 +02:00
|
|
|
|
|
|
|
result = coerce_to_target_type(pstate, expr, inputType,
|
|
|
|
targetType, targetTypmod,
|
|
|
|
COERCION_EXPLICIT,
|
|
|
|
COERCE_EXPLICIT_CAST,
|
|
|
|
location);
|
|
|
|
if (result == NULL)
|
2003-07-19 22:20:53 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CANNOT_COERCE),
|
|
|
|
errmsg("cannot cast type %s to %s",
|
|
|
|
format_type_be(inputType),
|
2006-03-14 23:48:25 +01:00
|
|
|
format_type_be(targetType)),
|
2008-08-29 01:09:48 +02:00
|
|
|
parser_coercion_errposition(pstate, location, expr)));
|
2000-01-17 01:14:49 +01:00
|
|
|
|
2008-08-29 01:09:48 +02:00
|
|
|
return result;
|
2000-01-17 01:14:49 +01:00
|
|
|
}
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
/*
|
|
|
|
* Handle an explicit COLLATE clause.
|
|
|
|
*
|
|
|
|
* Transform the argument, and look up the collation name.
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
transformCollateClause(ParseState *pstate, CollateClause *c)
|
|
|
|
{
|
2011-03-11 22:27:51 +01:00
|
|
|
CollateExpr *newc;
|
2011-04-10 17:42:00 +02:00
|
|
|
Oid argtype;
|
2011-02-08 22:04:18 +01:00
|
|
|
|
2011-03-11 22:27:51 +01:00
|
|
|
newc = makeNode(CollateExpr);
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
newc->arg = (Expr *) transformExprRecurse(pstate, c->arg);
|
2011-02-08 22:04:18 +01:00
|
|
|
|
|
|
|
argtype = exprType((Node *) newc->arg);
|
2011-04-10 17:42:00 +02:00
|
|
|
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
/*
|
2011-04-10 17:42:00 +02:00
|
|
|
* The unknown type is not collatable, but coerce_type() takes care of it
|
|
|
|
* separately, so we'll let it go here.
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
*/
|
2011-02-08 22:04:18 +01:00
|
|
|
if (!type_is_collatable(argtype) && argtype != UNKNOWNOID)
|
|
|
|
ereport(ERROR,
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2011-02-08 22:04:18 +01:00
|
|
|
errmsg("collations are not supported by type %s",
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
format_type_be(argtype)),
|
|
|
|
parser_errposition(pstate, c->location)));
|
2011-02-08 22:04:18 +01:00
|
|
|
|
2011-03-11 22:27:51 +01:00
|
|
|
newc->collOid = LookupCollation(pstate, c->collname, c->location);
|
2011-02-08 22:04:18 +01:00
|
|
|
newc->location = c->location;
|
|
|
|
|
|
|
|
return (Node *) newc;
|
|
|
|
}
|
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
/*
|
2005-12-28 02:30:02 +01:00
|
|
|
* Transform a "row compare-op row" construct
|
2005-11-28 05:35:32 +01:00
|
|
|
*
|
2005-12-28 02:30:02 +01:00
|
|
|
* The inputs are lists of already-transformed expressions.
|
|
|
|
* As with coerce_type, pstate may be NULL if no special unknown-Param
|
|
|
|
* processing is wanted.
|
|
|
|
*
|
|
|
|
* The output may be a single OpExpr, an AND or OR combination of OpExprs,
|
|
|
|
* or a RowCompareExpr. In all cases it is guaranteed to return boolean.
|
|
|
|
* The AND, OR, and RowCompareExpr cases further imply things about the
|
|
|
|
* behavior of the operators (ie, they behave as =, <>, or < <= > >=).
|
2004-05-11 00:44:49 +02:00
|
|
|
*/
|
|
|
|
static Node *
|
2005-12-28 02:30:02 +01:00
|
|
|
make_row_comparison_op(ParseState *pstate, List *opname,
|
2006-03-14 23:48:25 +01:00
|
|
|
List *largs, List *rargs, int location)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2005-12-28 02:30:02 +01:00
|
|
|
RowCompareExpr *rcexpr;
|
|
|
|
RowCompareType rctype;
|
|
|
|
List *opexprs;
|
|
|
|
List *opnos;
|
2006-12-23 01:43:13 +01:00
|
|
|
List *opfamilies;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l,
|
|
|
|
*r;
|
2011-07-06 20:53:16 +02:00
|
|
|
List **opinfo_lists;
|
2005-12-28 02:30:02 +01:00
|
|
|
Bitmapset *strats;
|
|
|
|
int nopers;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
nopers = list_length(largs);
|
|
|
|
if (nopers != list_length(rargs))
|
2004-05-11 00:44:49 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2006-03-14 23:48:25 +01:00
|
|
|
errmsg("unequal number of entries in row expressions"),
|
|
|
|
parser_errposition(pstate, location)));
|
2004-05-11 00:44:49 +02:00
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We can't compare zero-length rows because there is no principled basis
|
|
|
|
* for figuring out what the operator is.
|
2004-05-11 00:44:49 +02:00
|
|
|
*/
|
2005-12-28 02:30:02 +01:00
|
|
|
if (nopers == 0)
|
2004-05-11 00:44:49 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2006-03-14 23:48:25 +01:00
|
|
|
errmsg("cannot compare rows of zero length"),
|
|
|
|
parser_errposition(pstate, location)));
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Identify all the pairwise operators, using make_op so that behavior is
|
|
|
|
* the same as in the simple scalar case.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
opexprs = NIL;
|
2004-05-26 06:41:50 +02:00
|
|
|
forboth(l, largs, r, rargs)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Node *larg = (Node *) lfirst(l);
|
|
|
|
Node *rarg = (Node *) lfirst(r);
|
2005-12-28 02:30:02 +01:00
|
|
|
OpExpr *cmp;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
cmp = castNode(OpExpr, make_op(pstate, opname, larg, rarg,
|
|
|
|
pstate->p_last_srf, location));
|
2005-12-28 02:30:02 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't use coerce_to_boolean here because we insist on the
|
|
|
|
* operator yielding boolean directly, not via coercion. If it
|
2006-12-23 01:43:13 +01:00
|
|
|
* doesn't yield bool it won't be in any index opfamilies...
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
if (cmp->opresulttype != BOOLOID)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("row comparison operator must yield type boolean, "
|
|
|
|
"not type %s",
|
|
|
|
format_type_be(cmp->opresulttype)),
|
2006-03-14 23:48:25 +01:00
|
|
|
parser_errposition(pstate, location)));
|
2005-12-28 02:30:02 +01:00
|
|
|
if (expression_returns_set((Node *) cmp))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
2006-03-14 23:48:25 +01:00
|
|
|
errmsg("row comparison operator must not return a set"),
|
|
|
|
parser_errposition(pstate, location)));
|
2005-12-28 02:30:02 +01:00
|
|
|
opexprs = lappend(opexprs, cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* If rows are length 1, just return the single operator. In this case we
|
|
|
|
* don't insist on identifying btree semantics for the operator (but we
|
|
|
|
* still require it to return boolean).
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
if (nopers == 1)
|
|
|
|
return (Node *) linitial(opexprs);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we must determine which row comparison semantics (= <> < <= > >=)
|
2014-05-06 18:12:18 +02:00
|
|
|
* apply to this set of operators. We look for btree opfamilies
|
2007-11-15 22:14:46 +01:00
|
|
|
* containing the operators, and see which interpretations (strategy
|
|
|
|
* numbers) exist for each operator.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
2011-07-06 20:53:16 +02:00
|
|
|
opinfo_lists = (List **) palloc(nopers * sizeof(List *));
|
2005-12-28 02:30:02 +01:00
|
|
|
strats = NULL;
|
|
|
|
i = 0;
|
|
|
|
foreach(l, opexprs)
|
|
|
|
{
|
2006-12-23 01:43:13 +01:00
|
|
|
Oid opno = ((OpExpr *) lfirst(l))->opno;
|
2006-10-04 02:30:14 +02:00
|
|
|
Bitmapset *this_strats;
|
2005-12-28 02:30:02 +01:00
|
|
|
ListCell *j;
|
|
|
|
|
2011-07-06 20:53:16 +02:00
|
|
|
opinfo_lists[i] = get_op_btree_interpretation(opno);
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
/*
|
2012-06-10 21:20:04 +02:00
|
|
|
* convert strategy numbers into a Bitmapset to make the intersection
|
|
|
|
* calculation easy.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
this_strats = NULL;
|
2011-07-06 20:53:16 +02:00
|
|
|
foreach(j, opinfo_lists[i])
|
2005-12-28 02:30:02 +01:00
|
|
|
{
|
2011-07-06 20:53:16 +02:00
|
|
|
OpBtreeInterpretation *opinfo = lfirst(j);
|
|
|
|
|
|
|
|
this_strats = bms_add_member(this_strats, opinfo->strategy);
|
2005-12-28 02:30:02 +01:00
|
|
|
}
|
|
|
|
if (i == 0)
|
|
|
|
strats = this_strats;
|
2004-05-11 00:44:49 +02:00
|
|
|
else
|
2005-12-28 02:30:02 +01:00
|
|
|
strats = bms_int_members(strats, this_strats);
|
|
|
|
i++;
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
/*
|
|
|
|
* If there are multiple common interpretations, we may use any one of
|
|
|
|
* them ... this coding arbitrarily picks the lowest btree strategy
|
|
|
|
* number.
|
|
|
|
*/
|
|
|
|
i = bms_first_member(strats);
|
|
|
|
if (i < 0)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2006-12-23 01:43:13 +01:00
|
|
|
/* No common interpretation, so fail */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("could not determine interpretation of row comparison operator %s",
|
|
|
|
strVal(llast(opname))),
|
|
|
|
errhint("Row comparison operators must be associated with btree operator families."),
|
|
|
|
parser_errposition(pstate, location)));
|
2005-12-28 02:30:02 +01:00
|
|
|
}
|
2006-12-23 01:43:13 +01:00
|
|
|
rctype = (RowCompareType) i;
|
2005-12-28 02:30:02 +01:00
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* For = and <> cases, we just combine the pairwise operators with AND or
|
|
|
|
* OR respectively.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
|
|
|
if (rctype == ROWCOMPARE_EQ)
|
2008-08-29 01:09:48 +02:00
|
|
|
return (Node *) makeBoolExpr(AND_EXPR, opexprs, location);
|
2005-12-28 02:30:02 +01:00
|
|
|
if (rctype == ROWCOMPARE_NE)
|
2008-08-29 01:09:48 +02:00
|
|
|
return (Node *) makeBoolExpr(OR_EXPR, opexprs, location);
|
2005-12-28 02:30:02 +01:00
|
|
|
|
|
|
|
/*
|
2006-12-23 01:43:13 +01:00
|
|
|
* Otherwise we need to choose exactly which opfamily to associate with
|
2006-10-04 02:30:14 +02:00
|
|
|
* each operator.
|
2005-12-28 02:30:02 +01:00
|
|
|
*/
|
2006-12-23 01:43:13 +01:00
|
|
|
opfamilies = NIL;
|
2005-12-28 02:30:02 +01:00
|
|
|
for (i = 0; i < nopers; i++)
|
|
|
|
{
|
2006-12-23 01:43:13 +01:00
|
|
|
Oid opfamily = InvalidOid;
|
2011-07-06 20:53:16 +02:00
|
|
|
ListCell *j;
|
2005-12-28 02:30:02 +01:00
|
|
|
|
2011-07-06 20:53:16 +02:00
|
|
|
foreach(j, opinfo_lists[i])
|
2005-12-28 02:30:02 +01:00
|
|
|
{
|
2011-07-06 20:53:16 +02:00
|
|
|
OpBtreeInterpretation *opinfo = lfirst(j);
|
2005-12-28 02:30:02 +01:00
|
|
|
|
2011-07-06 20:53:16 +02:00
|
|
|
if (opinfo->strategy == rctype)
|
2005-12-28 02:30:02 +01:00
|
|
|
{
|
2011-07-06 20:53:16 +02:00
|
|
|
opfamily = opinfo->opfamily_id;
|
2006-12-23 01:43:13 +01:00
|
|
|
break;
|
2005-12-28 02:30:02 +01:00
|
|
|
}
|
|
|
|
}
|
2006-12-23 01:43:13 +01:00
|
|
|
if (OidIsValid(opfamily))
|
|
|
|
opfamilies = lappend_oid(opfamilies, opfamily);
|
2017-06-21 20:39:04 +02:00
|
|
|
else /* should not happen */
|
2005-12-28 02:30:02 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("could not determine interpretation of row comparison operator %s",
|
|
|
|
strVal(llast(opname))),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errdetail("There are multiple equally-plausible candidates."),
|
2006-03-14 23:48:25 +01:00
|
|
|
parser_errposition(pstate, location)));
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
|
|
|
|
2005-12-28 02:30:02 +01:00
|
|
|
/*
|
|
|
|
* Now deconstruct the OpExprs and create a RowCompareExpr.
|
|
|
|
*
|
|
|
|
* Note: can't just reuse the passed largs/rargs lists, because of
|
|
|
|
* possibility that make_op inserted coercion operations.
|
|
|
|
*/
|
|
|
|
opnos = NIL;
|
|
|
|
largs = NIL;
|
|
|
|
rargs = NIL;
|
|
|
|
foreach(l, opexprs)
|
|
|
|
{
|
|
|
|
OpExpr *cmp = (OpExpr *) lfirst(l);
|
|
|
|
|
|
|
|
opnos = lappend_oid(opnos, cmp->opno);
|
|
|
|
largs = lappend(largs, linitial(cmp->args));
|
|
|
|
rargs = lappend(rargs, lsecond(cmp->args));
|
|
|
|
}
|
|
|
|
|
|
|
|
rcexpr = makeNode(RowCompareExpr);
|
|
|
|
rcexpr->rctype = rctype;
|
|
|
|
rcexpr->opnos = opnos;
|
2006-12-23 01:43:13 +01:00
|
|
|
rcexpr->opfamilies = opfamilies;
|
2011-04-10 17:42:00 +02:00
|
|
|
rcexpr->inputcollids = NIL; /* assign_expr_collations will fix this */
|
2005-12-28 02:30:02 +01:00
|
|
|
rcexpr->largs = largs;
|
|
|
|
rcexpr->rargs = rargs;
|
|
|
|
|
|
|
|
return (Node *) rcexpr;
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Transform a "row IS DISTINCT FROM row" construct
|
2005-11-28 05:35:32 +01:00
|
|
|
*
|
|
|
|
* The input RowExprs are already transformed
|
2004-05-11 00:44:49 +02:00
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
make_row_distinct_op(ParseState *pstate, List *opname,
|
2006-03-14 23:48:25 +01:00
|
|
|
RowExpr *lrow, RowExpr *rrow,
|
|
|
|
int location)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
|
|
|
Node *result = NULL;
|
2005-11-28 05:35:32 +01:00
|
|
|
List *largs = lrow->args;
|
|
|
|
List *rargs = rrow->args;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l,
|
|
|
|
*r;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2004-05-31 01:40:41 +02:00
|
|
|
if (list_length(largs) != list_length(rargs))
|
2004-05-11 00:44:49 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
2006-03-14 23:48:25 +01:00
|
|
|
errmsg("unequal number of entries in row expressions"),
|
|
|
|
parser_errposition(pstate, location)));
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2004-05-26 06:41:50 +02:00
|
|
|
forboth(l, largs, r, rargs)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Node *larg = (Node *) lfirst(l);
|
|
|
|
Node *rarg = (Node *) lfirst(r);
|
|
|
|
Node *cmp;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
2006-03-14 23:48:25 +01:00
|
|
|
cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location);
|
2004-05-11 00:44:49 +02:00
|
|
|
if (result == NULL)
|
|
|
|
result = cmp;
|
|
|
|
else
|
|
|
|
result = (Node *) makeBoolExpr(OR_EXPR,
|
2008-08-29 01:09:48 +02:00
|
|
|
list_make2(result, cmp),
|
|
|
|
location);
|
2004-05-11 00:44:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result == NULL)
|
|
|
|
{
|
|
|
|
/* zero-length rows? Generate constant FALSE */
|
|
|
|
result = makeBoolConst(false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* make the node for an IS DISTINCT FROM operator
|
|
|
|
*/
|
|
|
|
static Expr *
|
2006-03-14 23:48:25 +01:00
|
|
|
make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
|
|
|
|
int location)
|
2004-05-11 00:44:49 +02:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
Expr *result;
|
2004-05-11 00:44:49 +02:00
|
|
|
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
result = make_op(pstate, opname, ltree, rtree,
|
|
|
|
pstate->p_last_srf, location);
|
2004-05-11 00:44:49 +02:00
|
|
|
if (((OpExpr *) result)->opresulttype != BOOLOID)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("IS DISTINCT FROM requires = operator to yield boolean"),
|
2006-03-14 23:48:25 +01:00
|
|
|
parser_errposition(pstate, location)));
|
Disallow set-returning functions inside CASE or COALESCE.
When we reimplemented SRFs in commit 69f4b9c85, our initial choice was
to allow the behavior to vary from historical practice in cases where a
SRF call appeared within a conditional-execution construct (currently,
only CASE or COALESCE). But that was controversial to begin with, and
subsequent discussion has resulted in a consensus that it's better to
throw an error instead of executing the query differently from before,
so long as we can provide a reasonably clear error message and a way to
rewrite the query.
Hence, add a parser mechanism to allow detection of such cases during
parse analysis. The mechanism just requires storing, in the ParseState,
a pointer to the set-returning FuncExpr or OpExpr most recently emitted
by parse analysis. Then the parsing functions for CASE and COALESCE can
detect the presence of a SRF in their arguments by noting whether this
pointer changes while analyzing their arguments. Furthermore, if it does,
it provides a suitable error cursor location for the complaint. (This
means that if there's more than one SRF in the arguments, the error will
point at the last one to be analyzed not the first. While connoisseurs of
parsing behavior might find that odd, it's unlikely the average user would
ever notice.)
While at it, we can also provide more specific error messages than before
about some pre-existing restrictions, such as no-SRFs-within-aggregates.
Also, reject at parse time cases where a NULLIF or IS DISTINCT FROM
construct would need to return a set. We've never supported that, but the
restriction is depended on in more subtle ways now, so it seems wise to
detect it at the start.
Also, provide some documentation about how to rewrite a SRF-within-CASE
query using a custom wrapper SRF.
It turns out that the information_schema.user_mapping_options view
contained an instance of exactly the behavior we're now forbidding; but
rewriting it makes it more clear and safer too.
initdb forced because of user_mapping_options change.
Patch by me, with error message suggestions from Alvaro Herrera and
Andres Freund, pursuant to a complaint from Regina Obe.
Discussion: https://postgr.es/m/000001d2d5de$d8d66170$8a832450$@pcorp.us
2017-06-14 05:46:39 +02:00
|
|
|
if (((OpExpr *) result)->opretset)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
/* translator: %s is name of a SQL construct, eg NULLIF */
|
|
|
|
errmsg("%s must not return a set", "IS DISTINCT FROM"),
|
|
|
|
parser_errposition(pstate, location)));
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-05-11 00:44:49 +02:00
|
|
|
/*
|
2004-08-29 07:07:03 +02:00
|
|
|
* We rely on DistinctExpr and OpExpr being same struct
|
2004-05-11 00:44:49 +02:00
|
|
|
*/
|
|
|
|
NodeSetTag(result, T_DistinctExpr);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
|
2016-07-28 23:23:03 +02:00
|
|
|
/*
|
|
|
|
* Produce a NullTest node from an IS [NOT] DISTINCT FROM NULL construct
|
|
|
|
*
|
|
|
|
* "arg" is the untransformed other argument
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
make_nulltest_from_distinct(ParseState *pstate, A_Expr *distincta, Node *arg)
|
|
|
|
{
|
|
|
|
NullTest *nt = makeNode(NullTest);
|
|
|
|
|
|
|
|
nt->arg = (Expr *) transformExprRecurse(pstate, arg);
|
|
|
|
/* the argument can be any type, so don't coerce it */
|
|
|
|
if (distincta->kind == AEXPR_NOT_DISTINCT)
|
|
|
|
nt->nulltesttype = IS_NULL;
|
|
|
|
else
|
|
|
|
nt->nulltesttype = IS_NOT_NULL;
|
|
|
|
/* argisrow = false is correct whether or not arg is composite */
|
|
|
|
nt->argisrow = false;
|
|
|
|
nt->location = distincta->location;
|
|
|
|
return (Node *) nt;
|
|
|
|
}
|
|
|
|
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
/*
|
|
|
|
* Identify node's group for operator precedence warnings
|
|
|
|
*
|
|
|
|
* For items in nonzero groups, also return a suitable node name into *nodename
|
|
|
|
*
|
|
|
|
* Note: group zero is used for nodes that are higher or lower precedence
|
|
|
|
* than everything that changed precedence; we need never issue warnings
|
|
|
|
* related to such nodes.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
operator_precedence_group(Node *node, const char **nodename)
|
|
|
|
{
|
|
|
|
int group = 0;
|
|
|
|
|
|
|
|
*nodename = NULL;
|
|
|
|
if (node == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (IsA(node, A_Expr))
|
|
|
|
{
|
|
|
|
A_Expr *aexpr = (A_Expr *) node;
|
|
|
|
|
|
|
|
if (aexpr->kind == AEXPR_OP &&
|
|
|
|
aexpr->lexpr != NULL &&
|
|
|
|
aexpr->rexpr != NULL)
|
|
|
|
{
|
|
|
|
/* binary operator */
|
|
|
|
if (list_length(aexpr->name) == 1)
|
|
|
|
{
|
|
|
|
*nodename = strVal(linitial(aexpr->name));
|
|
|
|
/* Ignore if op was always higher priority than IS-tests */
|
|
|
|
if (strcmp(*nodename, "+") == 0 ||
|
|
|
|
strcmp(*nodename, "-") == 0 ||
|
|
|
|
strcmp(*nodename, "*") == 0 ||
|
|
|
|
strcmp(*nodename, "/") == 0 ||
|
|
|
|
strcmp(*nodename, "%") == 0 ||
|
|
|
|
strcmp(*nodename, "^") == 0)
|
|
|
|
group = 0;
|
|
|
|
else if (strcmp(*nodename, "<") == 0 ||
|
|
|
|
strcmp(*nodename, ">") == 0)
|
|
|
|
group = PREC_GROUP_LESS;
|
|
|
|
else if (strcmp(*nodename, "=") == 0)
|
|
|
|
group = PREC_GROUP_EQUAL;
|
|
|
|
else if (strcmp(*nodename, "<=") == 0 ||
|
|
|
|
strcmp(*nodename, ">=") == 0 ||
|
|
|
|
strcmp(*nodename, "<>") == 0)
|
|
|
|
group = PREC_GROUP_LESS_EQUAL;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_INFIX_OP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* schema-qualified operator syntax */
|
|
|
|
*nodename = "OPERATOR()";
|
|
|
|
group = PREC_GROUP_INFIX_OP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_OP &&
|
|
|
|
aexpr->lexpr == NULL &&
|
|
|
|
aexpr->rexpr != NULL)
|
|
|
|
{
|
|
|
|
/* prefix operator */
|
|
|
|
if (list_length(aexpr->name) == 1)
|
|
|
|
{
|
|
|
|
*nodename = strVal(linitial(aexpr->name));
|
|
|
|
/* Ignore if op was always higher priority than IS-tests */
|
|
|
|
if (strcmp(*nodename, "+") == 0 ||
|
|
|
|
strcmp(*nodename, "-"))
|
|
|
|
group = 0;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_PREFIX_OP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* schema-qualified operator syntax */
|
|
|
|
*nodename = "OPERATOR()";
|
|
|
|
group = PREC_GROUP_PREFIX_OP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_OP &&
|
|
|
|
aexpr->lexpr != NULL &&
|
|
|
|
aexpr->rexpr == NULL)
|
|
|
|
{
|
|
|
|
/* postfix operator */
|
|
|
|
if (list_length(aexpr->name) == 1)
|
|
|
|
{
|
|
|
|
*nodename = strVal(linitial(aexpr->name));
|
|
|
|
group = PREC_GROUP_POSTFIX_OP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* schema-qualified operator syntax */
|
|
|
|
*nodename = "OPERATOR()";
|
|
|
|
group = PREC_GROUP_POSTFIX_OP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_OP_ANY ||
|
|
|
|
aexpr->kind == AEXPR_OP_ALL)
|
|
|
|
{
|
|
|
|
*nodename = strVal(llast(aexpr->name));
|
|
|
|
group = PREC_GROUP_POSTFIX_OP;
|
|
|
|
}
|
2016-07-28 23:23:03 +02:00
|
|
|
else if (aexpr->kind == AEXPR_DISTINCT ||
|
|
|
|
aexpr->kind == AEXPR_NOT_DISTINCT)
|
Make operator precedence follow the SQL standard more closely.
While the SQL standard is pretty vague on the overall topic of operator
precedence (because it never presents a unified BNF for all expressions),
it does seem reasonable to conclude from the spec for <boolean value
expression> that OR has the lowest precedence, then AND, then NOT, then IS
tests, then the six standard comparison operators, then everything else
(since any non-boolean operator in a WHERE clause would need to be an
argument of one of these).
We were only sort of on board with that: most notably, while "<" ">" and
"=" had properly low precedence, "<=" ">=" and "<>" were treated as generic
operators and so had significantly higher precedence. And "IS" tests were
even higher precedence than those, which is very clearly wrong per spec.
Another problem was that "foo NOT SOMETHING bar" constructs, such as
"x NOT LIKE y", were treated inconsistently because of a bison
implementation artifact: they had the documented precedence with respect
to operators to their right, but behaved like NOT (i.e., very low priority)
with respect to operators to their left.
Fixing the precedence issues is just a small matter of rearranging the
precedence declarations in gram.y, except for the NOT problem, which
requires adding an additional lookahead case in base_yylex() so that we
can attach a different token precedence to NOT LIKE and allied two-word
operators.
The bulk of this patch is not the bug fix per se, but adding logic to
parse_expr.c to allow giving warnings if an expression has changed meaning
because of these precedence changes. These warnings are off by default
and are enabled by the new GUC operator_precedence_warning. It's believed
that very few applications will be affected by these changes, but it was
agreed that a warning mechanism is essential to help debug any that are.
2015-03-11 18:22:52 +01:00
|
|
|
{
|
|
|
|
*nodename = "IS";
|
|
|
|
group = PREC_GROUP_INFIX_IS;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_OF)
|
|
|
|
{
|
|
|
|
*nodename = "IS";
|
|
|
|
group = PREC_GROUP_POSTFIX_IS;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_IN)
|
|
|
|
{
|
|
|
|
*nodename = "IN";
|
|
|
|
if (strcmp(strVal(linitial(aexpr->name)), "=") == 0)
|
|
|
|
group = PREC_GROUP_IN;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_NOT_IN;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_LIKE)
|
|
|
|
{
|
|
|
|
*nodename = "LIKE";
|
|
|
|
if (strcmp(strVal(linitial(aexpr->name)), "~~") == 0)
|
|
|
|
group = PREC_GROUP_LIKE;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_NOT_LIKE;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_ILIKE)
|
|
|
|
{
|
|
|
|
*nodename = "ILIKE";
|
|
|
|
if (strcmp(strVal(linitial(aexpr->name)), "~~*") == 0)
|
|
|
|
group = PREC_GROUP_LIKE;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_NOT_LIKE;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_SIMILAR)
|
|
|
|
{
|
|
|
|
*nodename = "SIMILAR";
|
|
|
|
if (strcmp(strVal(linitial(aexpr->name)), "~") == 0)
|
|
|
|
group = PREC_GROUP_LIKE;
|
|
|
|
else
|
|
|
|
group = PREC_GROUP_NOT_LIKE;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_BETWEEN ||
|
|
|
|
aexpr->kind == AEXPR_BETWEEN_SYM)
|
|
|
|
{
|
|
|
|
Assert(list_length(aexpr->name) == 1);
|
|
|
|
*nodename = strVal(linitial(aexpr->name));
|
|
|
|
group = PREC_GROUP_BETWEEN;
|
|
|
|
}
|
|
|
|
else if (aexpr->kind == AEXPR_NOT_BETWEEN ||
|
|
|
|
aexpr->kind == AEXPR_NOT_BETWEEN_SYM)
|
|
|
|
{
|
|
|
|
Assert(list_length(aexpr->name) == 1);
|
|
|
|
*nodename = strVal(linitial(aexpr->name));
|
|
|
|
group = PREC_GROUP_NOT_BETWEEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(node, NullTest) ||
|
|
|
|
IsA(node, BooleanTest))
|
|
|
|
{
|
|
|
|
*nodename = "IS";
|
|
|
|
group = PREC_GROUP_POSTFIX_IS;
|
|
|
|
}
|
|
|
|
else if (IsA(node, XmlExpr))
|
|
|
|
{
|
|
|
|
XmlExpr *x = (XmlExpr *) node;
|
|
|
|
|
|
|
|
if (x->op == IS_DOCUMENT)
|
|
|
|
{
|
|
|
|
*nodename = "IS";
|
|
|
|
group = PREC_GROUP_POSTFIX_IS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(node, SubLink))
|
|
|
|
{
|
|
|
|
SubLink *s = (SubLink *) node;
|
|
|
|
|
|
|
|
if (s->subLinkType == ANY_SUBLINK ||
|
|
|
|
s->subLinkType == ALL_SUBLINK)
|
|
|
|
{
|
|
|
|
if (s->operName == NIL)
|
|
|
|
{
|
|
|
|
*nodename = "IN";
|
|
|
|
group = PREC_GROUP_IN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*nodename = strVal(llast(s->operName));
|
|
|
|
group = PREC_GROUP_POSTFIX_OP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(node, BoolExpr))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Must dig into NOTs to see if it's IS NOT DOCUMENT or NOT IN. This
|
|
|
|
* opens us to possibly misrecognizing, eg, NOT (x IS DOCUMENT) as a
|
|
|
|
* problematic construct. We can tell the difference by checking
|
|
|
|
* whether the parse locations of the two nodes are identical.
|
|
|
|
*
|
|
|
|
* Note that when we are comparing the child node to its own children,
|
|
|
|
* we will not know that it was a NOT. Fortunately, that doesn't
|
|
|
|
* matter for these cases.
|
|
|
|
*/
|
|
|
|
BoolExpr *b = (BoolExpr *) node;
|
|
|
|
|
|
|
|
if (b->boolop == NOT_EXPR)
|
|
|
|
{
|
|
|
|
Node *child = (Node *) linitial(b->args);
|
|
|
|
|
|
|
|
if (IsA(child, XmlExpr))
|
|
|
|
{
|
|
|
|
XmlExpr *x = (XmlExpr *) child;
|
|
|
|
|
|
|
|
if (x->op == IS_DOCUMENT &&
|
|
|
|
x->location == b->location)
|
|
|
|
{
|
|
|
|
*nodename = "IS";
|
|
|
|
group = PREC_GROUP_POSTFIX_IS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(child, SubLink))
|
|
|
|
{
|
|
|
|
SubLink *s = (SubLink *) child;
|
|
|
|
|
|
|
|
if (s->subLinkType == ANY_SUBLINK && s->operName == NIL &&
|
|
|
|
s->location == b->location)
|
|
|
|
{
|
|
|
|
*nodename = "IN";
|
|
|
|
group = PREC_GROUP_NOT_IN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* helper routine for delivering 9.4-to-9.5 operator precedence warnings
|
|
|
|
*
|
|
|
|
* opgroup/opname/location represent some parent node
|
|
|
|
* lchild, rchild are its left and right children (either could be NULL)
|
|
|
|
*
|
|
|
|
* This should be called before transforming the child nodes, since if a
|
|
|
|
* precedence-driven parsing change has occurred in a query that used to work,
|
|
|
|
* it's quite possible that we'll get a semantic failure while analyzing the
|
|
|
|
* child expression. We want to produce the warning before that happens.
|
|
|
|
* In any case, operator_precedence_group() expects untransformed input.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
emit_precedence_warnings(ParseState *pstate,
|
|
|
|
int opgroup, const char *opname,
|
|
|
|
Node *lchild, Node *rchild,
|
|
|
|
int location)
|
|
|
|
{
|
|
|
|
int cgroup;
|
|
|
|
const char *copname;
|
|
|
|
|
|
|
|
Assert(opgroup > 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Complain if left child, which should be same or higher precedence
|
|
|
|
* according to current rules, used to be lower precedence.
|
|
|
|
*
|
|
|
|
* Exception to precedence rules: if left child is IN or NOT IN or a
|
|
|
|
* postfix operator, the grouping is syntactically forced regardless of
|
|
|
|
* precedence.
|
|
|
|
*/
|
|
|
|
cgroup = operator_precedence_group(lchild, &copname);
|
|
|
|
if (cgroup > 0)
|
|
|
|
{
|
|
|
|
if (oldprecedence_l[cgroup] < oldprecedence_r[opgroup] &&
|
|
|
|
cgroup != PREC_GROUP_IN &&
|
|
|
|
cgroup != PREC_GROUP_NOT_IN &&
|
|
|
|
cgroup != PREC_GROUP_POSTFIX_OP &&
|
|
|
|
cgroup != PREC_GROUP_POSTFIX_IS)
|
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("operator precedence change: %s is now lower precedence than %s",
|
|
|
|
opname, copname),
|
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Complain if right child, which should be higher precedence according to
|
|
|
|
* current rules, used to be same or lower precedence.
|
|
|
|
*
|
|
|
|
* Exception to precedence rules: if right child is a prefix operator, the
|
|
|
|
* grouping is syntactically forced regardless of precedence.
|
|
|
|
*/
|
|
|
|
cgroup = operator_precedence_group(rchild, &copname);
|
|
|
|
if (cgroup > 0)
|
|
|
|
{
|
|
|
|
if (oldprecedence_r[cgroup] <= oldprecedence_l[opgroup] &&
|
|
|
|
cgroup != PREC_GROUP_PREFIX_OP)
|
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("operator precedence change: %s is now lower precedence than %s",
|
|
|
|
opname, copname),
|
|
|
|
parser_errposition(pstate, location)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
/*
|
|
|
|
* Produce a string identifying an expression by kind.
|
|
|
|
*
|
|
|
|
* Note: when practical, use a simple SQL keyword for the result. If that
|
|
|
|
* doesn't work well, check call sites to see whether custom error message
|
|
|
|
* strings are required.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
ParseExprKindName(ParseExprKind exprKind)
|
|
|
|
{
|
|
|
|
switch (exprKind)
|
|
|
|
{
|
|
|
|
case EXPR_KIND_NONE:
|
|
|
|
return "invalid expression context";
|
|
|
|
case EXPR_KIND_OTHER:
|
|
|
|
return "extension expression";
|
|
|
|
case EXPR_KIND_JOIN_ON:
|
|
|
|
return "JOIN/ON";
|
|
|
|
case EXPR_KIND_JOIN_USING:
|
|
|
|
return "JOIN/USING";
|
|
|
|
case EXPR_KIND_FROM_SUBSELECT:
|
|
|
|
return "sub-SELECT in FROM";
|
|
|
|
case EXPR_KIND_FROM_FUNCTION:
|
|
|
|
return "function in FROM";
|
|
|
|
case EXPR_KIND_WHERE:
|
|
|
|
return "WHERE";
|
2015-07-30 00:37:48 +02:00
|
|
|
case EXPR_KIND_POLICY:
|
|
|
|
return "POLICY";
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
case EXPR_KIND_HAVING:
|
|
|
|
return "HAVING";
|
2013-07-17 02:15:36 +02:00
|
|
|
case EXPR_KIND_FILTER:
|
|
|
|
return "FILTER";
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
case EXPR_KIND_WINDOW_PARTITION:
|
|
|
|
return "window PARTITION BY";
|
|
|
|
case EXPR_KIND_WINDOW_ORDER:
|
|
|
|
return "window ORDER BY";
|
|
|
|
case EXPR_KIND_WINDOW_FRAME_RANGE:
|
|
|
|
return "window RANGE";
|
|
|
|
case EXPR_KIND_WINDOW_FRAME_ROWS:
|
|
|
|
return "window ROWS";
|
|
|
|
case EXPR_KIND_SELECT_TARGET:
|
|
|
|
return "SELECT";
|
|
|
|
case EXPR_KIND_INSERT_TARGET:
|
|
|
|
return "INSERT";
|
|
|
|
case EXPR_KIND_UPDATE_SOURCE:
|
|
|
|
case EXPR_KIND_UPDATE_TARGET:
|
|
|
|
return "UPDATE";
|
|
|
|
case EXPR_KIND_GROUP_BY:
|
|
|
|
return "GROUP BY";
|
|
|
|
case EXPR_KIND_ORDER_BY:
|
|
|
|
return "ORDER BY";
|
|
|
|
case EXPR_KIND_DISTINCT_ON:
|
|
|
|
return "DISTINCT ON";
|
|
|
|
case EXPR_KIND_LIMIT:
|
|
|
|
return "LIMIT";
|
|
|
|
case EXPR_KIND_OFFSET:
|
|
|
|
return "OFFSET";
|
|
|
|
case EXPR_KIND_RETURNING:
|
|
|
|
return "RETURNING";
|
|
|
|
case EXPR_KIND_VALUES:
|
2017-01-16 21:23:11 +01:00
|
|
|
case EXPR_KIND_VALUES_SINGLE:
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
return "VALUES";
|
|
|
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
|
|
|
case EXPR_KIND_DOMAIN_CHECK:
|
|
|
|
return "CHECK";
|
|
|
|
case EXPR_KIND_COLUMN_DEFAULT:
|
|
|
|
case EXPR_KIND_FUNCTION_DEFAULT:
|
|
|
|
return "DEFAULT";
|
|
|
|
case EXPR_KIND_INDEX_EXPRESSION:
|
|
|
|
return "index expression";
|
|
|
|
case EXPR_KIND_INDEX_PREDICATE:
|
|
|
|
return "index predicate";
|
|
|
|
case EXPR_KIND_ALTER_COL_TRANSFORM:
|
|
|
|
return "USING";
|
|
|
|
case EXPR_KIND_EXECUTE_PARAMETER:
|
|
|
|
return "EXECUTE";
|
|
|
|
case EXPR_KIND_TRIGGER_WHEN:
|
|
|
|
return "WHEN";
|
Implement table partitioning.
Table partitioning is like table inheritance and reuses much of the
existing infrastructure, but there are some important differences.
The parent is called a partitioned table and is always empty; it may
not have indexes or non-inherited constraints, since those make no
sense for a relation with no data of its own. The children are called
partitions and contain all of the actual data. Each partition has an
implicit partitioning constraint. Multiple inheritance is not
allowed, and partitioning and inheritance can't be mixed. Partitions
can't have extra columns and may not allow nulls unless the parent
does. Tuples inserted into the parent are automatically routed to the
correct partition, so tuple-routing ON INSERT triggers are not needed.
Tuple routing isn't yet supported for partitions which are foreign
tables, and it doesn't handle updates that cross partition boundaries.
Currently, tables can be range-partitioned or list-partitioned. List
partitioning is limited to a single column, but range partitioning can
involve multiple columns. A partitioning "column" can be an
expression.
Because table partitioning is less general than table inheritance, it
is hoped that it will be easier to reason about properties of
partitions, and therefore that this will serve as a better foundation
for a variety of possible optimizations, including query planner
optimizations. The tuple routing based which this patch does based on
the implicit partitioning constraints is an example of this, but it
seems likely that many other useful optimizations are also possible.
Amit Langote, reviewed and tested by Robert Haas, Ashutosh Bapat,
Amit Kapila, Rajkumar Raghuwanshi, Corey Huinker, Jaime Casanova,
Rushabh Lathia, Erik Rijkers, among others. Minor revisions by me.
2016-12-07 19:17:43 +01:00
|
|
|
case EXPR_KIND_PARTITION_EXPRESSION:
|
|
|
|
return "PARTITION BY";
|
2017-11-30 14:46:13 +01:00
|
|
|
case EXPR_KIND_CALL:
|
|
|
|
return "CALL";
|
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression
contained aggregates, window functions, or sub-selects when it shouldn't.
This is grotty, easily forgotten (indeed, we had forgotten to teach
DefineIndex about rejecting window functions), and none too efficient
since it requires extra traversals of the parse tree. To improve matters,
define an enum type that classifies all SQL sub-expressions, store it in
ParseState to show what kind of expression we are currently parsing, and
make transformAggregateCall, transformWindowFuncCall, and transformSubLink
check the expression type and throw error if the type indicates the
construct is disallowed. This allows removal of a large number of ad-hoc
checks scattered around the code base. The enum type is sufficiently
fine-grained that we can still produce error messages of at least the
same specificity as before.
Bringing these error checks together revealed that we'd been none too
consistent about phrasing of the error messages, so standardize the wording
a bit.
Also, rewrite checking of aggregate arguments so that it requires only one
traversal of the arguments, rather than up to three as before.
In passing, clean up some more comments left over from add_missing_from
support, and annotate some tests that I think are dead code now that that's
gone. (I didn't risk actually removing said dead code, though.)
2012-08-10 17:35:33 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is intentionally no default: case here, so that the
|
|
|
|
* compiler will warn if we add a new ParseExprKind without
|
|
|
|
* extending this switch. If we do see an unrecognized value at
|
|
|
|
* runtime, we'll fall through to the "unrecognized" return.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
return "unrecognized expression kind";
|
|
|
|
}
|