Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented support for various expressions needed by sqllogictest #60

Merged
merged 15 commits into from
Dec 1, 2023
12 changes: 9 additions & 3 deletions postgres/messages/row_description.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ func VitessFieldToDataTypeObjectID(field *query.Field) (int32, error) {
return 1114, nil
case query.Type_DATE:
return 1082, nil
case query.Type_NULL_TYPE:
return 25, nil // NULL is treated as TEXT on the wire
default:
return 0, fmt.Errorf("unsupported type returned from engine")
return 0, fmt.Errorf("unsupported type returned from engine: %s", field.Type)
}
}

Expand Down Expand Up @@ -210,8 +212,10 @@ func VitessFieldToDataTypeSize(field *query.Field) (int16, error) {
return 8, nil
case query.Type_DATE:
return 4, nil
case query.Type_NULL_TYPE:
return -1, nil // NULL is treated as TEXT on the wire
default:
return 0, fmt.Errorf("unsupported type returned from engine")
return 0, fmt.Errorf("unsupported type returned from engine: %s", field.Type)
}
}

Expand Down Expand Up @@ -255,7 +259,9 @@ func VitessFieldToDataTypeModifier(field *query.Field) (int32, error) {
return -1, nil
case query.Type_DATE:
return -1, nil
case query.Type_NULL_TYPE:
return -1, nil // NULL is treated as TEXT on the wire
default:
return 0, fmt.Errorf("unsupported type returned from engine")
return 0, fmt.Errorf("unsupported type returned from engine: %s", field.Type)
}
}
26 changes: 23 additions & 3 deletions server/ast/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,15 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
Type: convertType,
}, nil
case *tree.CoalesceExpr:
return nil, fmt.Errorf("COALESCE is not yet supported")
exprs, err := nodeExprsToSelectExprs(node.Exprs)
if err != nil {
return nil, err
}

return &vitess.FuncExpr{
Name: vitess.NewColIdent("COALESCE"),
Exprs: exprs,
}, nil
case *tree.CollateExpr:
return nil, fmt.Errorf("collations are not yet supported")
case *tree.ColumnAccessExpr:
Expand Down Expand Up @@ -400,8 +408,20 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
Expr: expr,
}, nil
case *tree.NullIfExpr:
//TODO: probably should be the IF function: IF(Expr1 == Expr2, NULL, Expr1)
return nil, fmt.Errorf("NULLIF is not yet supported")
expr1, err := nodeExprToSelectExpr(node.Expr1)
if err != nil {
return nil, err
}

expr2, err := nodeExprToSelectExpr(node.Expr2)
if err != nil {
return nil, err
}

