Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 762fe98

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 02037af commit 762fe98

File tree

4 files changed

+12
-2
lines changed

4 files changed

+12
-2
lines changed

src/backend/parser/analyze.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2679,7 +2679,7 @@ CheckSelectLocking(Query *qry, LockClauseStrength strength)
26792679
translator: %s is a SQL row locking clause such as FOR UPDATE */
26802680
errmsg("%s is not allowed with DISTINCT clause",
26812681
LCS_asString(strength))));
2682-
if (qry->groupClause != NIL)
2682+
if (qry->groupClause != NIL || qry->groupingSets != NIL)
26832683
ereport(ERROR,
26842684
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
26852685
/*------

src/backend/utils/adt/selfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4929,7 +4929,8 @@ examine_simple_variable(PlannerInfo *root, Var *var,
49294929
* of learning something even with it.
49304930
*/
49314931
if (subquery->setOperations ||
4932-
subquery->groupClause)
4932+
subquery->groupClause ||
4933+
subquery->groupingSets)
49334934
return;
49344935

49354936
/*

src/test/regress/expected/errors.out

Lines changed: 5 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
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)