Skip to content

Commit 1103033

Browse files
committed
Reject SELECT ... GROUP BY GROUPING SETS (()) FOR UPDATE.
This case should be disallowed, just as FOR UPDATE with a plain GROUP BY is disallowed; FOR UPDATE only makes sense when each row of the query result can be identified with a single table row. However, we missed teaching CheckSelectLocking() to check groupingSets as well as groupClause, so that it would allow degenerate grouping sets. That resulted in a bad plan and a null-pointer dereference in the executor. Looking around for other instances of the same bug, the only one I found was in examine_simple_variable(). That'd just lead to silly estimates, but it should be fixed too. Per private report from Yaoguang Chen. Back-patch to all supported branches.
1 parent eb89cb4 commit 1103033

File tree

4 files changed

+12
-2
lines changed

4 files changed

+12
-2
lines changed

src/backend/parser/analyze.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3019,7 +3019,7 @@ CheckSelectLocking(Query *qry, LockClauseStrength strength)
30193019
translator: %s is a SQL row locking clause such as FOR UPDATE */
30203020
errmsg("%s is not allowed with DISTINCT clause",
30213021
LCS_asString(strength))));
3022-
if (qry->groupClause != NIL)
3022+
if (qry->groupClause != NIL || qry->groupingSets != NIL)
30233023
ereport(ERROR,
30243024
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
30253025
/*------

src/backend/utils/adt/selfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -5497,7 +5497,8 @@ examine_simple_variable(PlannerInfo *root, Var *var,
54975497
* of learning something even with it.
54985498
*/
54995499
if (subquery->setOperations ||
5500-
subquery->groupClause)
5500+
subquery->groupClause ||
5501+
subquery->groupingSets)
55015502
return;
55025503

55035504
/*

src/test/regress/expected/errors.out

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ select distinct on (foobar) * from pg_database;
5050
ERROR: column "foobar" does not exist
5151
LINE 1: select distinct on (foobar) * from pg_database;
5252
^
53+
-- grouping with FOR UPDATE
54+
select null from pg_database group by datname for update;
55+
ERROR: FOR UPDATE is not allowed with GROUP BY clause
56+
select null from pg_database group by grouping sets (()) for update;
57+
ERROR: FOR UPDATE is not allowed with GROUP BY clause
5358
--
5459
-- DELETE
5560
-- missing relation name (this had better not wildcard!)

src/test/regress/sql/errors.sql

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ select * from pg_database where pg_database.datname = nonesuch;
3737
-- bad attribute name in select distinct on
3838
select distinct on (foobar) * from pg_database;
3939

40+
-- grouping with FOR UPDATE
41+
select null from pg_database group by datname for update;
42+
select null from pg_database group by grouping sets (()) for update;
43+
4044

4145
--
4246
-- DELETE

0 commit comments

Comments
 (0)