Skip to content

Commit 3eca185

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 34a65fc commit 3eca185

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
@@ -2566,7 +2566,7 @@ CheckSelectLocking(Query *qry, LockClauseStrength strength)
25662566
translator: %s is a SQL row locking clause such as FOR UPDATE */
25672567
errmsg("%s is not allowed with DISTINCT clause",
25682568
LCS_asString(strength))));
2569-
if (qry->groupClause != NIL)
2569+
if (qry->groupClause != NIL || qry->groupingSets != NIL)
25702570
ereport(ERROR,
25712571
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
25722572
/*------

src/backend/utils/adt/selfuncs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -4746,7 +4746,8 @@ examine_simple_variable(PlannerInfo *root, Var *var,
47464746
* of learning something even with it.
47474747
*/
47484748
if (subquery->setOperations ||
4749-
subquery->groupClause)
4749+
subquery->groupClause ||
4750+
subquery->groupingSets)
47504751
return;
47514752

47524753
/*

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)