From 58a94ad8102f33ad243acbcf6f173bd46effbc73 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 27 Nov 2023 17:45:00 -0800 Subject: [PATCH 1/5] Bug fix for aggregate funcs (COUNT(*) exprs) and NUMERIC type handling --- server/ast/func_expr.go | 4 ++-- testing/logictest/harness/doltgres_harness.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/ast/func_expr.go b/server/ast/func_expr.go index e86af20759..5064cb1d7e 100644 --- a/server/ast/func_expr.go +++ b/server/ast/func_expr.go @@ -30,8 +30,8 @@ func nodeFuncExpr(node *tree.FuncExpr) (*vitess.FuncExpr, error) { if node.Filter != nil { return nil, fmt.Errorf("function filters are not yet supported") } - if node.AggType != tree.GeneralAgg { - return nil, fmt.Errorf("function aggregation is not yet supported") + if node.AggType == tree.OrderedSetAgg { + return nil, fmt.Errorf("WITHIN GROUP is not yet supported") } if len(node.OrderBy) > 0 { return nil, fmt.Errorf("function ORDER BY is not yet supported") diff --git a/testing/logictest/harness/doltgres_harness.go b/testing/logictest/harness/doltgres_harness.go index 3cc85942c8..9f0fcc1646 100755 --- a/testing/logictest/harness/doltgres_harness.go +++ b/testing/logictest/harness/doltgres_harness.go @@ -230,7 +230,7 @@ func columns(rows *sql.Rows) (string, []interface{}, error) { colVal := sql.NullString{} columns = append(columns, &colVal) sb.WriteString("T") - case "DECIMAL", "DOUBLE", "FLOAT": + case "DECIMAL", "DOUBLE", "FLOAT", "FLOAT8", "NUMERIC": colVal := sql.NullFloat64{} columns = append(columns, &colVal) sb.WriteString("R") From a9ca9e6ace7198396738acd1245022a496fd6347 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 27 Nov 2023 18:15:14 -0800 Subject: [PATCH 2/5] Support CAST --- server/ast/expr.go | 61 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/server/ast/expr.go b/server/ast/expr.go index b534547ab4..5148468387 100644 --- a/server/ast/expr.go +++ b/server/ast/expr.go @@ -17,7 +17,9 @@ package ast import ( "fmt" "go/constant" + "strconv" + "github.com/dolthub/doltgresql/postgres/parser/types" vitess "github.com/dolthub/vitess/go/vt/sqlparser" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" @@ -183,12 +185,21 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { Else: else_, }, nil case *tree.CastExpr: - //TODO: finish the implementation + expr, err := nodeExpr(node.Expr) + if err != nil { + return nil, err + } + + convertType, err := typeConvertType(node.Type) + if err != nil { + return nil, err + } + return &vitess.ConvertExpr{ - Name: "", - Expr: nil, - Type: nil, - }, fmt.Errorf("CAST is not yet supported") + Name: "CAST", + Expr: expr, + Type: convertType, + }, nil case *tree.CoalesceExpr: return nil, fmt.Errorf("COALESCE is not yet supported") case *tree.CollateExpr: @@ -532,3 +543,43 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { return nil, fmt.Errorf("unknown expression: `%T`", node) } } + +func typeConvertType(typ tree.ResolvableTypeReference) (*vitess.ConvertType, error) { + if typ == nil { + return nil, nil + } + + var columnTypeName string + var columnTypeLength *vitess.SQLVal + var columnTypeScale *vitess.SQLVal + switch columnType := typ.(type) { + case *tree.ArrayTypeReference: + return nil, fmt.Errorf("array types are not yet supported") + case *tree.OIDTypeReference: + return nil, fmt.Errorf("referencing types by their OID is not yet supported") + case *tree.UnresolvedObjectName: + return nil, fmt.Errorf("type declaration format is not yet supported") + case *types.GeoMetadata: + return nil, fmt.Errorf("geometry types are not yet supported") + case *types.T: + columnTypeName = columnType.SQLStandardName() + switch columnType.Family() { + case types.DecimalFamily: + columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Precision())))) + columnTypeScale = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Scale())))) + case types.JsonFamily: + columnTypeName = "JSON" + case types.StringFamily: + columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Width())))) + case types.TimestampFamily: + columnTypeName = columnType.Name() + } + } + + return &vitess.ConvertType{ + Type: columnTypeName, + Length: columnTypeLength, + Scale: columnTypeScale, + Charset: "", // TODO + }, nil +} \ No newline at end of file From 6f67981b5df4015a9a371d60884f6a8e0f26c27e Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 28 Nov 2023 13:57:39 -0800 Subject: [PATCH 3/5] PR feedback --- server/ast/column_table_def.go | 38 +++----------- server/ast/expr.go | 61 ++++++---------------- server/ast/resolvable_type_reference.go | 69 +++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 75 deletions(-) create mode 100755 server/ast/resolvable_type_reference.go diff --git a/server/ast/column_table_def.go b/server/ast/column_table_def.go index 1fc8a6f394..a45224dc32 100644 --- a/server/ast/column_table_def.go +++ b/server/ast/column_table_def.go @@ -16,12 +16,10 @@ package ast import ( "fmt" - "strconv" vitess "github.com/dolthub/vitess/go/vt/sqlparser" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" - "github.com/dolthub/doltgresql/postgres/parser/types" ) // nodeColumnTableDef handles *tree.ColumnTableDef nodes. @@ -40,32 +38,12 @@ func nodeColumnTableDef(node *tree.ColumnTableDef) (_ *vitess.ColumnDefinition, if node.Family.Create || len(node.Family.Name) > 0 { return nil, fmt.Errorf("FAMILY is not yet supported") } - var columnTypeName string - var columnTypeLength *vitess.SQLVal - var columnTypeScale *vitess.SQLVal - switch columnType := node.Type.(type) { - case *tree.ArrayTypeReference: - return nil, fmt.Errorf("array types are not yet supported") - case *tree.OIDTypeReference: - return nil, fmt.Errorf("referencing types by their OID is not yet supported") - case *tree.UnresolvedObjectName: - return nil, fmt.Errorf("type declaration format is not yet supported") - case *types.GeoMetadata: - return nil, fmt.Errorf("geometry types are not yet supported") - case *types.T: - columnTypeName = columnType.SQLStandardName() - switch columnType.Family() { - case types.DecimalFamily: - columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Precision())))) - columnTypeScale = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Scale())))) - case types.JsonFamily: - columnTypeName = "JSON" - case types.StringFamily: - columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Width())))) - case types.TimestampFamily: - columnTypeName = columnType.Name() - } + + typeParams, err := nodeResolvableTypeReference(node.Type) + if err != nil { + return nil, err } + var isNull vitess.BoolVal var isNotNull vitess.BoolVal switch node.Nullable.Nullability { @@ -126,13 +104,13 @@ func nodeColumnTableDef(node *tree.ColumnTableDef) (_ *vitess.ColumnDefinition, return &vitess.ColumnDefinition{ Name: vitess.NewColIdent(string(node.Name)), Type: vitess.ColumnType{ - Type: columnTypeName, + Type: typeParams.name, Null: isNull, NotNull: isNotNull, Autoincrement: vitess.BoolVal(node.IsSerial), Default: defaultExpr, - Length: columnTypeLength, - Scale: columnTypeScale, + Length: typeParams.length, + Scale: typeParams.scale, KeyOpt: keyOpt, ForeignKeyDef: fkDef, GeneratedExpr: generated, diff --git a/server/ast/expr.go b/server/ast/expr.go index 5148468387..0ccdb0c0ee 100644 --- a/server/ast/expr.go +++ b/server/ast/expr.go @@ -17,9 +17,7 @@ package ast import ( "fmt" "go/constant" - "strconv" - "github.com/dolthub/doltgresql/postgres/parser/types" vitess "github.com/dolthub/vitess/go/vt/sqlparser" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" @@ -190,15 +188,28 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { return nil, err } - convertType, err := typeConvertType(node.Type) + if node.SyntaxMode == tree.CastShort { + return nil, fmt.Errorf("TYPECAST is not yet supported") + } + + if node.SyntaxMode == tree.CastPrepend { + return nil, fmt.Errorf("typed literals are not yet supported") + } + + params, err := nodeResolvableTypeReference(node.Type) if err != nil { return nil, err } - + return &vitess.ConvertExpr{ Name: "CAST", Expr: expr, - Type: convertType, + Type: &vitess.ConvertType{ + Type: params.name, + Length: params.length, + Scale: params.scale, + Charset: "", // TODO + }, }, nil case *tree.CoalesceExpr: return nil, fmt.Errorf("COALESCE is not yet supported") @@ -542,44 +553,4 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { default: return nil, fmt.Errorf("unknown expression: `%T`", node) } -} - -func typeConvertType(typ tree.ResolvableTypeReference) (*vitess.ConvertType, error) { - if typ == nil { - return nil, nil - } - - var columnTypeName string - var columnTypeLength *vitess.SQLVal - var columnTypeScale *vitess.SQLVal - switch columnType := typ.(type) { - case *tree.ArrayTypeReference: - return nil, fmt.Errorf("array types are not yet supported") - case *tree.OIDTypeReference: - return nil, fmt.Errorf("referencing types by their OID is not yet supported") - case *tree.UnresolvedObjectName: - return nil, fmt.Errorf("type declaration format is not yet supported") - case *types.GeoMetadata: - return nil, fmt.Errorf("geometry types are not yet supported") - case *types.T: - columnTypeName = columnType.SQLStandardName() - switch columnType.Family() { - case types.DecimalFamily: - columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Precision())))) - columnTypeScale = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Scale())))) - case types.JsonFamily: - columnTypeName = "JSON" - case types.StringFamily: - columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Width())))) - case types.TimestampFamily: - columnTypeName = columnType.Name() - } - } - - return &vitess.ConvertType{ - Type: columnTypeName, - Length: columnTypeLength, - Scale: columnTypeScale, - Charset: "", // TODO - }, nil } \ No newline at end of file diff --git a/server/ast/resolvable_type_reference.go b/server/ast/resolvable_type_reference.go new file mode 100755 index 0000000000..9558743579 --- /dev/null +++ b/server/ast/resolvable_type_reference.go @@ -0,0 +1,69 @@ +// 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 ast + +import ( + "fmt" + "strconv" + + "github.com/dolthub/doltgresql/postgres/parser/sem/tree" + "github.com/dolthub/doltgresql/postgres/parser/types" + vitess "github.com/dolthub/vitess/go/vt/sqlparser" +) + +type typeParams struct { + name string + length *vitess.SQLVal + scale *vitess.SQLVal +} + +func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*typeParams, error) { + if typ == nil { + return nil, nil + } + + var columnTypeName string + var columnTypeLength *vitess.SQLVal + var columnTypeScale *vitess.SQLVal + switch columnType := typ.(type) { + case *tree.ArrayTypeReference: + return nil, fmt.Errorf("array types are not yet supported") + case *tree.OIDTypeReference: + return nil, fmt.Errorf("referencing types by their OID is not yet supported") + case *tree.UnresolvedObjectName: + return nil, fmt.Errorf("type declaration format is not yet supported") + case *types.GeoMetadata: + return nil, fmt.Errorf("geometry types are not yet supported") + case *types.T: + columnTypeName = columnType.SQLStandardName() + switch columnType.Family() { + case types.DecimalFamily: + columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Precision())))) + columnTypeScale = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Scale())))) + case types.JsonFamily: + columnTypeName = "JSON" + case types.StringFamily: + columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Width())))) + case types.TimestampFamily: + columnTypeName = columnType.Name() + } + } + + return &typeParams{ + name: columnTypeName, + length: columnTypeLength, + scale: columnTypeScale, + }, nil +} From a4213c788de90b0bd99dfb4ce9a264c95df5bd04 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 28 Nov 2023 13:58:29 -0800 Subject: [PATCH 4/5] Formatting --- server/ast/column_table_def.go | 4 ++-- server/ast/expr.go | 4 ++-- server/ast/resolvable_type_reference.go | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/server/ast/column_table_def.go b/server/ast/column_table_def.go index a45224dc32..b2dd3654be 100644 --- a/server/ast/column_table_def.go +++ b/server/ast/column_table_def.go @@ -38,12 +38,12 @@ func nodeColumnTableDef(node *tree.ColumnTableDef) (_ *vitess.ColumnDefinition, if node.Family.Create || len(node.Family.Name) > 0 { return nil, fmt.Errorf("FAMILY is not yet supported") } - + typeParams, err := nodeResolvableTypeReference(node.Type) if err != nil { return nil, err } - + var isNull vitess.BoolVal var isNotNull vitess.BoolVal switch node.Nullable.Nullability { diff --git a/server/ast/expr.go b/server/ast/expr.go index 0ccdb0c0ee..e83a16663c 100644 --- a/server/ast/expr.go +++ b/server/ast/expr.go @@ -187,7 +187,7 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { if err != nil { return nil, err } - + if node.SyntaxMode == tree.CastShort { return nil, fmt.Errorf("TYPECAST is not yet supported") } @@ -553,4 +553,4 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { default: return nil, fmt.Errorf("unknown expression: `%T`", node) } -} \ No newline at end of file +} diff --git a/server/ast/resolvable_type_reference.go b/server/ast/resolvable_type_reference.go index 9558743579..20d5e15c49 100755 --- a/server/ast/resolvable_type_reference.go +++ b/server/ast/resolvable_type_reference.go @@ -18,15 +18,16 @@ import ( "fmt" "strconv" + vitess "github.com/dolthub/vitess/go/vt/sqlparser" + "github.com/dolthub/doltgresql/postgres/parser/sem/tree" "github.com/dolthub/doltgresql/postgres/parser/types" - vitess "github.com/dolthub/vitess/go/vt/sqlparser" ) type typeParams struct { - name string + name string length *vitess.SQLVal - scale *vitess.SQLVal + scale *vitess.SQLVal } func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*typeParams, error) { @@ -62,8 +63,8 @@ func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*typeParams, } return &typeParams{ - name: columnTypeName, - length: columnTypeLength, - scale: columnTypeScale, + name: columnTypeName, + length: columnTypeLength, + scale: columnTypeScale, }, nil } From dba2cda4b742bce61c9a2652d27157c0c32b6eb6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 28 Nov 2023 14:49:47 -0800 Subject: [PATCH 5/5] Switch with default error --- server/ast/expr.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server/ast/expr.go b/server/ast/expr.go index e83a16663c..220ea2b468 100644 --- a/server/ast/expr.go +++ b/server/ast/expr.go @@ -188,12 +188,15 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) { return nil, err } - if node.SyntaxMode == tree.CastShort { + switch node.SyntaxMode { + case tree.CastExplicit: + // only acceptable cast type + case tree.CastShort: return nil, fmt.Errorf("TYPECAST is not yet supported") - } - - if node.SyntaxMode == tree.CastPrepend { + case tree.CastPrepend: return nil, fmt.Errorf("typed literals are not yet supported") + default: + return nil, fmt.Errorf("unknown cast syntax") } params, err := nodeResolvableTypeReference(node.Type)