aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_clause.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-07-03 19:07:54 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-07-03 19:07:54 +0000
commitb89140a7eccd0247fa910346da79e701d78a8152 (patch)
tree4b5e25e4407755598f6f352825ebffcff32db7c8 /src/backend/parser/parse_clause.c
parent455891bf96f6ee3dda9150fe83af2be5e86a572b (diff)
downloadpostgresql-b89140a7eccd0247fa910346da79e701d78a8152.tar.gz
postgresql-b89140a7eccd0247fa910346da79e701d78a8152.zip
Do honest transformation and preprocessing of LIMIT/OFFSET clauses,
instead of the former kluge whereby gram.y emitted already-transformed expressions. This is needed so that Params appearing in these clauses actually work correctly. I suppose some might claim that the side effect of 'SELECT ... LIMIT 2+2' working is a new feature, but I say this is a bug fix.
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r--src/backend/parser/parse_clause.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 4d08704da66..9094a14ae53 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.116 2003/06/16 02:03:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.117 2003/07/03 19:07:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -317,10 +317,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
save_namespace = pstate->p_namespace;
pstate->p_namespace = makeList2(j->larg, j->rarg);
- /* This part is just like transformWhereClause() */
- result = transformExpr(pstate, j->quals);
-
- result = coerce_to_boolean(pstate, result, "JOIN/ON");
+ result = transformWhereClause(pstate, j->quals, "JOIN/ON");
pstate->p_namespace = save_namespace;
@@ -945,10 +942,38 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
/*
* transformWhereClause -
- * transforms the qualification and make sure it is of type Boolean
+ * Transform the qualification and make sure it is of type boolean.
+ * Used for WHERE and allied clauses.
+ *
+ * constructName does not affect the semantics, but is used in error messages
+ */
+Node *
+transformWhereClause(ParseState *pstate, Node *clause,
+ const char *constructName)
+{
+ Node *qual;
+
+ if (clause == NULL)
+ return NULL;
+
+ qual = transformExpr(pstate, clause);
+
+ qual = coerce_to_boolean(pstate, qual, constructName);
+
+ return qual;
+}
+
+
+/*
+ * transformLimitClause -
+ * Transform the expression and make sure it is of type integer.
+ * Used for LIMIT and allied clauses.
+ *
+ * constructName does not affect the semantics, but is used in error messages
*/
Node *
-transformWhereClause(ParseState *pstate, Node *clause)
+transformLimitClause(ParseState *pstate, Node *clause,
+ const char *constructName)
{
Node *qual;
@@ -957,7 +982,31 @@ transformWhereClause(ParseState *pstate, Node *clause)
qual = transformExpr(pstate, clause);
- qual = coerce_to_boolean(pstate, qual, "WHERE");
+ qual = coerce_to_integer(pstate, qual, constructName);
+
+ /*
+ * LIMIT can't refer to any vars or aggregates of the current query;
+ * we don't allow subselects either (though that case would at least
+ * be sensible)
+ */
+ if (contain_vars_of_level(qual, 0))
+ {
+ /* translator: %s is name of a SQL construct, eg LIMIT */
+ elog(ERROR, "argument of %s must not contain variables",
+ constructName);
+ }
+ if (checkExprHasAggs(qual))
+ {
+ /* translator: %s is name of a SQL construct, eg LIMIT */
+ elog(ERROR, "argument of %s must not contain aggregates",
+ constructName);
+ }
+ if (contain_subplans(qual))
+ {
+ /* translator: %s is name of a SQL construct, eg LIMIT */
+ elog(ERROR, "argument of %s must not contain subselects",
+ constructName);
+ }
return qual;
}