Skip to content

Commit

Permalink
Merge pull request #60 from dolthub/zachmu/exprs
Browse files Browse the repository at this point in the history
Implemented support for various expressions needed by sqllogictest
  • Loading branch information
zachmu authored Dec 1, 2023
2 parents 06567ef + 7b284d5 commit 39f8360
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 13 deletions.
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)
}
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:
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

0 comments on commit 39f8360

Please sign in to comment.