diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 828e11058e9..a2078ec95ef 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10839,6 +10839,29 @@ c_expr: columnref { $$ = $1; } n->location = @1; $$ = (Node *)n; } + | select_with_parens indirection + { + /* + * Because the select_with_parens nonterminal is designed + * to "eat" as many levels of parens as possible, the + * '(' a_expr ')' opt_indirection production above will + * fail to match a sub-SELECT with indirection decoration; + * the sub-SELECT won't be regarded as an a_expr as long + * as there are parens around it. To support applying + * subscripting or field selection to a sub-SELECT result, + * we need this redundant-looking production. + */ + SubLink *n = makeNode(SubLink); + A_Indirection *a = makeNode(A_Indirection); + n->subLinkType = EXPR_SUBLINK; + n->testexpr = NULL; + n->operName = NIL; + n->subselect = $1; + n->location = @1; + a->arg = (Node *)n; + a->indirection = check_indirection($2, yyscanner); + $$ = (Node *)a; + } | EXISTS select_with_parens { SubLink *n = makeNode(SubLink); diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 6a81df95386..8bda3039d68 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -17,6 +17,61 @@ SELECT 1 AS zero WHERE 1 IN (SELECT 2); ------ (0 rows) +-- Check grammar's handling of extra parens in assorted contexts +SELECT * FROM (SELECT 1 AS x) ss; + x +--- + 1 +(1 row) + +SELECT * FROM ((SELECT 1 AS x)) ss; + x +--- + 1 +(1 row) + +(SELECT 2) UNION SELECT 2; + ?column? +---------- + 2 +(1 row) + +((SELECT 2)) UNION SELECT 2; + ?column? +---------- + 2 +(1 row) + +SELECT ((SELECT 2) UNION SELECT 2); + ?column? +---------- + 2 +(1 row) + +SELECT (((SELECT 2)) UNION SELECT 2); + ?column? +---------- + 2 +(1 row) + +SELECT (SELECT ARRAY[1,2,3])[1]; + array +------- + 1 +(1 row) + +SELECT ((SELECT ARRAY[1,2,3]))[2]; + array +------- + 2 +(1 row) + +SELECT (((SELECT ARRAY[1,2,3])))[3]; + array +------- + 3 +(1 row) + -- Set up some simple test tables CREATE TABLE SUBSELECT_TBL ( f1 integer, diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index cba449a203d..8a55474b54a 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -8,6 +8,21 @@ SELECT 1 AS zero WHERE 1 NOT IN (SELECT 1); SELECT 1 AS zero WHERE 1 IN (SELECT 2); +-- Check grammar's handling of extra parens in assorted contexts + +SELECT * FROM (SELECT 1 AS x) ss; +SELECT * FROM ((SELECT 1 AS x)) ss; + +(SELECT 2) UNION SELECT 2; +((SELECT 2)) UNION SELECT 2; + +SELECT ((SELECT 2) UNION SELECT 2); +SELECT (((SELECT 2)) UNION SELECT 2); + +SELECT (SELECT ARRAY[1,2,3])[1]; +SELECT ((SELECT ARRAY[1,2,3]))[2]; +SELECT (((SELECT ARRAY[1,2,3])))[3]; + -- Set up some simple test tables CREATE TABLE SUBSELECT_TBL (