From 409b61f76fb61829cb1955c8256fd43bd8e06a45 Mon Sep 17 00:00:00 2001 From: James Cor Date: Tue, 12 Nov 2024 11:29:48 -0800 Subject: [PATCH 01/13] support with --- server/ast/table_def.go | 2 +- server/ast/with.go | 57 ++++++++++++++++++++++++++++++++++--- server/auth/auth_handler.go | 3 ++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/server/ast/table_def.go b/server/ast/table_def.go index 9f0bed8e77..73b0d2dec8 100644 --- a/server/ast/table_def.go +++ b/server/ast/table_def.go @@ -88,7 +88,7 @@ func assignTableDef(ctx *Context, node tree.TableDef, target *vitess.DDL) error return err } target.OptLike = &vitess.OptLike{ - LikeTable: tableName, + LikeTables: []vitess.TableName{tableName}, } return nil case *tree.UniqueConstraintTableDef: diff --git a/server/ast/with.go b/server/ast/with.go index 165f0a03dc..966db530ab 100644 --- a/server/ast/with.go +++ b/server/ast/with.go @@ -15,17 +15,66 @@ package ast import ( - "fmt" - - vitess "github.com/dolthub/vitess/go/vt/sqlparser" + "fmt" +vitess "github.com/dolthub/vitess/go/vt/sqlparser" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" ) +// TODO: move this else where +// nodeWith handles *tree.CTE nodes. +func nodeCTE(ctx *Context, node *tree.CTE) (*vitess.CommonTableExpr, error) { + if node == nil { + return nil, nil + } + + alias := vitess.NewTableIdent(string(node.Name.Alias)) + cols := make([]vitess.ColIdent, len(node.Name.Cols)) + for _, col := range node.Name.Cols { + cols = append(cols, vitess.NewColIdent(string(col))) + } + + subSelect, ok := node.Stmt.(*tree.Select) + if !ok { + return nil, fmt.Errorf("unsupported CTE statement type: %T", node.Stmt) + } + + selectStmt, err := nodeSelect(ctx, subSelect) + if err != nil { + return nil, err + } + + subQuery := &vitess.Subquery{ + Select: selectStmt, + } + + return &vitess.CommonTableExpr{ + AliasedTableExpr: &vitess.AliasedTableExpr{ + Expr: subQuery, + As: alias, + Auth: vitess.AuthInformation{AuthType: vitess.AuthType_IGNORE}, + }, + Columns: cols, + }, nil +} + // nodeWith handles *tree.With nodes. func nodeWith(ctx *Context, node *tree.With) (*vitess.With, error) { if node == nil { return nil, nil } - return &vitess.With{}, fmt.Errorf("WITH is not yet supported") + + ctes := make([]vitess.TableExpr, len(node.CTEList)) + for i, cte := range node.CTEList { + var err error + ctes[i], err = nodeCTE(ctx, cte) + if err != nil { + return nil, err + } + } + + return &vitess.With{ + Recursive: node.Recursive, + Ctes: ctes, + }, nil } diff --git a/server/auth/auth_handler.go b/server/auth/auth_handler.go index c06469df48..a8f364069e 100644 --- a/server/auth/auth_handler.go +++ b/server/auth/auth_handler.go @@ -97,6 +97,9 @@ func (h *AuthorizationHandler) HandleAuth(ctx *sql.Context, aqs sql.Authorizatio var privileges []Privilege switch auth.AuthType { + case AuthType_IGNORE: + // This means that authorization is being handled elsewhere (such as a child or parent), and should be ignored here + return nil case AuthType_DELETE: privileges = []Privilege{Privilege_DELETE} case AuthType_INSERT: From 9cb819d28c109b6a713bdac9c08e7e17458448a0 Mon Sep 17 00:00:00 2001 From: James Cor Date: Tue, 12 Nov 2024 11:58:57 -0800 Subject: [PATCH 02/13] temp --- server/ast/table_def.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/ast/table_def.go b/server/ast/table_def.go index 73b0d2dec8..7f6ebe821c 100644 --- a/server/ast/table_def.go +++ b/server/ast/table_def.go @@ -88,7 +88,8 @@ func assignTableDef(ctx *Context, node tree.TableDef, target *vitess.DDL) error return err } target.OptLike = &vitess.OptLike{ - LikeTables: []vitess.TableName{tableName}, + LikeTable: tableName, + //LikeTables: []vitess.TableName{tableName}, } return nil case *tree.UniqueConstraintTableDef: From 117d9d4b95170f8905f238ea480af1f4f64f60bd Mon Sep 17 00:00:00 2001 From: James Cor Date: Tue, 12 Nov 2024 13:04:31 -0800 Subject: [PATCH 03/13] append --- server/ast/with.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/ast/with.go b/server/ast/with.go index 966db530ab..714752f832 100644 --- a/server/ast/with.go +++ b/server/ast/with.go @@ -30,8 +30,8 @@ func nodeCTE(ctx *Context, node *tree.CTE) (*vitess.CommonTableExpr, error) { alias := vitess.NewTableIdent(string(node.Name.Alias)) cols := make([]vitess.ColIdent, len(node.Name.Cols)) - for _, col := range node.Name.Cols { - cols = append(cols, vitess.NewColIdent(string(col))) + for i, col := range node.Name.Cols { + cols[i] = vitess.NewColIdent(string(col)) } subSelect, ok := node.Stmt.(*tree.Select) From c3af7ea796ec3116c517836945171157f5ce08fa Mon Sep 17 00:00:00 2001 From: James Cor Date: Tue, 12 Nov 2024 14:27:52 -0800 Subject: [PATCH 04/13] better values conversion --- server/ast/values_clause.go | 14 +++++--------- server/ast/with.go | 7 ++++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/server/ast/values_clause.go b/server/ast/values_clause.go index 8bfe36f8ad..7c150295f0 100644 --- a/server/ast/values_clause.go +++ b/server/ast/values_clause.go @@ -33,19 +33,15 @@ func nodeValuesClause(ctx *Context, node *tree.ValuesClause) (*vitess.Select, er } valTuples[i] = vitess.ValTuple(exprs) } - //TODO: ValuesStatement might need to be aliased - //TODO: is the SelectExprs necessary? return &vitess.Select{ SelectExprs: vitess.SelectExprs{ - &vitess.StarExpr{ - TableName: vitess.TableName{ - Name: vitess.NewTableIdent("*"), - }, - }, + &vitess.StarExpr{}, }, From: vitess.TableExprs{ - &vitess.ValuesStatement{ - Rows: valTuples, + &vitess.AliasedTableExpr{ + Expr: &vitess.ValuesStatement{ + Rows: valTuples, + }, }, }, }, nil diff --git a/server/ast/with.go b/server/ast/with.go index 714752f832..6d0569729a 100644 --- a/server/ast/with.go +++ b/server/ast/with.go @@ -15,10 +15,11 @@ package ast import ( - "fmt" -vitess "github.com/dolthub/vitess/go/vt/sqlparser" + "fmt" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" + + vitess "github.com/dolthub/vitess/go/vt/sqlparser" ) // TODO: move this else where @@ -51,7 +52,7 @@ func nodeCTE(ctx *Context, node *tree.CTE) (*vitess.CommonTableExpr, error) { return &vitess.CommonTableExpr{ AliasedTableExpr: &vitess.AliasedTableExpr{ Expr: subQuery, - As: alias, + As: alias, Auth: vitess.AuthInformation{AuthType: vitess.AuthType_IGNORE}, }, Columns: cols, From 439d419cd01335d1b8f3d1613b6749f109effad0 Mon Sep 17 00:00:00 2001 From: James Cor Date: Tue, 12 Nov 2024 15:33:32 -0800 Subject: [PATCH 05/13] fix insert --- server/ast/insert.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/ast/insert.go b/server/ast/insert.go index 2f7ba88893..3b87ae7d9d 100644 --- a/server/ast/insert.go +++ b/server/ast/insert.go @@ -87,9 +87,11 @@ func nodeInsert(ctx *Context, node *tree.Insert) (*vitess.Insert, error) { // For a ValuesStatement with simple rows, GMS expects AliasedValues if vSelect, ok := rows.(*vitess.Select); ok && len(vSelect.From) == 1 { - if valsStmt, ok := vSelect.From[0].(*vitess.ValuesStatement); ok { - rows = &vitess.AliasedValues{ - Values: valsStmt.Rows, + if aliasedStmt, ok := vSelect.From[0].(*vitess.AliasedTableExpr); ok { + if valsStmt, ok := aliasedStmt.Expr.(*vitess.ValuesStatement); ok { + rows = &vitess.AliasedValues{ + Values: valsStmt.Rows, + } } } } From af6afcbf965c4c4c75ac4901c2b6dca6d46c80d8 Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 01:16:34 -0800 Subject: [PATCH 06/13] fix --- server/ast/aliased_table_expr.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/server/ast/aliased_table_expr.go b/server/ast/aliased_table_expr.go index 8ea1e10427..a12af43f2c 100644 --- a/server/ast/aliased_table_expr.go +++ b/server/ast/aliased_table_expr.go @@ -72,16 +72,18 @@ func nodeAliasedTableExpr(ctx *Context, node *tree.AliasedTableExpr) (*vitess.Al } if inSelect, ok := innerSelect.(*vitess.Select); ok { if len(inSelect.From) == 1 { - if valuesStmt, ok := inSelect.From[0].(*vitess.ValuesStatement); ok { - if len(node.As.Cols) > 0 { - columns := make([]vitess.ColIdent, len(node.As.Cols)) - for i := range node.As.Cols { - columns[i] = vitess.NewColIdent(string(node.As.Cols[i])) + if aliasedTblExpr, ok := inSelect.From[0].(*vitess.AliasedTableExpr); ok { + if valuesStmt, ok := aliasedTblExpr.Expr.(*vitess.ValuesStatement); ok { + if len(node.As.Cols) > 0 { + columns := make([]vitess.ColIdent, len(node.As.Cols)) + for i := range node.As.Cols { + columns[i] = vitess.NewColIdent(string(node.As.Cols[i])) + } + valuesStmt.Columns = columns } - valuesStmt.Columns = columns + aliasExpr = valuesStmt + break } - aliasExpr = valuesStmt - break } } } From 3181fb1c50abd1cb6578f916798c8e0547d3e4fc Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 11:14:24 -0800 Subject: [PATCH 07/13] cleaning up and adding enginetests --- server/ast/with.go | 1 - testing/go/with_test.go | 80 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 testing/go/with_test.go diff --git a/server/ast/with.go b/server/ast/with.go index 6d0569729a..8b4551d756 100644 --- a/server/ast/with.go +++ b/server/ast/with.go @@ -22,7 +22,6 @@ import ( vitess "github.com/dolthub/vitess/go/vt/sqlparser" ) -// TODO: move this else where // nodeWith handles *tree.CTE nodes. func nodeCTE(ctx *Context, node *tree.CTE) (*vitess.CommonTableExpr, error) { if node == nil { diff --git a/testing/go/with_test.go b/testing/go/with_test.go new file mode 100644 index 0000000000..e6dc3117eb --- /dev/null +++ b/testing/go/with_test.go @@ -0,0 +1,80 @@ +// 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 TestWithStatements(t *testing.T) { + RunScripts(t, WithStatementTests) +} + +var WithStatementTests = []ScriptTest{ + { + Name: "basic values statements", + SetUpScript: []string{ + "create table t (i int primary key);", + "insert into t values (1), (2), (3);", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "with cte as (select 1) select * from cte;", + Expected: []sql.Row{ + {1}, + }, + }, + { + Query: "with cte as (select 1, 2, 3 union select 4, 5, 6) select * from cte;", + Expected: []sql.Row{ + {1, 2, 3}, + {4, 5, 6}, + }, + }, + { + Query: "with cte as (values (1)) select * from cte;", + Expected: []sql.Row{ + {1}, + }, + }, + { + Query: "with cte as (values (1, 2, 3) union values (4, 5, 6)) select * from cte;", + Expected: []sql.Row{ + {1, 2, 3}, + {4, 5, 6}, + }, + }, + { + Query: "with cte as (select 1, 2, 3 union values (4, 5, 6)) select * from cte;", + Expected: []sql.Row{ + {1, 2, 3}, + {4, 5, 6}, + }, + }, + { + Query: "with recursive cte(x) as (select 1 union all select x + 1 from cte) select * from cte limit 5;", + Expected: []sql.Row{ + {1}, + {2}, + {3}, + {4}, + {5}, + }, + }, + }, + }, +} From 6af307b504c6b4a3f1637dde33d9d9dcd1e6d89c Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 11:14:46 -0800 Subject: [PATCH 08/13] unskipping test --- testing/go/dolt_tables_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/testing/go/dolt_tables_test.go b/testing/go/dolt_tables_test.go index 5a3ffa9d76..fcdf047ea3 100755 --- a/testing/go/dolt_tables_test.go +++ b/testing/go/dolt_tables_test.go @@ -109,7 +109,6 @@ func TestUserSpaceDoltTables(t *testing.T) { }, }, { - Skip: true, // TODO: dolt blame will not work until the first query (with clause) works Name: "dolt blame with tablename", SetUpScript: []string{ "CREATE TABLE test (id INT PRIMARY KEY)", @@ -118,7 +117,6 @@ func TestUserSpaceDoltTables(t *testing.T) { }, Assertions: []ScriptTestAssertion{ { - // TODO: WITH is not yet supported Query: `WITH sorted_diffs_by_pk AS (SELECT "to_id", From 0c3b0ea2b5c67bdc9fc36cf0384683fde12160fb Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 12:56:47 -0800 Subject: [PATCH 09/13] huh --- testing/go/dolt_tables_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/go/dolt_tables_test.go b/testing/go/dolt_tables_test.go index fcdf047ea3..d02651b330 100755 --- a/testing/go/dolt_tables_test.go +++ b/testing/go/dolt_tables_test.go @@ -109,6 +109,7 @@ func TestUserSpaceDoltTables(t *testing.T) { }, }, { + Skip: true, Name: "dolt blame with tablename", SetUpScript: []string{ "CREATE TABLE test (id INT PRIMARY KEY)", From 2b8adb40504654b5b06822324165704585166ee4 Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 12:59:27 -0800 Subject: [PATCH 10/13] readd todo --- testing/go/dolt_tables_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/go/dolt_tables_test.go b/testing/go/dolt_tables_test.go index d02651b330..b1533be026 100755 --- a/testing/go/dolt_tables_test.go +++ b/testing/go/dolt_tables_test.go @@ -109,7 +109,7 @@ func TestUserSpaceDoltTables(t *testing.T) { }, }, { - Skip: true, + Skip: true, // TODO: dolt blame will not work until the first query (with clause) works Name: "dolt blame with tablename", SetUpScript: []string{ "CREATE TABLE test (id INT PRIMARY KEY)", From b9e368045975ab6d008456d6b5c51715d6afd122 Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 13:01:26 -0800 Subject: [PATCH 11/13] aaaaaaaahhhhhhhhhh foramtting whyuadrgfuin ak --- testing/go/with_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/go/with_test.go b/testing/go/with_test.go index e6dc3117eb..3fdd03e3a4 100644 --- a/testing/go/with_test.go +++ b/testing/go/with_test.go @@ -26,7 +26,7 @@ func TestWithStatements(t *testing.T) { var WithStatementTests = []ScriptTest{ { - Name: "basic values statements", + Name: "basic values statements", SetUpScript: []string{ "create table t (i int primary key);", "insert into t values (1), (2), (3);", From 0bfadf0261af4e6aec345c7868e40ecdfde77395 Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 13:08:53 -0800 Subject: [PATCH 12/13] adding cte auth test --- testing/go/auth_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/testing/go/auth_test.go b/testing/go/auth_test.go index 7f9b31463b..d7c4dac18a 100644 --- a/testing/go/auth_test.go +++ b/testing/go/auth_test.go @@ -429,6 +429,12 @@ func TestAuthTests(t *testing.T) { Password: `a`, ExpectedErr: `denied`, }, + { + Query: `WITH cte AS (SELECT * FROM test ORDER BY pk) SELECT * FROM cte;`, + Username: `user1`, + Password: `a`, + ExpectedErr: `denied`, + }, { Query: `INSERT INTO test VALUES (10);`, Username: `user1`, From 7bd6c411b605dd4fbe8f257e7415b07d0178e497 Mon Sep 17 00:00:00 2001 From: James Cor Date: Wed, 13 Nov 2024 14:15:46 -0800 Subject: [PATCH 13/13] skipped cte auth tests --- testing/go/auth_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testing/go/auth_test.go b/testing/go/auth_test.go index d7c4dac18a..38b28b1dff 100644 --- a/testing/go/auth_test.go +++ b/testing/go/auth_test.go @@ -465,6 +465,13 @@ func TestAuthTests(t *testing.T) { Password: `a`, Expected: []sql.Row{{1}, {6}, {7}}, }, + { + Skip: true, // CTEs are seen as different tables + Query: `WITH cte AS (SELECT * FROM test ORDER BY pk) SELECT * FROM cte;`, + Username: `user1`, + Password: `a`, + Expected: []sql.Row{{1}, {6}, {7}}, + }, { Query: `INSERT INTO test VALUES (10);`, Username: `user1`,