From c02799c67a8f5295b554136ff727143b18b125b6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 10:19:39 -0700 Subject: [PATCH 01/20] Removed AS OF from from_list --- postgres/parser/parser/sql.y | 8 ++++++-- postgres/parser/sem/tree/pretty.go | 6 ------ postgres/parser/sem/tree/select.go | 5 ----- postgres/parser/sem/tree/walk.go | 13 +------------ testing/go/enginetest/doltgres_engine_test.go | 1 - 5 files changed, 7 insertions(+), 26 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 02b69ca6dc..7b828b0f8b 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10764,9 +10764,9 @@ values_clause: // where_clause - qualifications for joins or restrictions from_clause: - FROM from_list opt_as_of_clause + FROM from_list { - $$.val = tree.From{Tables: $2.tblExprs(), AsOf: $3.asOfClause()} + $$.val = tree.From{Tables: $2.tblExprs()} } | FROM error // SHOW HELP: | /* EMPTY */ @@ -11091,6 +11091,10 @@ as_of_clause: { $$.val = tree.AsOfClause{Expr: $5.expr()} } +| AS_LA OF a_expr + { + $$.val = tree.AsOfClause{Expr: $3.expr()} + } opt_as_of_clause: as_of_clause diff --git a/postgres/parser/sem/tree/pretty.go b/postgres/parser/sem/tree/pretty.go index 4074878b3c..dcf87b8d34 100644 --- a/postgres/parser/sem/tree/pretty.go +++ b/postgres/parser/sem/tree/pretty.go @@ -597,12 +597,6 @@ func (node *From) docRow(p *PrettyCfg) pretty.TableRow { return emptyRow } d := node.Tables.doc(p) - if node.AsOf.Expr != nil { - d = p.nestUnder( - d, - p.Doc(&node.AsOf), - ) - } return p.row("FROM", d) } diff --git a/postgres/parser/sem/tree/select.go b/postgres/parser/sem/tree/select.go index 7d130cf1cf..6de18baada 100644 --- a/postgres/parser/sem/tree/select.go +++ b/postgres/parser/sem/tree/select.go @@ -222,17 +222,12 @@ func (a *AsOfClause) Format(ctx *FmtCtx) { // From represents a FROM clause. type From struct { Tables TableExprs - AsOf AsOfClause } // Format implements the NodeFormatter interface. func (node *From) Format(ctx *FmtCtx) { ctx.WriteString("FROM ") ctx.FormatNode(&node.Tables) - if node.AsOf.Expr != nil { - ctx.WriteByte(' ') - ctx.FormatNode(&node.AsOf) - } } // TableExprs represents a list of table expressions. diff --git a/postgres/parser/sem/tree/walk.go b/postgres/parser/sem/tree/walk.go index 7bc0d3bd9a..d5bfbd9ebc 100644 --- a/postgres/parser/sem/tree/walk.go +++ b/postgres/parser/sem/tree/walk.go @@ -1178,7 +1178,6 @@ func (stmt *SelectClause) copyNode() *SelectClause { stmtCopy.Exprs = append(SelectExprs(nil), stmt.Exprs...) stmtCopy.From = From{ Tables: append(TableExprs(nil), stmt.From.Tables...), - AsOf: stmt.From.AsOf, } if stmt.Where != nil { wCopy := *stmt.Where @@ -1206,17 +1205,7 @@ func (stmt *SelectClause) walkStmt(v Visitor) Statement { ret.Exprs[i].Expr = e } } - - if stmt.From.AsOf.Expr != nil { - e, changed := WalkExpr(v, stmt.From.AsOf.Expr) - if changed { - if ret == stmt { - ret = stmt.copyNode() - } - ret.From.AsOf.Expr = e - } - } - + if stmt.Where != nil { e, changed := WalkExpr(v, stmt.Where.Expr) if changed { diff --git a/testing/go/enginetest/doltgres_engine_test.go b/testing/go/enginetest/doltgres_engine_test.go index 7a4a73bb10..a9aa1479f5 100755 --- a/testing/go/enginetest/doltgres_engine_test.go +++ b/testing/go/enginetest/doltgres_engine_test.go @@ -1147,7 +1147,6 @@ func TestDoltRebasePrepared(t *testing.T) { } func TestDoltRevert(t *testing.T) { - t.Skip() h := newDoltgresServerHarness(t) denginetest.RunDoltRevertTests(t, h) } From 2295ca853ded68fc02be8d810ba9db513cc74b83 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 10:27:34 -0700 Subject: [PATCH 02/20] Successful additoin of as_of_clause to from rule, need to generalize --- postgres/parser/parser/sql.y | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 7b828b0f8b..e7ed32e16d 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10890,6 +10890,13 @@ table_ref: As: $4.aliasClause(), } } +| numeric_table_ref as_of_clause + { + /* SKIP DOC */ + $$.val = &tree.AliasedTableExpr{ + Expr: $1.tblExpr(), + } + } | relation_expr opt_index_flags opt_ordinality opt_alias_clause { name := $1.unresolvedObjectName().ToTableName() From 816181e8f80816df358278f2c628cb7320fd44a0 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 15:19:34 -0700 Subject: [PATCH 03/20] Starting down the combinatorial explosion route --- postgres/parser/parser/sql.y | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index e7ed32e16d..cc22c21a07 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -1261,7 +1261,7 @@ func (u *sqlSymUnion) aggregatesToDrop() []tree.AggregateToDrop { %type opt_ordinality opt_compact %type <*tree.Order> sortby %type index_elem index_elem_name_only partition_index_elem -%type table_ref numeric_table_ref func_table +%type table_ref numeric_table_ref func_table table_ref_options %type rowsfrom_list %type rowsfrom_item %type joined_table @@ -10880,22 +10880,11 @@ opt_index_flags: // // %SeeAlso: WEBDOCS/table-expressions.html table_ref: - numeric_table_ref opt_index_flags opt_ordinality opt_alias_clause +numeric_table_ref table_ref_options { /* SKIP DOC */ - $$.val = &tree.AliasedTableExpr{ - Expr: $1.tblExpr(), - IndexFlags: $2.indexFlags(), - Ordinality: $3.bool(), - As: $4.aliasClause(), - } - } -| numeric_table_ref as_of_clause - { - /* SKIP DOC */ - $$.val = &tree.AliasedTableExpr{ - Expr: $1.tblExpr(), - } + $$.val = $$ + $$.val.Expr = $1.tblExpr() } | relation_expr opt_index_flags opt_ordinality opt_alias_clause { @@ -10972,6 +10961,17 @@ table_ref: $$.val = &tree.AliasedTableExpr{Expr: &tree.StatementSource{ Statement: $2.stmt() }, Ordinality: $4.bool(), As: $5.aliasClause() } } +table_ref_options: +opt_index_flags opt_ordinality alias_clause + { + /* SKIP DOC */ + $$.val = &tree.AliasedTableExpr{ + IndexFlags: $1.indexFlags(), + Ordinality: $2.bool(), + As: $3.aliasClause(), + } + } + numeric_table_ref: '[' iconst64 opt_tableref_col_list alias_clause ']' { From ffa77cf31a054aa381478a7bc158b8d52dd92b52 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 15:24:51 -0700 Subject: [PATCH 04/20] Keeping going --- postgres/parser/parser/sql.y | 20 ++++++++++++++++++++ postgres/parser/sem/tree/select.go | 1 + 2 files changed, 21 insertions(+) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index cc22c21a07..a456441ae7 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10971,6 +10971,26 @@ opt_index_flags opt_ordinality alias_clause As: $3.aliasClause(), } } +| opt_index_flags opt_ordinality as_of_clause + { + /* SKIP DOC */ + $$.val = &tree.AliasedTableExpr{ + IndexFlags: $1.indexFlags(), + Ordinality: $2.bool(), + AsOf: &($3), + } + } +| opt_index_flags opt_ordinality alias_clause as_of_clause + { + /* SKIP DOC */ + $$.val = &tree.AliasedTableExpr{ + IndexFlags: $1.indexFlags(), + Ordinality: $2.bool(), + As: $3.aliasClause(), + AsOf: &($4), + } + } + numeric_table_ref: '[' iconst64 opt_tableref_col_list alias_clause ']' diff --git a/postgres/parser/sem/tree/select.go b/postgres/parser/sem/tree/select.go index 6de18baada..9291cbbf23 100644 --- a/postgres/parser/sem/tree/select.go +++ b/postgres/parser/sem/tree/select.go @@ -395,6 +395,7 @@ type AliasedTableExpr struct { Ordinality bool Lateral bool As AliasClause + AsOf *AsOfClause } // Format implements the NodeFormatter interface. From f4b94bef5e0fd638f52dbb863b263ceeed7ff72d Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 15:39:39 -0700 Subject: [PATCH 05/20] More inlining of rules --- postgres/parser/parser/sql.y | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index a456441ae7..77ff8e7ac0 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10886,15 +10886,11 @@ numeric_table_ref table_ref_options $$.val = $$ $$.val.Expr = $1.tblExpr() } -| relation_expr opt_index_flags opt_ordinality opt_alias_clause +| relation_expr table_ref_options { name := $1.unresolvedObjectName().ToTableName() - $$.val = &tree.AliasedTableExpr{ - Expr: &name, - IndexFlags: $2.indexFlags(), - Ordinality: $3.bool(), - As: $4.aliasClause(), - } + $$val = $$ + $$.val.Expr = &name } | select_with_parens opt_ordinality opt_alias_clause { @@ -10961,6 +10957,8 @@ numeric_table_ref table_ref_options $$.val = &tree.AliasedTableExpr{Expr: &tree.StatementSource{ Statement: $2.stmt() }, Ordinality: $4.bool(), As: $5.aliasClause() } } +// table_ref_options is the set of all possible combinations of AS OF and AS, since the optional versions of those +// rules clauses creates shift/reduce conflicts if they're combined in same rule table_ref_options: opt_index_flags opt_ordinality alias_clause { @@ -10980,18 +10978,18 @@ opt_index_flags opt_ordinality alias_clause AsOf: &($3), } } -| opt_index_flags opt_ordinality alias_clause as_of_clause +| opt_index_flags opt_ordinality as_of_clause AS table_alias_name opt_column_list { /* SKIP DOC */ + alias := tree.AliasClause{Alias: tree.Name($5), Cols: $6.nameList()} $$.val = &tree.AliasedTableExpr{ IndexFlags: $1.indexFlags(), Ordinality: $2.bool(), - As: $3.aliasClause(), - AsOf: &($4), + AsOf: &($3), + As: alias, } } - numeric_table_ref: '[' iconst64 opt_tableref_col_list alias_clause ']' { From 00e8ed417f58ab2fa02cda466f0da71f7e9f7548 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 15:49:52 -0700 Subject: [PATCH 06/20] Final rule causes conflict --- postgres/parser/parser/sql.y | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 77ff8e7ac0..13bc345f97 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10960,7 +10960,7 @@ numeric_table_ref table_ref_options // table_ref_options is the set of all possible combinations of AS OF and AS, since the optional versions of those // rules clauses creates shift/reduce conflicts if they're combined in same rule table_ref_options: -opt_index_flags opt_ordinality alias_clause + opt_index_flags opt_ordinality alias_clause { /* SKIP DOC */ $$.val = &tree.AliasedTableExpr{ @@ -10989,6 +10989,17 @@ opt_index_flags opt_ordinality alias_clause As: alias, } } +| opt_index_flags opt_ordinality as_of_clause table_alias_name opt_column_list + { + /* SKIP DOC */ + alias := tree.AliasClause{Alias: tree.Name($4), Cols: $5.nameList()} + $$.val = &tree.AliasedTableExpr{ + IndexFlags: $1.indexFlags(), + Ordinality: $2.bool(), + AsOf: &($3), + As: alias, + } + } numeric_table_ref: '[' iconst64 opt_tableref_col_list alias_clause ']' From 0bf8c88440f74ee14590c1c63e79b3fc41fd49e8 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 16:02:19 -0700 Subject: [PATCH 07/20] Fully working AS OF expansion --- postgres/parser/parser/sql.y | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 13bc345f97..7edc61a8bb 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -11122,16 +11122,43 @@ opt_alias_clause: $$.val = tree.AliasClause{} } +// as_of_clause is limited to constants and a few function expressions. The entire expressoin tree is too permissive, +// and causes many conflicts elsewhere in the rest of the grammar. +// These clauses are chosen carefully from the d_expr list. as_of_clause: - AS_LA OF SYSTEM TIME a_expr + AS_LA OF SYSTEM TIME SCONST { $$.val = tree.AsOfClause{Expr: $5.expr()} } -| AS_LA OF a_expr +| AS_LA OF SYSTEM typed_literal + { + $$.val = tree.AsOfClause{Expr: $5.expr()} + } +| AS_LA OF SYSTEM TIME func_expr_common_subexpr + { + $$.val = tree.AsOfClause{Expr: $5.expr()} + } +| AS_LA OF SYSTEM TIME func_application + { + $$.val = tree.AsOfClause{Expr: $5.expr()} + } +| AS_LA OF SCONST { $$.val = tree.AsOfClause{Expr: $3.expr()} } - +| AS_LA OF typed_literal + { + $$.val = tree.AsOfClause{Expr: $3.expr()} + } +| AS_LA OF func_expr_common_subexpr + { + $$.val = tree.AsOfClause{Expr: $3.expr()} + } +| AS_LA OF func_application + { + $$.val = tree.AsOfClause{Expr: $3.expr()} + } + opt_as_of_clause: as_of_clause | /* EMPTY */ From 272d04c58d416d4bb134f9a22b7d89a74ec2fe8b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 16:31:01 -0700 Subject: [PATCH 08/20] Fix errors --- postgres/parser/parser/sql.y | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 7edc61a8bb..542218250e 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10957,9 +10957,8 @@ numeric_table_ref table_ref_options $$.val = &tree.AliasedTableExpr{Expr: &tree.StatementSource{ Statement: $2.stmt() }, Ordinality: $4.bool(), As: $5.aliasClause() } } -// table_ref_options is the set of all possible combinations of AS OF and AS, since the optional versions of those -// rules clauses creates shift/reduce conflicts if they're combined in same rule -table_ref_options: + // table_ref_options is the set of all possible combinations of AS OF and alias, since the optional versions of those + // rules create shift/reduce conflicts if they're combined in same ruletable_ref_options: opt_index_flags opt_ordinality alias_clause { /* SKIP DOC */ @@ -11130,7 +11129,7 @@ as_of_clause: { $$.val = tree.AsOfClause{Expr: $5.expr()} } -| AS_LA OF SYSTEM typed_literal +| AS_LA OF SYSTEM TIME typed_literal { $$.val = tree.AsOfClause{Expr: $5.expr()} } From 42cc308c8ab6cb86f7d4f0219c2e57732fd47123 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 4 Oct 2024 16:34:53 -0700 Subject: [PATCH 09/20] Fix errors --- postgres/parser/parser/sql.y | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index 542218250e..dedfb6615c 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10883,13 +10883,14 @@ table_ref: numeric_table_ref table_ref_options { /* SKIP DOC */ - $$.val = $$ + $$ = $2 $$.val.Expr = $1.tblExpr() } | relation_expr table_ref_options { + /* SKIP DOC */ + $$ = $2 name := $1.unresolvedObjectName().ToTableName() - $$val = $$ $$.val.Expr = &name } | select_with_parens opt_ordinality opt_alias_clause @@ -10958,8 +10959,9 @@ numeric_table_ref table_ref_options } // table_ref_options is the set of all possible combinations of AS OF and alias, since the optional versions of those - // rules create shift/reduce conflicts if they're combined in same ruletable_ref_options: - opt_index_flags opt_ordinality alias_clause + // rules create shift/reduce conflicts if they're combined in same rule + table_ref_options: + opt_index_flags opt_ordinality alias_clause { /* SKIP DOC */ $$.val = &tree.AliasedTableExpr{ From bb46507f0536d7dcc82c142c49fac4945a9a154b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:08:40 -0700 Subject: [PATCH 10/20] Parser working for AsOf per table --- postgres/parser/parser/sql.y | 19 +++++++++++-------- server/ast/select_clause.go | 4 ---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index dedfb6615c..e911a80e54 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10884,14 +10884,14 @@ numeric_table_ref table_ref_options { /* SKIP DOC */ $$ = $2 - $$.val.Expr = $1.tblExpr() + $$.val.(*tree.AliasedTableExpr).Expr = $1.tblExpr() } | relation_expr table_ref_options { /* SKIP DOC */ $$ = $2 name := $1.unresolvedObjectName().ToTableName() - $$.val.Expr = &name + $$.val.(*tree.AliasedTableExpr).Expr = &name } | select_with_parens opt_ordinality opt_alias_clause { @@ -10960,7 +10960,7 @@ numeric_table_ref table_ref_options // table_ref_options is the set of all possible combinations of AS OF and alias, since the optional versions of those // rules create shift/reduce conflicts if they're combined in same rule - table_ref_options: +table_ref_options: opt_index_flags opt_ordinality alias_clause { /* SKIP DOC */ @@ -10973,20 +10973,22 @@ numeric_table_ref table_ref_options | opt_index_flags opt_ordinality as_of_clause { /* SKIP DOC */ + asOf := $3.asOfClause() $$.val = &tree.AliasedTableExpr{ IndexFlags: $1.indexFlags(), Ordinality: $2.bool(), - AsOf: &($3), + AsOf: &asOf, } } | opt_index_flags opt_ordinality as_of_clause AS table_alias_name opt_column_list { /* SKIP DOC */ alias := tree.AliasClause{Alias: tree.Name($5), Cols: $6.nameList()} + asOf := $3.asOfClause() $$.val = &tree.AliasedTableExpr{ IndexFlags: $1.indexFlags(), Ordinality: $2.bool(), - AsOf: &($3), + AsOf: &asOf, As: alias, } } @@ -10994,10 +10996,11 @@ numeric_table_ref table_ref_options { /* SKIP DOC */ alias := tree.AliasClause{Alias: tree.Name($4), Cols: $5.nameList()} + asOf := $3.asOfClause() $$.val = &tree.AliasedTableExpr{ IndexFlags: $1.indexFlags(), Ordinality: $2.bool(), - AsOf: &($3), + AsOf: &asOf, As: alias, } } @@ -11129,7 +11132,7 @@ opt_alias_clause: as_of_clause: AS_LA OF SYSTEM TIME SCONST { - $$.val = tree.AsOfClause{Expr: $5.expr()} + $$.val = tree.AsOfClause{Expr: tree.NewStrVal($5)} } | AS_LA OF SYSTEM TIME typed_literal { @@ -11145,7 +11148,7 @@ as_of_clause: } | AS_LA OF SCONST { - $$.val = tree.AsOfClause{Expr: $3.expr()} + $$.val = tree.AsOfClause{Expr: tree.NewStrVal($3)} } | AS_LA OF typed_literal { diff --git a/server/ast/select_clause.go b/server/ast/select_clause.go index 99d81d4d49..f267325732 100644 --- a/server/ast/select_clause.go +++ b/server/ast/select_clause.go @@ -38,10 +38,6 @@ func nodeSelectClause(node *tree.SelectClause) (*vitess.Select, error) { // pass along a join node. // TODO: handle more than two tables, also make this more robust with handling more node types if len(node.From.Tables) == 2 && node.Where != nil { - // We don't yet handle AS OF for rewrites - if node.From.AsOf.Expr != nil { - goto PostJoinRewrite - } tableNames := make(map[tree.TableName]int) tableAliases := make(map[tree.TableName]int) // First we need to get the table names and aliases, since they'll be referenced by the filters From 78717e6ad90bc83ed5789d7f091f6731f1722e05 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:22:35 -0700 Subject: [PATCH 11/20] Targeted AS OF tests --- testing/go/as_of_test.go | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 testing/go/as_of_test.go diff --git a/testing/go/as_of_test.go b/testing/go/as_of_test.go new file mode 100755 index 0000000000..2851c76fdf --- /dev/null +++ b/testing/go/as_of_test.go @@ -0,0 +1,67 @@ +// 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 TestAsOf(t *testing.T) { + RunScripts(t, []ScriptTest{ + { + Name: "Single table", + SetUpScript: []string{ + `CREATE TABLE test (a INT)`, + `INSERT INTO test VALUES (1)`, + `CALL DOLT_COMMIT('-Am', 'new table')`, + `INSERT INTO test VALUES (2)`, + `CALL DOLT_COMMIT('-am', 'new row')`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM test AS OF 'HEAD^'`, + Expected: []sql.Row{ + {1}, + }, + }, + }, + }, + { + Name: "Join", + SetUpScript: []string{ + `CREATE TABLE test (a INT)`, + `INSERT INTO test VALUES (1)`, + `CALL DOLT_COMMIT('-Am', 'new table')`, + `INSERT INTO test VALUES (2)`, + `CALL DOLT_COMMIT('-am', 'new row')`, + `CREATE TABLE test2 (b INT)`, + `INSERT INTO test2 VALUES (1)`, + `CALL DOLT_COMMIT('-Am', 'new table')`, + `INSERT INTO test2 VALUES (2)`, + `CALL DOLT_COMMIT('-am', 'new row')`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM test ASOF 'HEAD^3' join test2 AS OF 'HEAD^'`, + Expected: []sql.Row{ + {1}, + }, + }, + }, + }, + }) +} From c6af16c9014b3cb8ec381b7745cc18de9618e201 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:30:29 -0700 Subject: [PATCH 12/20] AS OF per table working --- server/ast/aliased_table_expr.go | 16 +++++++++++++++- server/ast/from.go | 19 ------------------- testing/go/as_of_test.go | 10 ++++++++-- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/server/ast/aliased_table_expr.go b/server/ast/aliased_table_expr.go index c1cba50142..e084a1c00f 100644 --- a/server/ast/aliased_table_expr.go +++ b/server/ast/aliased_table_expr.go @@ -31,6 +31,7 @@ func nodeAliasedTableExpr(node *tree.AliasedTableExpr) (*vitess.AliasedTableExpr return nil, fmt.Errorf("index flags are not yet supported") } var aliasExpr vitess.SimpleTableExpr + switch expr := node.Expr.(type) { case *tree.TableName: var err error @@ -94,10 +95,23 @@ func nodeAliasedTableExpr(node *tree.AliasedTableExpr) (*vitess.AliasedTableExpr return nil, fmt.Errorf("unhandled table expression: `%T`", expr) } alias := string(node.As.Alias) + + var asOf *vitess.AsOf + if node.AsOf != nil { + asOfExpr, err := nodeExpr(node.AsOf.Expr) + if err != nil { + return nil, err + } + // TODO: other forms of AS OF (not just point in time) + asOf = &vitess.AsOf{ + Time: asOfExpr, + } + } + return &vitess.AliasedTableExpr{ Expr: aliasExpr, As: vitess.NewTableIdent(alias), - AsOf: nil, + AsOf: asOf, Lateral: node.Lateral, }, nil } diff --git a/server/ast/from.go b/server/ast/from.go index a652010780..31b1fbf8dc 100644 --- a/server/ast/from.go +++ b/server/ast/from.go @@ -15,8 +15,6 @@ package ast import ( - "fmt" - vitess "github.com/dolthub/vitess/go/vt/sqlparser" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" @@ -27,26 +25,9 @@ func nodeFrom(node tree.From) (vitess.TableExprs, error) { if len(node.Tables) == 0 { return nil, nil } - asOfExpr, err := nodeExpr(node.AsOf.Expr) - if err != nil { - return nil, err - } tableExprs, err := nodeTableExprs(node.Tables) if err != nil { return nil, err } - if asOfExpr != nil { - //TODO: determine if this will always be Time - asOf := &vitess.AsOf{ - Time: asOfExpr, - } - for _, tableExpr := range tableExprs { - if aliasedTableExpr, ok := tableExpr.(*vitess.AliasedTableExpr); ok { - aliasedTableExpr.AsOf = asOf - } else { - return nil, fmt.Errorf("this particular usage of AS OF is not yet supported") - } - } - } return tableExprs, err } diff --git a/testing/go/as_of_test.go b/testing/go/as_of_test.go index 2851c76fdf..c349fa7d33 100755 --- a/testing/go/as_of_test.go +++ b/testing/go/as_of_test.go @@ -56,9 +56,15 @@ func TestAsOf(t *testing.T) { }, Assertions: []ScriptTestAssertion{ { - Query: `SELECT * FROM test ASOF 'HEAD^3' join test2 AS OF 'HEAD^'`, + Query: `SELECT * FROM test AS OF 'HEAD~3' t1 join test2 AS OF 'HEAD~' t2 on t1.a = t2.b`, Expected: []sql.Row{ - {1}, + {1, 1}, + }, + }, + { + Query: `SELECT * FROM test AS OF 'HEAD~3' t1 join test2 AS t2 on t1.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, }, }, }, From 941e95625a91737fbdcc8eedf9ee45ff1c4d2663 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:47:00 -0700 Subject: [PATCH 13/20] More tests --- testing/go/as_of_test.go | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/testing/go/as_of_test.go b/testing/go/as_of_test.go index c349fa7d33..f47010d5e6 100755 --- a/testing/go/as_of_test.go +++ b/testing/go/as_of_test.go @@ -67,6 +67,53 @@ func TestAsOf(t *testing.T) { {1, 1}, }, }, + { + Query: `SELECT * FROM test t1 join test2 AS OF 'HEAD~' AS t2 on t1.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, + }, + }, + }, + }, + { + Name: "Syntax variations", // There are no unit tests for the parser, so test all variations of the AS OF syntax + SetUpScript: []string{ + `CREATE TABLE test (a INT)`, + `INSERT INTO test VALUES (1)`, + `CALL DOLT_COMMIT('-Am', 'new table')`, + `INSERT INTO test VALUES (2)`, + `CALL DOLT_COMMIT('-am', 'new row')`, + `CREATE TABLE test2 (b INT)`, + `INSERT INTO test2 VALUES (1)`, + `CALL DOLT_COMMIT('-Am', 'new table')`, + `INSERT INTO test2 VALUES (2)`, + `CALL DOLT_COMMIT('-am', 'new row')`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT * FROM test AS OF 'HEAD~3' AS t1 join test2 AS OF 'HEAD' AS t2 on t1.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: `SELECT * FROM test AS OF 'HEAD~3' t1 join test2 AS OF 'HEAD' t2 on t1.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: `SELECT * FROM test AS t1 join test2 AS OF 'HEAD~' t2 on t1.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: `SELECT * FROM test AS OF SYSTEM TIME 'HEAD~3' join test2 AS t2 on test.a = t2.b`, + Expected: []sql.Row{ + {1, 1}, + }, + }, }, }, }) From 4d6b30e4c4d2525e4a2555659356873a25ddf4eb Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:53:31 -0700 Subject: [PATCH 14/20] Added missing string support for new syntax --- postgres/parser/sem/tree/pretty.go | 9 +++++++++ postgres/parser/sem/tree/select.go | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/postgres/parser/sem/tree/pretty.go b/postgres/parser/sem/tree/pretty.go index dcf87b8d34..5559344879 100644 --- a/postgres/parser/sem/tree/pretty.go +++ b/postgres/parser/sem/tree/pretty.go @@ -682,6 +682,15 @@ func (node *AliasedTableExpr) doc(p *PrettyCfg) pretty.Doc { p.keywordWithText(" ", "WITH ORDINALITY", ""), ) } + if node.AsOf != nil { + d = p.nestUnder( + d, + pretty.Concat( + p.keywordWithText("", "AS OF SYSTEM TIME", " "), + p.Doc(node.AsOf), + ), + ) + } if node.As.Alias != "" { d = p.nestUnder( d, diff --git a/postgres/parser/sem/tree/select.go b/postgres/parser/sem/tree/select.go index 9291cbbf23..22653ce49c 100644 --- a/postgres/parser/sem/tree/select.go +++ b/postgres/parser/sem/tree/select.go @@ -410,6 +410,10 @@ func (node *AliasedTableExpr) Format(ctx *FmtCtx) { if node.Ordinality { ctx.WriteString(" WITH ORDINALITY") } + if node.AsOf != nil { + ctx.WriteString(" AS OF SYSTEM TIME ") + ctx.FormatNode(node.AsOf) + } if node.As.Alias != "" { ctx.WriteString(" AS ") ctx.FormatNode(&node.As) From d21c0ebfa75969563e372d5049abcde0a68a6b0f Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 11:54:34 -0700 Subject: [PATCH 15/20] Formatting --- postgres/parser/sem/tree/walk.go | 2 +- server/ast/aliased_table_expr.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/postgres/parser/sem/tree/walk.go b/postgres/parser/sem/tree/walk.go index d5bfbd9ebc..cacb18ea2b 100644 --- a/postgres/parser/sem/tree/walk.go +++ b/postgres/parser/sem/tree/walk.go @@ -1205,7 +1205,7 @@ func (stmt *SelectClause) walkStmt(v Visitor) Statement { ret.Exprs[i].Expr = e } } - + if stmt.Where != nil { e, changed := WalkExpr(v, stmt.Where.Expr) if changed { diff --git a/server/ast/aliased_table_expr.go b/server/ast/aliased_table_expr.go index e084a1c00f..c88c879648 100644 --- a/server/ast/aliased_table_expr.go +++ b/server/ast/aliased_table_expr.go @@ -31,7 +31,7 @@ func nodeAliasedTableExpr(node *tree.AliasedTableExpr) (*vitess.AliasedTableExpr return nil, fmt.Errorf("index flags are not yet supported") } var aliasExpr vitess.SimpleTableExpr - + switch expr := node.Expr.(type) { case *tree.TableName: var err error @@ -107,7 +107,7 @@ func nodeAliasedTableExpr(node *tree.AliasedTableExpr) (*vitess.AliasedTableExpr Time: asOfExpr, } } - + return &vitess.AliasedTableExpr{ Expr: aliasExpr, As: vitess.NewTableIdent(alias), From de23102911281feae4a48f22ecb93f659bdfbcef Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 14:03:12 -0700 Subject: [PATCH 16/20] Reskip test --- testing/go/enginetest/doltgres_engine_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/go/enginetest/doltgres_engine_test.go b/testing/go/enginetest/doltgres_engine_test.go index c0e5853b29..f34d11b2d3 100755 --- a/testing/go/enginetest/doltgres_engine_test.go +++ b/testing/go/enginetest/doltgres_engine_test.go @@ -1147,6 +1147,7 @@ func TestDoltRebasePrepared(t *testing.T) { } func TestDoltRevert(t *testing.T) { + t.Skip() h := newDoltgresServerHarness(t) denginetest.RunDoltRevertTests(t, h) } From a6adb5b4670e660dca1a7aa46e03bbba647fbb3c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 15:06:07 -0700 Subject: [PATCH 17/20] Fixed parser bug for no table alias --- postgres/parser/parser/sql.y | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/postgres/parser/parser/sql.y b/postgres/parser/parser/sql.y index e911a80e54..a7bd154ac8 100644 --- a/postgres/parser/parser/sql.y +++ b/postgres/parser/parser/sql.y @@ -10961,7 +10961,15 @@ numeric_table_ref table_ref_options // table_ref_options is the set of all possible combinations of AS OF and alias, since the optional versions of those // rules create shift/reduce conflicts if they're combined in same rule table_ref_options: - opt_index_flags opt_ordinality alias_clause + opt_index_flags opt_ordinality + { + /* SKIP DOC */ + $$.val = &tree.AliasedTableExpr{ + IndexFlags: $1.indexFlags(), + Ordinality: $2.bool(), + } + } +| opt_index_flags opt_ordinality alias_clause { /* SKIP DOC */ $$.val = &tree.AliasedTableExpr{ From bbdd7039565e88e6b94ecea2b299405ed5d89690 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 7 Oct 2024 18:09:04 -0700 Subject: [PATCH 18/20] Unskip most dolt_revert calls, preliminary suppport for alter table statements --- testing/go/enginetest/doltgres_engine_test.go | 80 ++--------------- testing/go/enginetest/query_converter_test.go | 88 +++++++++++++++++++ 2 files changed, 97 insertions(+), 71 deletions(-) diff --git a/testing/go/enginetest/doltgres_engine_test.go b/testing/go/enginetest/doltgres_engine_test.go index f34d11b2d3..54bd289074 100755 --- a/testing/go/enginetest/doltgres_engine_test.go +++ b/testing/go/enginetest/doltgres_engine_test.go @@ -148,79 +148,15 @@ func TestSingleScript(t *testing.T) { var scripts = []queries.ScriptTest{ { - Name: "primary key table: basic cases", + Name: "dolt_revert() detects not null violation (issue #4527)", SetUpScript: []string{ - "create table t1 (n int primary key, de varchar(20));", - "call dolt_add('.')", - "insert into t1 values (1, 'Eins'), (2, 'Zwei'), (3, 'Drei');", - "call dolt_commit('-am', 'inserting into t1', '--date', '2022-08-06T12:00:01');", - "SET @Commit1 = (select hashof('HEAD'));", - - "alter table t1 add column fr varchar(20);", - "insert into t1 values (4, 'Vier', 'Quatre');", - "call dolt_commit('-am', 'adding column and inserting data in t1', '--date', '2022-08-06T12:00:02');", - "SET @Commit2 = (select hashof('HEAD'));", - - "update t1 set fr='Un' where n=1;", - "update t1 set fr='Deux' where n=2;", - "call dolt_commit('-am', 'updating data in t1', '--date', '2022-08-06T12:00:03');", - "SET @Commit3 = (select hashof('HEAD'));", - - "update t1 set de=concat(de, ', meine herren') where n>1;", - "call dolt_commit('-am', 'be polite when you address a gentleman', '--date', '2022-08-06T12:00:04');", - "SET @Commit4 = (select hashof('HEAD'));", - - "delete from t1 where n=2;", - "call dolt_commit('-am', 'we don''t need the number 2', '--date', '2022-08-06T12:00:05');", - "SET @Commit5 = (select hashof('HEAD'));", + "create table test2 (pk int primary key, c0 int)", + "alter table test2 modify c0 int not null", }, Assertions: []queries.ScriptTestAssertion{ { - Query: "select count(*) from Dolt_History_t1;", - Expected: []sql.Row{{18}}, - }, - { - Query: "select n, de, fr from dolt_history_T1 where commit_hash = @Commit1;", - Expected: []sql.Row{{1, "Eins", nil}, {2, "Zwei", nil}, {3, "Drei", nil}}, - }, - { - Query: "select de, fr from dolt_history_T1 where commit_hash = @Commit1;", - Expected: []sql.Row{{"Eins", nil}, {"Zwei", nil}, {"Drei", nil}}, - }, - { - Query: "select n, de, fr from dolt_history_T1 where commit_hash = @Commit2;", - Expected: []sql.Row{{1, "Eins", nil}, {2, "Zwei", nil}, {3, "Drei", nil}, {4, "Vier", "Quatre"}}, - }, - { - Query: "select n, de, fr from dolt_history_T1 where commit_hash = @Commit3;", - Expected: []sql.Row{{1, "Eins", "Un"}, {2, "Zwei", "Deux"}, {3, "Drei", nil}, {4, "Vier", "Quatre"}}, - }, - { - Query: "select n, de, fr from dolt_history_T1 where commit_hash = @Commit4;", - Expected: []sql.Row{ - {1, "Eins", "Un"}, - {2, "Zwei, meine herren", "Deux"}, - {3, "Drei, meine herren", nil}, - {4, "Vier, meine herren", "Quatre"}, - }, - }, - { - Query: "select n, de, fr from dolt_history_T1 where commit_hash = @Commit5;", - Expected: []sql.Row{ - {1, "Eins", "Un"}, - {3, "Drei, meine herren", nil}, - {4, "Vier, meine herren", "Quatre"}, - }, - }, - { - Query: "select de, fr, commit_hash=@commit1, commit_hash=@commit2, commit_hash=@commit3, commit_hash=@commit4" + - " from dolt_history_T1 where n=2 order by commit_date", - Expected: []sql.Row{ - {"Zwei", nil, true, false, false, false}, - {"Zwei", nil, false, true, false, false}, - {"Zwei", "Deux", false, false, true, false}, - {"Zwei, meine herren", "Deux", false, false, false, true}, - }, + Query: "call dolt_revert('head~1');", + ExpectedErrStr: "revert currently does not handle constraint violations", }, }, }, @@ -1147,8 +1083,10 @@ func TestDoltRebasePrepared(t *testing.T) { } func TestDoltRevert(t *testing.T) { - t.Skip() - h := newDoltgresServerHarness(t) + h := newDoltgresServerHarness(t).WithSkippedQueries([]string{ + "dolt_revert() respects dolt_ignore", // ERROR: INSERT: non-Doltgres type found in destination: text + "dolt_revert() automatically resolves some conflicts", // panic: interface conversion: sql.Type is types.VarCharType, not types.StringType + }) denginetest.RunDoltRevertTests(t, h) } diff --git a/testing/go/enginetest/query_converter_test.go b/testing/go/enginetest/query_converter_test.go index 8825c85976..08a51b667b 100755 --- a/testing/go/enginetest/query_converter_test.go +++ b/testing/go/enginetest/query_converter_test.go @@ -42,11 +42,99 @@ func transformAST(query string) ([]string, bool) { return transformSet(stmt) case *sqlparser.Select: return transformSelect(stmt) + case *sqlparser.AlterTable: + return transformAlterTable(stmt) } return nil, false } +func transformAlterTable(stmt *sqlparser.AlterTable) ([]string, bool) { + var outputStmts []string + for _, statement := range stmt.Statements { + converted, ok := convertDdlStatement(statement) + if !ok { + return nil, false + } + outputStmts = append(outputStmts, converted...) + } + return outputStmts, true +} + +func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { + switch statement.Action { + case "alter": + switch statement.ColumnAction { + case "modify": + if len(statement.TableSpec.Columns) != 1 { + return nil, false + } + + stmts := make([]string, 0) + + col := statement.TableSpec.Columns[0] + tableName, err := tree.NewUnresolvedObjectName(1, [3]string{statement.Table.Name.String(), "", ""}, 0) + if err != nil { + panic(err) + } + + newType := convertTypeDef(col.Type) + alter := tree.AlterTable{ + Table: tableName, + Cmds: []tree.AlterTableCmd{ + &tree.AlterTableAlterColumnType{ + Column: tree.Name(col.Name.String()), + ToType: newType, + }, + }, + } + + ctx := formatNodeWithUnqualifiedTableNames(&alter) + stmts = append(stmts, ctx.String()) + + // constraints + if col.Type.NotNull { + alter.Cmds = []tree.AlterTableCmd{ + &tree.AlterTableSetNotNull{ + Column: tree.Name(col.Name.String()), + }, + } + ctx = formatNodeWithUnqualifiedTableNames(&alter) + stmts = append(stmts, ctx.String()) + } else { + alter.Cmds = []tree.AlterTableCmd{ + &tree.AlterTableDropNotNull{ + Column: tree.Name(col.Name.String()), + }, + } + ctx = formatNodeWithUnqualifiedTableNames(&alter) + stmts = append(stmts, ctx.String()) + } + + // rename + if statement.Column.String() != col.Name.String() { + alter.Cmds = []tree.AlterTableCmd{ + &tree.AlterTableRenameColumn{ + Column: tree.Name(statement.Column.String()), + NewName: tree.Name(col.Name.String()), + }, + } + ctx = formatNodeWithUnqualifiedTableNames(&alter) + stmts = append(stmts, ctx.String()) + } + + return stmts, true + default: + return nil, false + } + default: + return nil, false + } + + return nil, false +} + + // transformSelect converts a MySQL SELECT statement to a postgres-compatible SELECT statement. // This is a very broad surface area, so we do this very selectively func transformSelect(stmt *sqlparser.Select) ([]string, bool) { From 98a6650bf9eaa896b653c5113b22e298a1ca9165 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 8 Oct 2024 11:21:22 -0700 Subject: [PATCH 19/20] Formatting --- testing/go/enginetest/doltgres_engine_test.go | 2 +- testing/go/enginetest/query_converter_test.go | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/testing/go/enginetest/doltgres_engine_test.go b/testing/go/enginetest/doltgres_engine_test.go index 54bd289074..2169e4934b 100755 --- a/testing/go/enginetest/doltgres_engine_test.go +++ b/testing/go/enginetest/doltgres_engine_test.go @@ -1084,7 +1084,7 @@ func TestDoltRebasePrepared(t *testing.T) { func TestDoltRevert(t *testing.T) { h := newDoltgresServerHarness(t).WithSkippedQueries([]string{ - "dolt_revert() respects dolt_ignore", // ERROR: INSERT: non-Doltgres type found in destination: text + "dolt_revert() respects dolt_ignore", // ERROR: INSERT: non-Doltgres type found in destination: text "dolt_revert() automatically resolves some conflicts", // panic: interface conversion: sql.Type is types.VarCharType, not types.StringType }) denginetest.RunDoltRevertTests(t, h) diff --git a/testing/go/enginetest/query_converter_test.go b/testing/go/enginetest/query_converter_test.go index 08a51b667b..e40bc008b1 100755 --- a/testing/go/enginetest/query_converter_test.go +++ b/testing/go/enginetest/query_converter_test.go @@ -50,7 +50,7 @@ func transformAST(query string) ([]string, bool) { } func transformAlterTable(stmt *sqlparser.AlterTable) ([]string, bool) { - var outputStmts []string + var outputStmts []string for _, statement := range stmt.Statements { converted, ok := convertDdlStatement(statement) if !ok { @@ -69,9 +69,9 @@ func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { if len(statement.TableSpec.Columns) != 1 { return nil, false } - + stmts := make([]string, 0) - + col := statement.TableSpec.Columns[0] tableName, err := tree.NewUnresolvedObjectName(1, [3]string{statement.Table.Name.String(), "", ""}, 0) if err != nil { @@ -83,8 +83,8 @@ func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { Table: tableName, Cmds: []tree.AlterTableCmd{ &tree.AlterTableAlterColumnType{ - Column: tree.Name(col.Name.String()), - ToType: newType, + Column: tree.Name(col.Name.String()), + ToType: newType, }, }, } @@ -122,7 +122,7 @@ func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { ctx = formatNodeWithUnqualifiedTableNames(&alter) stmts = append(stmts, ctx.String()) } - + return stmts, true default: return nil, false @@ -130,11 +130,10 @@ func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { default: return nil, false } - + return nil, false } - // transformSelect converts a MySQL SELECT statement to a postgres-compatible SELECT statement. // This is a very broad surface area, so we do this very selectively func transformSelect(stmt *sqlparser.Select) ([]string, bool) { From 44379321645f70e43b7db0f8dbc49d1ac2dd3d99 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 8 Oct 2024 11:41:19 -0700 Subject: [PATCH 20/20] Linting --- testing/go/enginetest/query_converter_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/testing/go/enginetest/query_converter_test.go b/testing/go/enginetest/query_converter_test.go index e40bc008b1..7c20cb1291 100755 --- a/testing/go/enginetest/query_converter_test.go +++ b/testing/go/enginetest/query_converter_test.go @@ -130,8 +130,6 @@ func convertDdlStatement(statement *sqlparser.DDL) ([]string, bool) { default: return nil, false } - - return nil, false } // transformSelect converts a MySQL SELECT statement to a postgres-compatible SELECT statement.