Allow FOR UPDATE to appear after LIMIT/OFFSET to match MySQL syntax and as

a more logical ordering.
This commit is contained in:
Bruce Momjian 2002-08-28 14:35:37 +00:00
parent 8e4357d8ad
commit 6077db92c2
4 changed files with 43 additions and 32 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.56 2002/08/15 02:59:18 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.57 2002/08/28 14:35:37 momjian Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -28,9 +28,9 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
[ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ] [ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ]
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ] [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ]
[ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ] [ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ] [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ]
where <replaceable class="PARAMETER">from_item</replaceable> can be: where <replaceable class="PARAMETER">from_item</replaceable> can be:
@ -107,9 +107,9 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
<term><replaceable class="PARAMETER">select</replaceable></term> <term><replaceable class="PARAMETER">select</replaceable></term>
<listitem> <listitem>
<para> <para>
A select statement with all features except the ORDER BY, FOR UPDATE, A select statement with all features except the ORDER BY,
and LIMIT clauses (even those can be used when the select is LIMIT/OFFSET, and FOR UPDATE clauses (even those can be used when the
parenthesized). select is parenthesized).
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -354,17 +354,17 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
(See <xref linkend="sql-except" endterm="sql-except-title">.) (See <xref linkend="sql-except" endterm="sql-except-title">.)
</para> </para>
<para>
The FOR UPDATE clause allows the SELECT statement to perform
exclusive locking of selected rows.
</para>
<para> <para>
The LIMIT clause allows a subset of the rows produced by the query The LIMIT clause allows a subset of the rows produced by the query
to be returned to the user. to be returned to the user.
(See <xref linkend="sql-limit" endterm="sql-limit-title">.) (See <xref linkend="sql-limit" endterm="sql-limit-title">.)
</para> </para>
<para>
The FOR UPDATE clause allows the SELECT statement to perform
exclusive locking of selected rows.
</para>
<para> <para>
You must have SELECT privilege to a table to read its values You must have SELECT privilege to a table to read its values
(See the <command>GRANT</command>/<command>REVOKE</command> statements). (See the <command>GRANT</command>/<command>REVOKE</command> statements).
@ -666,8 +666,8 @@ SELECT name FROM distributors ORDER BY code;
where where
<replaceable class="PARAMETER">table_query</replaceable> <replaceable class="PARAMETER">table_query</replaceable>
specifies any select expression without an ORDER BY, FOR UPDATE, specifies any select expression without an ORDER BY, LIMIT, or FOR UPDATE
or LIMIT clause. (ORDER BY and LIMIT can be attached to a sub-expression clause. (ORDER BY and LIMIT can be attached to a sub-expression
if it is enclosed in parentheses. Without parentheses, these clauses if it is enclosed in parentheses. Without parentheses, these clauses
will be taken to apply to the result of the UNION, not to its right-hand will be taken to apply to the result of the UNION, not to its right-hand
input expression.) input expression.)
@ -716,8 +716,8 @@ SELECT name FROM distributors ORDER BY code;
where where
<replaceable class="PARAMETER">table_query</replaceable> <replaceable class="PARAMETER">table_query</replaceable>
specifies any select expression without an ORDER BY, FOR UPDATE, specifies any select expression without an ORDER BY, LIMIT, or
or LIMIT clause. FOR UPDATE clause.
</para> </para>
<para> <para>
@ -757,8 +757,8 @@ SELECT name FROM distributors ORDER BY code;
where where
<replaceable class="PARAMETER">table_query</replaceable> <replaceable class="PARAMETER">table_query</replaceable>
specifies any select expression without an ORDER BY, FOR UPDATE, specifies any select expression without an ORDER BY, LIMIT,
or LIMIT clause. or FOR UPDATE clause.
</para> </para>
<para> <para>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.18 2002/04/23 02:07:16 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.19 2002/08/28 14:35:37 momjian Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -29,9 +29,9 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
[ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ] [ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ]
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ] [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ]
[ LIMIT [ <replaceable class="PARAMETER">start</replaceable> , ] { <replaceable class="PARAMETER">count</replaceable> | ALL } ] [ LIMIT [ <replaceable class="PARAMETER">start</replaceable> , ] { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ] [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ]
where <replaceable class="PARAMETER">from_item</replaceable> can be: where <replaceable class="PARAMETER">from_item</replaceable> can be:

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/sql.sgml,v 1.26 2002/03/15 16:16:31 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/sql.sgml,v 1.27 2002/08/28 14:35:36 momjian Exp $
--> -->
<chapter id="sql"> <chapter id="sql">
@ -863,9 +863,9 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
[ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ] [ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ]
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ] [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">class_name</replaceable> [, ...] ] ]
[ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ] [ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ] [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">class_name</replaceable> [, ...] ] ]
</synopsis> </synopsis>
</para> </para>

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.361 2002/08/27 04:55:08 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.362 2002/08/28 14:35:37 momjian Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -208,8 +208,8 @@ static void doNegateFloat(Value *v);
func_args_list, func_as, createfunc_opt_list func_args_list, func_as, createfunc_opt_list
oper_argtypes, RuleActionList, RuleActionMulti, oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list, opt_column_list, columnList, opt_name_list,
sort_clause, sortby_list, index_params, index_list, sort_clause, opt_sort_clause, sortby_list, index_params,
name_list, from_clause, from_list, opt_array_bounds, index_list,name_list, from_clause, from_list, opt_array_bounds,
qualified_name_list, any_name, any_name_list, qualified_name_list, any_name, any_name_list,
any_operator, expr_list, dotted_name, attrs, any_operator, expr_list, dotted_name, attrs,
target_list, update_target_list, insert_column_list, target_list, update_target_list, insert_column_list,
@ -4180,26 +4180,32 @@ select_with_parens:
| '(' select_with_parens ')' { $$ = $2; } | '(' select_with_parens ')' { $$ = $2; }
; ;
/*
* FOR UPDATE may be before or after LIMIT/OFFSET.
* In <=7.2.X, LIMIT/OFFSET had to be after FOR UPDATE
* We now support both orderings, but prefer LIMIT/OFFSET before FOR UPDATE
* 2002-08-28 bjm
*/
select_no_parens: select_no_parens:
simple_select { $$ = $1; } simple_select { $$ = $1; }
| select_clause sort_clause opt_for_update_clause opt_select_limit | select_clause sort_clause
{
insertSelectOptions((SelectStmt *) $1, $2, NIL,
NULL, NULL);
$$ = $1;
}
| select_clause opt_sort_clause for_update_clause opt_select_limit
{ {
insertSelectOptions((SelectStmt *) $1, $2, $3, insertSelectOptions((SelectStmt *) $1, $2, $3,
nth(0, $4), nth(1, $4)); nth(0, $4), nth(1, $4));
$$ = $1; $$ = $1;
} }
| select_clause for_update_clause opt_select_limit | select_clause opt_sort_clause select_limit opt_for_update_clause
{ {
insertSelectOptions((SelectStmt *) $1, NIL, $2, insertSelectOptions((SelectStmt *) $1, $2, $4,
nth(0, $3), nth(1, $3)); nth(0, $3), nth(1, $3));
$$ = $1; $$ = $1;
} }
| select_clause select_limit
{
insertSelectOptions((SelectStmt *) $1, NIL, NIL,
nth(0, $2), nth(1, $2));
$$ = $1;
}
; ;
select_clause: select_clause:
@ -4335,6 +4341,11 @@ opt_distinct:
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
opt_sort_clause:
sort_clause { $$ = $1;}
| /*EMPTY*/ { $$ = NIL; }
;
sort_clause: sort_clause:
ORDER BY sortby_list { $$ = $3; } ORDER BY sortby_list { $$ = $3; }
; ;