return &vitess.FuncExpr{
Name: vitess.NewColIdent("NULLIF"),
Exprs: vitess.SelectExprs{expr1, expr2},
}, nil
case tree.NullLiteral:
return &vitess.NullVal{}, nil
case *tree.NumVal:
Expand Down
6 changes: 3 additions & 3 deletions server/ast/func_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ func nodeFuncExpr(node *tree.FuncExpr) (*vitess.FuncExpr, error) {
}
var distinct bool
switch node.Type {
case 0:
case 0, tree.AllFuncType:
distinct = false
case tree.DistinctFuncType:
distinct = true
case tree.AllFuncType:
return nil, fmt.Errorf("function spec is not yet supported")
default:
return nil, fmt.Errorf("unknown function spec type %d", node.Type)
zachmu marked this conversation as resolved.
Show resolved Hide resolved
}
windowDef, err := nodeWindowDef(node.WindowDef)
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions server/ast/table_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ func nodeTableExpr(node tree.TableExpr) (vitess.TableExpr, error) {
for i := range treeCondition.Cols {
condition.Using[i] = vitess.NewColIdent(string(treeCondition.Cols[i]))
}
case nil:
// cross join (no join condition)
default:
return nil, fmt.Errorf("unknown JOIN condition: `%T`", treeCondition)
}
Expand All @@ -70,10 +72,7 @@ func nodeTableExpr(node tree.TableExpr) (vitess.TableExpr, error) {
} else {
joinType = vitess.RightJoinStr
}
case tree.AstCross:
// GMS doesn't have any support for CROSS joins, as MySQL doesn't actually implement them
return nil, fmt.Errorf("CROSS joins are not yet supported")
case tree.AstInner:
case tree.AstCross, tree.AstInner:
zachmu marked this conversation as resolved.
Show resolved Hide resolved
joinType = vitess.JoinStr
case "":
if condition.On == nil && len(condition.Using) == 0 {
Expand Down
134 changes: 134 additions & 0 deletions testing/go/regression_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2023 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 TestRegressions(t *testing.T) {
RunScripts(t, []ScriptTest{
// {
// Name: "nullif",
// SetUpScript: []string{},
// Assertions: []ScriptTestAssertion{
// {
// Query: "select nullif(1, 1);",
// Expected: []sql.Row{{nil}},
// },
// {
// Query: "select nullif('', null);",
// Expected: []sql.Row{{""}},
// },
// {
// Query: "select nullif(10, 'a');",
// Expected: []sql.Row{{10}},
// },
// },
// },
// {
// Name: "coalesce",
// SetUpScript: []string{},
// Assertions: []ScriptTestAssertion{
// {
// Query: "select coalesce(null + 5, 100);",
// Expected: []sql.Row{{100.0}}, // TODO: this should be an integer
// },
// {
// Query: "select coalesce(null, null, 'abc');",
// Expected: []sql.Row{{"abc"}},
// },
// {
// Query: "select coalesce(null, null);",
// Expected: []sql.Row{{nil}},
// },
// },
// },
{
Name: "case / when",
SetUpScript: []string{},
Assertions: []ScriptTestAssertion{
{
Query: "SELECT\n" +
" CASE\n" +
" WHEN 1 = 1 THEN 'One is equal to One'\n" +
" ELSE 'One is not equal to One'\n" +
" END AS result;",
Expected: []sql.Row{{"One is equal to One"}},
},
{
Query: "SELECT\n" +
" CASE\n" +
" WHEN NULL IS NULL THEN 'NULL is NULL'\n" +
" ELSE 'NULL is not NULL'\n" +
" END AS result;",
Expected: []sql.Row{{"NULL is NULL"}},
},
},
},
{
Name: "ALL / DISTINCT in functions",
SetUpScript: []string{
"create table t1 (pk int);",
"insert into t1 values (1), (2), (3), (1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "select all count(*) from t1;",
Expected: []sql.Row{{4}},
},
{
Query: "select all count(distinct pk) from t1;",
Expected: []sql.Row{{3}},
},
{
Query: "select all count(all pk) from t1;",
Expected: []sql.Row{{4}},
},
},
},
{
Name: "cross joins",
SetUpScript: []string{
"create table t1 (pk1 int);",
"create table t2 (pk2 int);",
"insert into t1 values (1), (2);",
"insert into t2 values (3), (4);",
},
Assertions: []ScriptTestAssertion{
{
Query: "select * from t1 cross join t2 order by pk1, pk2;",
Expected: []sql.Row{
{1, 3},
{1, 4},
{2, 3},
{2, 4},
},
},
{
Query: "select * from t1, t2 order by pk1, pk2;",
Expected: []sql.Row{
{1, 3},
{1, 4},
{2, 3},
{2, 4},
},
},
},
},
})
}
4 changes: 4 additions & 0 deletions testing/logictest/harness/doltgres_harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ func columns(rows *sql.Rows) (string, []interface{}, error) {
colVal := sql.NullInt64{}
columns = append(columns, &colVal)
sb.WriteString("I")
case "UNKNOWN": // used for NULL values
colVal := sql.NullString{}
columns = append(columns, &colVal)
sb.WriteString("I") // is this right?
default:
return "", nil, fmt.Errorf("Unhandled type %s", columnType.DatabaseTypeName())
}
Expand Down