Skip to content

Commit 35a449e

Browse files
authored
support EXISTS subquery (#978)
1 parent c1ac30d commit 35a449e

File tree

5 files changed

+63
-7
lines changed

5 files changed

+63
-7
lines changed

server/ast/expr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ func nodeExpr(ctx *Context, node tree.Expr) (vitess.Expr, error) {
727727
Expression: unknownLiteral,
728728
}, nil
729729
case *tree.Subquery:
730-
return nodeSubquery(ctx, node)
730+
return nodeSubqueryOrExists(ctx, node)
731731
case *tree.Tuple:
732732
if len(node.Labels) > 0 {
733733
return nil, fmt.Errorf("tuple labels are not yet supported")

server/ast/subquery.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
package ast
1616

1717
import (
18-
"fmt"
19-
2018
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
2119

2220
"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
@@ -28,9 +26,6 @@ func nodeSubquery(ctx *Context, node *tree.Subquery) (*vitess.Subquery, error) {
2826
if node == nil {
2927
return nil, nil
3028
}
31-
if node.Exists {
32-
return nil, fmt.Errorf("EXISTS is not yet supported")
33-
}
3429
selectStmt, err := nodeSelectStatement(ctx, node.Select)
3530
if err != nil {
3631
return nil, err
@@ -51,3 +46,17 @@ func nodeSubqueryToTableExpr(ctx *Context, node *tree.Subquery) (vitess.TableExp
5146
As: vitess.NewTableIdent(utils.GenerateUniqueAlias()),
5247
}, nil
5348
}
49+
50+
// nodeSubqueryOrExists handles *tree.Subquery nodes that may be an EXISTS subquery, returning a vitess.Expr.
51+
func nodeSubqueryOrExists(ctx *Context, node *tree.Subquery) (vitess.Expr, error) {
52+
subquery, err := nodeSubquery(ctx, node)
53+
if err != nil {
54+
return nil, err
55+
}
56+
if !node.Exists {
57+
return subquery, nil
58+
}
59+
return &vitess.ExistsExpr{
60+
Subquery: subquery,
61+
}, nil
62+
}

testing/go/regression/tool/replay.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ ListenerLoop:
454454
}
455455
}
456456
for _, failQuery := range options.FailQueries {
457-
if message.String == failQuery {
457+
if strings.Contains(message.String, failQuery) {
458458
tracker.Failed++
459459
tracker.AddFailure(ReplayTrackerItem{
460460
Query: message.String,

testing/go/regression/tool/run_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,5 @@ WHERE pg_class.oid=indexrelid
102102
AND indrelid=pg_class_2.oid
103103
AND pg_class_2.relname = 'clstr_tst'
104104
AND indisclustered;`,
105+
`SELECT 1 FROM pg_catalog.pg_constraint WHERE conrelid = i.indrelid AND conindid = i.indexrelid`,
105106
}

testing/go/subqueries_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,49 @@ ORDER BY 1;`,
161161
},
162162
})
163163
}
164+
165+
func TestExistSubquery(t *testing.T) {
166+
RunScripts(t, []ScriptTest{
167+
{
168+
Name: "basic case",
169+
SetUpScript: []string{
170+
`CREATE TABLE test (id INT PRIMARY KEY);`,
171+
`INSERT INTO test VALUES (1), (3), (2);`,
172+
},
173+
Assertions: []ScriptTestAssertion{
174+
{
175+
Query: `SELECT * FROM test WHERE EXISTS (SELECT 123);`,
176+
Expected: []sql.Row{
177+
{1},
178+
{2},
179+
{3},
180+
},
181+
},
182+
{
183+
Query: `SELECT * FROM test WHERE NOT EXISTS (SELECT 123);`,
184+
Expected: []sql.Row{},
185+
},
186+
{
187+
Query: `SELECT 123 WHERE EXISTS (SELECT * FROM test);`,
188+
Expected: []sql.Row{
189+
{123},
190+
},
191+
},
192+
{
193+
Query: `SELECT 123 WHERE EXISTS (SELECT * FROM test WHERE id > 10);`,
194+
Expected: []sql.Row{},
195+
},
196+
{
197+
Query: `SELECT 123 WHERE NOT EXISTS (SELECT * FROM test);`,
198+
Expected: []sql.Row{},
199+
},
200+
{
201+
Query: `SELECT 123 WHERE NOT EXISTS (SELECT * FROM test WHERE id > 10);`,
202+
Expected: []sql.Row{
203+
{123},
204+
},
205+
},
206+
},
207+
},
208+
})
209+
}

0 commit comments

Comments
 (0)