aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/parser/gram.y23
-rw-r--r--src/test/regress/expected/subselect.out55
-rw-r--r--src/test/regress/sql/subselect.sql15
3 files changed, 93 insertions, 0 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0fd96369197..74c50bf6b07 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -8712,6 +8712,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);
+ $$ = (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 eae1b611dc8..850777acd5c 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];
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT ((SELECT ARRAY[1,2,3]))[2];
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT (((SELECT ARRAY[1,2,3])))[3];
+ ?column?
+----------
+ 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 7d7830dfe23..8ca7a3bd2fb 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 (