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

All Array Types #162

Merged
merged 2 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions postgres/parser/sem/tree/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ type typeAnnotation struct {
typ *types.T
}

func (ta typeAnnotation) HasResolvedType() bool {
return ta.typ != nil
}

func (ta typeAnnotation) ResolvedType() *types.T {
ta.assertTyped()
return ta.typ
Expand Down
47 changes: 21 additions & 26 deletions server/ast/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ import (
"go/constant"
"strings"

"github.com/dolthub/go-mysql-server/sql"
"github.com/dolthub/go-mysql-server/sql/expression"
vitess "github.com/dolthub/vitess/go/vt/sqlparser"

"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
"github.com/dolthub/doltgresql/postgres/parser/types"
pgexprs "github.com/dolthub/doltgresql/server/expression"
"github.com/dolthub/doltgresql/server/functions/framework"
pgtypes "github.com/dolthub/doltgresql/server/types"
Expand Down Expand Up @@ -101,32 +99,27 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
case *tree.AnnotateTypeExpr:
return nil, fmt.Errorf("ANNOTATE_TYPE is not yet supported")
case *tree.Array:
//TODO: right now, this only works with boolean array values for the sake of demonstration
var sqlChildren []sql.Expression
var unresolvedChildren []vitess.Expr
var unresolvedIndexes []int
if len(node.Exprs) == 0 {
if node.ResolvedType().Family() == types.ArrayFamily && node.ResolvedType().ArrayContents().Family() == types.BoolFamily {
sqlChildren = []sql.Expression{expression.NewLiteral([]bool{}, pgtypes.BoolArray)}
unresolvedChildren := make([]vitess.Expr, len(node.Exprs))
var coercedType pgtypes.DoltgresType
if node.HasResolvedType() {
_, resolvedType, err := nodeResolvableTypeReference(node.ResolvedType())
if err != nil {
return nil, err
}
if arrayType, ok := resolvedType.(pgtypes.DoltgresArrayType); ok {
coercedType = arrayType
} else {
return nil, fmt.Errorf("arrays are generally not yet supported")
return nil, fmt.Errorf("array has invalid resolved type")
}
} else {
for _, arrayExpr := range node.Exprs {
if arrayVal, ok := arrayExpr.(*tree.DBool); ok && arrayVal != nil {
sqlChildren = append(sqlChildren, expression.NewLiteral(bool(*arrayVal), pgtypes.Bool))
} else {
unresolvedChild, err := nodeExpr(arrayExpr)
if err != nil {
return nil, err
}
unresolvedChildren = append(unresolvedChildren, unresolvedChild)
unresolvedIndexes = append(unresolvedIndexes, len(sqlChildren))
sqlChildren = append(sqlChildren, nil)
}
}
for i, arrayExpr := range node.Exprs {
var err error
unresolvedChildren[i], err = nodeExpr(arrayExpr)
if err != nil {
return nil, err
}
}
arrayExpr, err := pgexprs.NewArray(sqlChildren, unresolvedChildren, unresolvedIndexes, nil)
arrayExpr, err := pgexprs.NewArray(coercedType)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -375,7 +368,9 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
case *tree.DBitArray:
return nil, fmt.Errorf("the statement is not yet supported")
case *tree.DBool:
return nil, fmt.Errorf("the statement is not yet supported")
return vitess.InjectedExpr{
Expression: pgexprs.NewBoolLiteral(bool(*node)),
}, nil
case *tree.DBox2D:
return nil, fmt.Errorf("the statement is not yet supported")
case *tree.DBytes:
Expand Down Expand Up @@ -489,7 +484,7 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
Expression: intLiteral,
}, err
case constant.Float:
numericLiteral, err := pgexprs.NewFloatLiteral(node.FormattedString())
numericLiteral, err := pgexprs.NewNumericLiteral(node.FormattedString())
return vitess.InjectedExpr{
Expression: numericLiteral,
}, err
Expand Down
22 changes: 17 additions & 5 deletions server/ast/resolvable_type_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@ func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*vitess.Conv
columnTypeName = columnType.SQLStandardName()
switch columnType.Family() {
case types.ArrayFamily:
if columnType.ArrayContents().Family() == types.BoolFamily {
resolvedType = pgtypes.BoolArray
_, baseResolvedType, err := nodeResolvableTypeReference(columnType.ArrayContents())
if err != nil {
return nil, nil, err
}
if doltgresType, ok := baseResolvedType.(pgtypes.DoltgresType); ok {
resolvedType = doltgresType.ToArrayType()
} else {
return nil, nil, fmt.Errorf("the given array type is not yet supported")
}
Expand All @@ -72,7 +76,7 @@ func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*vitess.Conv
case oid.T_float8:
resolvedType = pgtypes.Float64
default:
return nil, nil, fmt.Errorf("unknown type in float familiy: %s", typ.SQLString())
return nil, nil, fmt.Errorf("unknown type in float family: %s", typ.SQLString())
}
case types.IntFamily:
switch columnType.Oid() {
Expand All @@ -83,14 +87,22 @@ func nodeResolvableTypeReference(typ tree.ResolvableTypeReference) (*vitess.Conv
case oid.T_int8:
resolvedType = pgtypes.Int64
default:
return nil, nil, fmt.Errorf("unknown type in integer familiy: %s", typ.SQLString())
return nil, nil, fmt.Errorf("unknown type in integer family: %s", typ.SQLString())
}
case types.JsonFamily:
columnTypeName = "JSON"
case types.StringFamily:
switch columnType.Oid() {
case oid.T_varchar:
resolvedType = pgtypes.VarCharType{Length: uint32(columnType.Width())}
width := uint32(columnType.Width())
if width > pgtypes.VarCharMaxLength {
return nil, nil, fmt.Errorf("length for type varchar cannot exceed %d", pgtypes.VarCharMaxLength)
}
// Handle varchars that do not declare a length, as they will set the width at zero
if width == 0 {
width = pgtypes.VarCharMaxLength
}
resolvedType = pgtypes.VarCharType{Length: width}
default:
columnTypeLength = vitess.NewIntVal([]byte(strconv.Itoa(int(columnType.Width()))))
}
Expand Down
Loading
Loading