diff --git a/server/ast/union_clause.go b/server/ast/union_clause.go index d1e8ec15ee..acad8ed534 100644 --- a/server/ast/union_clause.go +++ b/server/ast/union_clause.go @@ -50,8 +50,11 @@ func nodeUnionClause(ctx *Context, node *tree.UnionClause) (*vitess.SetOp, error unionType = vitess.IntersectStr } case tree.ExceptOp: - // This is not implemented on the GMS side, so we'll throw an appropriate error here - return nil, fmt.Errorf("EXCEPT is not yet supported") + if node.All { + unionType = vitess.ExceptAllStr + } else { + unionType = vitess.ExceptStr + } default: return nil, fmt.Errorf("unknown type of UNION operator: `%s`", node.Type.String()) } diff --git a/testing/go/union_test.go b/testing/go/union_test.go new file mode 100644 index 0000000000..40af1a445b --- /dev/null +++ b/testing/go/union_test.go @@ -0,0 +1,128 @@ +// Copyright 2024 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package _go + +import ( + "testing" + + "github.com/dolthub/go-mysql-server/sql" +) + +func TestUnion(t *testing.T) { + RunScripts(t, []ScriptTest{ + { + Name: "union tests", + SetUpScript: []string{ + `CREATE TABLE t1 (i INT PRIMARY KEY);`, + `CREATE TABLE t2 (j INT PRIMARY KEY);`, + `INSERT INTO t1 VALUES (1), (2), (3);`, + `INSERT INTO t2 VALUES (2), (3), (4);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM t1 UNION SELECT * FROM t2;`, + Expected: []sql.Row{ + {1}, + {2}, + {3}, + {4}, + }, + }, + { + Query: `SELECT 123 UNION SELECT 456;`, + Expected: []sql.Row{ + {123}, + {456}, + }, + }, + { + Query: `SELECT * FROM (VALUES (123), (456)) a UNION SELECT * FROM (VALUES (456), (789)) b;`, + Expected: []sql.Row{ + {123}, + {456}, + {789}, + }, + }, + }, + }, + }) +} + +func TestIntersect(t *testing.T) { + RunScripts(t, []ScriptTest{ + { + Name: "intersect tests", + SetUpScript: []string{ + `CREATE TABLE t1 (i INT PRIMARY KEY);`, + `CREATE TABLE t2 (j INT PRIMARY KEY);`, + `INSERT INTO t1 VALUES (1), (2), (3);`, + `INSERT INTO t2 VALUES (2), (3), (4);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM t1 INTERSECT SELECT * FROM t2;`, + Expected: []sql.Row{ + {2}, + {3}, + }, + }, + { + Query: `SELECT 123 INTERSECT SELECT 456;`, + Expected: []sql.Row{}, + }, + { + Query: `SELECT * FROM (VALUES (123), (456)) a INTERSECT SELECT * FROM (VALUES (456), (789)) b;`, + Expected: []sql.Row{ + {456}, + }, + }, + }, + }, + }) +} + +func TestExcept(t *testing.T) { + RunScripts(t, []ScriptTest{ + { + Name: "except tests", + SetUpScript: []string{ + `CREATE TABLE t1 (i INT PRIMARY KEY);`, + `CREATE TABLE t2 (j INT PRIMARY KEY);`, + `INSERT INTO t1 VALUES (1), (2), (3);`, + `INSERT INTO t2 VALUES (2), (3), (4);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM t1 EXCEPT SELECT * FROM t2;`, + Expected: []sql.Row{ + {1}, + }, + }, + { + Query: `SELECT 123 EXCEPT SELECT 456;`, + Expected: []sql.Row{ + {123}, + }, + }, + { + Query: `SELECT * FROM (VALUES (123), (456)) a EXCEPT SELECT * FROM (VALUES (456), (789)) b;`, + Expected: []sql.Row{ + {123}, + }, + }, + }, + }, + }) +}