implemented extract ddl; tightened up type related stuff (#2329)

* implemented extract ddl; tightened up type related stuff

* added some test coverage

* review feedback
This commit is contained in:
pokeeffe-molecula 2022-12-05 16:50:30 -06:00 committed by GitHub
parent 2843f218bc
commit f62313762c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 1820 additions and 1464 deletions

View file

@ -162,7 +162,7 @@ func (q *Queryer) QuerySQL(ctx context.Context, qual dax.TableQualifier, sql str
Fields: make([]*featurebase.WireQueryField, len(columns)),
}
for i, col := range columns {
btype, err := dax.BaseTypeFromString(col.Type.TypeName())
btype, err := dax.BaseTypeFromString(col.Type.BaseTypeName())
if err != nil {
applyError(errors.Wrap(err, "getting fieldtype from string"))
return ret, nil

View file

@ -12,7 +12,6 @@ import (
"fmt"
"io"
"math"
"math/big"
"mime"
"net"
"net/http"
@ -1437,30 +1436,36 @@ func (h *Handler) handlePostSQL(w http.ResponseWriter, r *http.Request) {
// Write the closing bracket on any exit from this method.
defer func() {
var execTime int64 = 0
// we are going to make best effort here - don't actually care about the error
// if there was an error, the request.ElapsedTime will be zero
request, _ := h.api.server.SystemLayer.ExecutionRequests().GetRequest(requestID.String())
execTime = request.ElapsedTime.Microseconds()
var value []byte
request, err := h.api.server.SystemLayer.ExecutionRequests().GetRequest(requestID.String())
value, err = json.Marshal(execTime)
if err != nil {
value = big.NewInt(-1).Bytes()
w.Write([]byte(`,"exec_time": 0`))
} else {
value, err = json.Marshal(request.ElapsedTime.Microseconds())
if err != nil {
value = big.NewInt(-1).Bytes()
}
w.Write([]byte(`,"exec_time":`))
w.Write(value)
}
w.Write([]byte(`,"exec_time":`))
w.Write(value)
w.Write([]byte("}"))
}()
// writeError is a helper function that can be called anywhere during the
// output handling to insert an error into the json output.
writeError := func(err error) {
writeError := func(err error, withComma bool) {
if err != nil {
errMsg, err := json.Marshal(err.Error())
if err != nil {
errMsg = []byte(`"PROBLEM ENCODING ERROR MESSAGE"`)
}
w.Write([]byte(`,"error":`))
if withComma {
w.Write([]byte(`,"error":`))
} else {
w.Write([]byte(`"error":`))
}
w.Write(errMsg)
}
}
@ -1498,7 +1503,7 @@ func (h *Handler) handlePostSQL(w http.ResponseWriter, r *http.Request) {
// Get a query iterator.
iter, err := rootOperator.Iterator(ctx, nil)
if err != nil {
writeError(err)
writeError(err, false)
writeWarnings(rootOperator.Warnings())
return
}
@ -1509,15 +1514,15 @@ func (h *Handler) handlePostSQL(w http.ResponseWriter, r *http.Request) {
Fields: make([]*WireQueryField, len(columns)),
}
for i, col := range columns {
btype, err := dax.BaseTypeFromString(col.Type.TypeName())
btype, err := dax.BaseTypeFromString(col.Type.BaseTypeName())
if err != nil {
writeError(err)
writeError(err, false)
writeWarnings(rootOperator.Warnings())
return
}
schema.Fields[i] = &WireQueryField{
Name: dax.FieldName(col.ColumnName),
Type: strings.ToLower(col.Type.TypeDescription()), // TODO(tlt): remove this once sql3 uses BaseTypes.
Type: col.Type.TypeDescription(),
BaseType: btype,
TypeInfo: col.Type.TypeInfo(),
}
@ -1528,7 +1533,7 @@ func (h *Handler) handlePostSQL(w http.ResponseWriter, r *http.Request) {
h.logger.Errorf("write schema response error: %s", err)
// Provide an empty list as the schema value to maintain valid json.
w.Write([]byte("[]"))
writeError(err)
writeError(err, false)
writeWarnings(rootOperator.Warnings())
return
}
@ -1564,7 +1569,7 @@ func (h *Handler) handlePostSQL(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("]"))
writeError(rowErr)
writeError(rowErr, true)
writeWarnings(rootOperator.Warnings())
writePlan(rootOperator.Plan())
}

View file

@ -13,114 +13,116 @@ type Node interface {
fmt.Stringer
}
func (*AlterTableStatement) node() {}
func (*AnalyzeStatement) node() {}
func (*Assignment) node() {}
func (*ShowTablesStatement) node() {}
func (*ShowColumnsStatement) node() {}
func (*BeginStatement) node() {}
func (*BinaryExpr) node() {}
func (*BoolLit) node() {}
func (*BulkInsertMapDefinition) node() {}
func (*BulkInsertStatement) node() {}
func (*CacheTypeConstraint) node() {}
func (*Call) node() {}
func (*CaseBlock) node() {}
func (*CaseExpr) node() {}
func (*CastExpr) node() {}
func (*CheckConstraint) node() {}
func (*ColumnDefinition) node() {}
func (*CommitStatement) node() {}
func (*CreateIndexStatement) node() {}
func (*CreateTableStatement) node() {}
func (*CreateFunctionStatement) node() {}
func (*CreateViewStatement) node() {}
func (*DateLit) node() {}
func (*DefaultConstraint) node() {}
func (*DeleteStatement) node() {}
func (*DropIndexStatement) node() {}
func (*DropTableStatement) node() {}
func (*DropFunctionStatement) node() {}
func (*DropViewStatement) node() {}
func (*Exists) node() {}
func (*ExplainStatement) node() {}
func (*ExprList) node() {}
func (*FilterClause) node() {}
func (*FloatLit) node() {}
func (*ForeignKeyArg) node() {}
func (*ForeignKeyConstraint) node() {}
func (*FrameSpec) node() {}
func (*Ident) node() {}
func (*Variable) node() {}
func (*IndexedColumn) node() {}
func (*InsertStatement) node() {}
func (*JoinClause) node() {}
func (*JoinOperator) node() {}
func (*KeyPartitionsOption) node() {}
func (*MinConstraint) node() {}
func (*MaxConstraint) node() {}
func (*NotNullConstraint) node() {}
func (*NullLit) node() {}
func (*IntegerLit) node() {}
func (*OnConstraint) node() {}
func (*OrderingTerm) node() {}
func (*OverClause) node() {}
func (*ParenExpr) node() {}
func (*SetLiteralExpr) node() {}
func (*ParenSource) node() {}
func (*PrimaryKeyConstraint) node() {}
func (*QualifiedRef) node() {}
func (*QualifiedTableName) node() {}
func (*Range) node() {}
func (*ReleaseStatement) node() {}
func (*ResultColumn) node() {}
func (*RollbackStatement) node() {}
func (*SavepointStatement) node() {}
func (*SelectStatement) node() {}
func (*ShardWidthOption) node() {}
func (*StringLit) node() {}
func (*TableValuedFunction) node() {}
func (*TimeUnitConstraint) node() {}
func (*TimeQuantumConstraint) node() {}
func (*TupleLiteralExpr) node() {}
func (*Type) node() {}
func (*UnaryExpr) node() {}
func (*UniqueConstraint) node() {}
func (*UpdateStatement) node() {}
func (*UpsertClause) node() {}
func (*UsingConstraint) node() {}
func (*Window) node() {}
func (*WindowDefinition) node() {}
func (*WithClause) node() {}
func (*AlterTableStatement) node() {}
func (*AnalyzeStatement) node() {}
func (*Assignment) node() {}
func (*ShowTablesStatement) node() {}
func (*ShowColumnsStatement) node() {}
func (*ShowCreateTableStatement) node() {}
func (*BeginStatement) node() {}
func (*BinaryExpr) node() {}
func (*BoolLit) node() {}
func (*BulkInsertMapDefinition) node() {}
func (*BulkInsertStatement) node() {}
func (*CacheTypeConstraint) node() {}
func (*Call) node() {}
func (*CaseBlock) node() {}
func (*CaseExpr) node() {}
func (*CastExpr) node() {}
func (*CheckConstraint) node() {}
func (*ColumnDefinition) node() {}
func (*CommitStatement) node() {}
func (*CreateIndexStatement) node() {}
func (*CreateTableStatement) node() {}
func (*CreateFunctionStatement) node() {}
func (*CreateViewStatement) node() {}
func (*DateLit) node() {}
func (*DefaultConstraint) node() {}
func (*DeleteStatement) node() {}
func (*DropIndexStatement) node() {}
func (*DropTableStatement) node() {}
func (*DropFunctionStatement) node() {}
func (*DropViewStatement) node() {}
func (*Exists) node() {}
func (*ExplainStatement) node() {}
func (*ExprList) node() {}
func (*FilterClause) node() {}
func (*FloatLit) node() {}
func (*ForeignKeyArg) node() {}
func (*ForeignKeyConstraint) node() {}
func (*FrameSpec) node() {}
func (*Ident) node() {}
func (*Variable) node() {}
func (*IndexedColumn) node() {}
func (*InsertStatement) node() {}
func (*JoinClause) node() {}
func (*JoinOperator) node() {}
func (*KeyPartitionsOption) node() {}
func (*MinConstraint) node() {}
func (*MaxConstraint) node() {}
func (*NotNullConstraint) node() {}
func (*NullLit) node() {}
func (*IntegerLit) node() {}
func (*OnConstraint) node() {}
func (*OrderingTerm) node() {}
func (*OverClause) node() {}
func (*ParenExpr) node() {}
func (*SetLiteralExpr) node() {}
func (*ParenSource) node() {}
func (*PrimaryKeyConstraint) node() {}
func (*QualifiedRef) node() {}
func (*QualifiedTableName) node() {}
func (*Range) node() {}
func (*ReleaseStatement) node() {}
func (*ResultColumn) node() {}
func (*RollbackStatement) node() {}
func (*SavepointStatement) node() {}
func (*SelectStatement) node() {}
func (*ShardWidthOption) node() {}
func (*StringLit) node() {}
func (*TableValuedFunction) node() {}
func (*TimeUnitConstraint) node() {}
func (*TimeQuantumConstraint) node() {}
func (*TupleLiteralExpr) node() {}
func (*Type) node() {}
func (*UnaryExpr) node() {}
func (*UniqueConstraint) node() {}
func (*UpdateStatement) node() {}
func (*UpsertClause) node() {}
func (*UsingConstraint) node() {}
func (*Window) node() {}
func (*WindowDefinition) node() {}
func (*WithClause) node() {}
type Statement interface {
Node
stmt()
}
func (*AlterTableStatement) stmt() {}
func (*AnalyzeStatement) stmt() {}
func (*BeginStatement) stmt() {}
func (*BulkInsertStatement) stmt() {}
func (*ShowTablesStatement) stmt() {}
func (*ShowColumnsStatement) stmt() {}
func (*CommitStatement) stmt() {}
func (*CreateIndexStatement) stmt() {}
func (*CreateTableStatement) stmt() {}
func (*CreateFunctionStatement) stmt() {}
func (*CreateViewStatement) stmt() {}
func (*DeleteStatement) stmt() {}
func (*DropIndexStatement) stmt() {}
func (*DropTableStatement) stmt() {}
func (*DropFunctionStatement) stmt() {}
func (*DropViewStatement) stmt() {}
func (*ExplainStatement) stmt() {}
func (*InsertStatement) stmt() {}
func (*ReleaseStatement) stmt() {}
func (*RollbackStatement) stmt() {}
func (*SavepointStatement) stmt() {}
func (*SelectStatement) stmt() {}
func (*UpdateStatement) stmt() {}
func (*AlterTableStatement) stmt() {}
func (*AnalyzeStatement) stmt() {}
func (*BeginStatement) stmt() {}
func (*BulkInsertStatement) stmt() {}
func (*ShowTablesStatement) stmt() {}
func (*ShowColumnsStatement) stmt() {}
func (*ShowCreateTableStatement) stmt() {}
func (*CommitStatement) stmt() {}
func (*CreateIndexStatement) stmt() {}
func (*CreateTableStatement) stmt() {}
func (*CreateFunctionStatement) stmt() {}
func (*CreateViewStatement) stmt() {}
func (*DeleteStatement) stmt() {}
func (*DropIndexStatement) stmt() {}
func (*DropTableStatement) stmt() {}
func (*DropFunctionStatement) stmt() {}
func (*DropViewStatement) stmt() {}
func (*ExplainStatement) stmt() {}
func (*InsertStatement) stmt() {}
func (*ReleaseStatement) stmt() {}
func (*RollbackStatement) stmt() {}
func (*SavepointStatement) stmt() {}
func (*SelectStatement) stmt() {}
func (*UpdateStatement) stmt() {}
// CloneStatement returns a deep copy stmt.
func CloneStatement(stmt Statement) Statement {
@ -494,6 +496,23 @@ func (s *ShowColumnsStatement) String() string {
return buf.String()
}
type ShowCreateTableStatement struct {
Show Pos // position of SHOW
Create Pos // position of CREATE
Table Pos // position of CREATE
TableName *Ident // name of table
}
// String returns the string representation of the statement.
func (s *ShowCreateTableStatement) String() string {
var buf bytes.Buffer
buf.WriteString("SHOW CREATE TABLE ")
if s.TableName != nil {
fmt.Fprintf(&buf, " %s", s.TableName.String())
}
return buf.String()
}
type BeginStatement struct {
Begin Pos // position of BEGIN
Deferred Pos // position of DEFERRED keyword

View file

@ -3,43 +3,39 @@ package parser
import (
"fmt"
"strings"
)
// TODO(pok) make all these lower case
const (
FieldTypeBool = "BOOL"
FieldTypeDecimal = "DECIMAL"
FieldTypeID = "ID"
FieldTypeIDSet = "IDSET"
FieldTypeIDSetQuantum = "IDSETQ"
FieldTypeInt = "INT"
FieldTypeString = "STRING"
FieldTypeStringSet = "STRINGSET"
FieldTypeStringSetQuantum = "STRINGSETQ"
FieldTypeTimestamp = "TIMESTAMP"
"github.com/molecula/featurebase/v3/dax"
)
func IsValidTypeName(typeName string) bool {
switch strings.ToUpper(typeName) {
case FieldTypeBool,
FieldTypeDecimal,
FieldTypeID,
FieldTypeIDSet,
FieldTypeInt,
FieldTypeString,
FieldTypeStringSet,
FieldTypeTimestamp:
switch strings.ToLower(typeName) {
case dax.BaseTypeBool,
dax.BaseTypeDecimal,
dax.BaseTypeID,
dax.BaseTypeIDSet,
dax.BaseTypeInt,
dax.BaseTypeString,
dax.BaseTypeStringSet,
dax.BaseTypeTimestamp:
return true
default:
return false
}
}
// ExprDataType is the interface for all language layer types
type ExprDataType interface {
exprDataType()
TypeName() string
TypeDescription() string
// the base type name e.g. int or decimal
BaseTypeName() string
// additional type information - intended to be used outside the language
// layer (marshalled over json, or otherwise serialized so that consumers
// have access to complete type information)
// TypeInfo is not used inside the language layer itself, as the concrete
// types (e.g. DataTypeString) are used
TypeInfo() map[string]interface{}
// the full type specification as a string - intended to be human readable
TypeDescription() string
}
func (*DataTypeVoid) exprDataType() {}
@ -64,12 +60,12 @@ func NewDataTypeVoid() *DataTypeVoid {
return &DataTypeVoid{}
}
func (*DataTypeVoid) TypeName() string {
return "VOID"
func (*DataTypeVoid) BaseTypeName() string {
return "void"
}
func (dt *DataTypeVoid) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeVoid) TypeInfo() map[string]interface{} {
@ -86,12 +82,12 @@ func NewDataTypeRange(subscriptType ExprDataType) *DataTypeRange {
}
}
func (dt *DataTypeRange) TypeName() string {
return fmt.Sprintf("RANGE(%s)", dt.SubscriptType.TypeName())
func (dt *DataTypeRange) BaseTypeName() string {
return "range"
}
func (dt *DataTypeRange) TypeDescription() string {
return dt.TypeName()
return fmt.Sprintf("range(%s)", dt.SubscriptType.TypeDescription())
}
func (*DataTypeRange) TypeInfo() map[string]interface{} {
@ -108,19 +104,19 @@ func NewDataTypeTuple(members []ExprDataType) *DataTypeTuple {
}
}
func (dt *DataTypeTuple) TypeName() string {
func (dt *DataTypeTuple) BaseTypeName() string {
return "tuple"
}
func (dt *DataTypeTuple) TypeDescription() string {
ms := ""
for idx, m := range dt.Members {
ms = ms + m.TypeName()
ms = ms + m.TypeDescription()
if idx+1 < len(dt.Members) {
ms = ms + ", "
}
}
return fmt.Sprintf("TUPLE(%s)", ms)
}
func (dt *DataTypeTuple) TypeDescription() string {
return dt.TypeName()
return fmt.Sprintf("tuple(%s)", ms)
}
func (*DataTypeTuple) TypeInfo() map[string]interface{} {
@ -142,19 +138,19 @@ func NewDataTypeSubtable(columns []*SubtableColumn) *DataTypeSubtable {
}
}
func (dt *DataTypeSubtable) TypeName() string {
func (dt *DataTypeSubtable) BaseTypeName() string {
return "subtable"
}
func (dt *DataTypeSubtable) TypeDescription() string {
ms := ""
for idx, m := range dt.Columns {
ms = ms + m.DataType.TypeName()
ms = ms + m.DataType.TypeDescription()
if idx+1 < len(dt.Columns) {
ms = ms + ", "
}
}
return fmt.Sprintf("SUBTABLE(%s)", ms)
}
func (dt *DataTypeSubtable) TypeDescription() string {
return dt.TypeName()
return fmt.Sprintf("subtable(%s)", ms)
}
func (*DataTypeSubtable) TypeInfo() map[string]interface{} {
@ -168,12 +164,12 @@ func NewDataTypeBool() *DataTypeBool {
return &DataTypeBool{}
}
func (*DataTypeBool) TypeName() string {
return FieldTypeBool
func (*DataTypeBool) BaseTypeName() string {
return dax.BaseTypeBool
}
func (dt *DataTypeBool) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeBool) TypeInfo() map[string]interface{} {
@ -190,12 +186,12 @@ func NewDataTypeDecimal(scale int64) *DataTypeDecimal {
}
}
func (d *DataTypeDecimal) TypeName() string {
return FieldTypeDecimal
func (d *DataTypeDecimal) BaseTypeName() string {
return dax.BaseTypeDecimal
}
func (d *DataTypeDecimal) TypeDescription() string {
return fmt.Sprintf("%s(%d)", FieldTypeDecimal, d.Scale)
return fmt.Sprintf("%s(%d)", dax.BaseTypeDecimal, d.Scale)
}
func (d *DataTypeDecimal) TypeInfo() map[string]interface{} {
@ -211,12 +207,12 @@ func NewDataTypeID() *DataTypeID {
return &DataTypeID{}
}
func (*DataTypeID) TypeName() string {
return FieldTypeID
func (*DataTypeID) BaseTypeName() string {
return dax.BaseTypeID
}
func (dt *DataTypeID) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeID) TypeInfo() map[string]interface{} {
@ -230,18 +226,19 @@ func NewDataTypeIDSet() *DataTypeIDSet {
return &DataTypeIDSet{}
}
func (*DataTypeIDSet) TypeName() string {
return FieldTypeIDSet
func (*DataTypeIDSet) BaseTypeName() string {
return dax.BaseTypeIDSet
}
func (dt *DataTypeIDSet) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeIDSet) TypeInfo() map[string]interface{} {
return nil
}
// TODO (pok) should time quantum be it's own type and not a constraint?
type DataTypeIDSetQuantum struct {
}
@ -249,12 +246,12 @@ func NewDataTypeIDSetQuantum() *DataTypeIDSetQuantum {
return &DataTypeIDSetQuantum{}
}
func (*DataTypeIDSetQuantum) TypeName() string {
return FieldTypeIDSetQuantum
func (*DataTypeIDSetQuantum) BaseTypeName() string {
return dax.BaseTypeIDSet
}
func (dt *DataTypeIDSetQuantum) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeIDSetQuantum) TypeInfo() map[string]interface{} {
@ -268,12 +265,12 @@ func NewDataTypeInt() *DataTypeInt {
return &DataTypeInt{}
}
func (*DataTypeInt) TypeName() string {
return FieldTypeInt
func (*DataTypeInt) BaseTypeName() string {
return dax.BaseTypeInt
}
func (dt *DataTypeInt) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeInt) TypeInfo() map[string]interface{} {
@ -287,12 +284,12 @@ func NewDataTypeString() *DataTypeString {
return &DataTypeString{}
}
func (*DataTypeString) TypeName() string {
return FieldTypeString
func (*DataTypeString) BaseTypeName() string {
return dax.BaseTypeString
}
func (dt *DataTypeString) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeString) TypeInfo() map[string]interface{} {
@ -306,12 +303,12 @@ func NewDataTypeStringSet() *DataTypeStringSet {
return &DataTypeStringSet{}
}
func (*DataTypeStringSet) TypeName() string {
return FieldTypeStringSet
func (*DataTypeStringSet) BaseTypeName() string {
return dax.BaseTypeStringSet
}
func (dt *DataTypeStringSet) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeStringSet) TypeInfo() map[string]interface{} {
@ -325,12 +322,12 @@ func NewDataTypeStringSetQuantum() *DataTypeStringSetQuantum {
return &DataTypeStringSetQuantum{}
}
func (*DataTypeStringSetQuantum) TypeName() string {
return FieldTypeStringSetQuantum
func (*DataTypeStringSetQuantum) BaseTypeName() string {
return dax.BaseTypeStringSet
}
func (dt *DataTypeStringSetQuantum) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeStringSetQuantum) TypeInfo() map[string]interface{} {
@ -344,12 +341,12 @@ func NewDataTypeTimestamp() *DataTypeTimestamp {
return &DataTypeTimestamp{}
}
func (*DataTypeTimestamp) TypeName() string {
return FieldTypeTimestamp
func (*DataTypeTimestamp) BaseTypeName() string {
return dax.BaseTypeTimestamp
}
func (dt *DataTypeTimestamp) TypeDescription() string {
return dt.TypeName()
return dt.BaseTypeName()
}
func (*DataTypeTimestamp) TypeInfo() map[string]interface{} {

View file

@ -163,8 +163,10 @@ func (p *Parser) parseShowStatement() (Statement, error) {
return p.parseShowTablesStatement(show)
case COLUMNS:
return p.parseShowColumnsStatement(show)
case CREATE:
return p.parseShowCreateStatement(show)
default:
return nil, p.errorExpected(p.pos, p.tok, "TABLES, COLUMNS")
return nil, p.errorExpected(p.pos, p.tok, "TABLES, COLUMNS or CREATE")
}
}
@ -200,6 +202,33 @@ func (p *Parser) parseShowColumnsStatement(showPos Pos) (_ *ShowColumnsStatement
}
}
func (p *Parser) parseShowCreateStatement(showPos Pos) (Statement, error) {
assert(p.peek() == CREATE)
create, _, _ := p.scan()
switch p.peek() {
case TABLE:
return p.parseShowCreateTableStatement(showPos, create)
default:
return nil, p.errorExpected(p.pos, p.tok, "TABLES")
}
}
func (p *Parser) parseShowCreateTableStatement(showPos Pos, createPos Pos) (_ *ShowCreateTableStatement, err error) {
assert(p.peek() == TABLE)
table, _, _ := p.scan()
var stmt ShowCreateTableStatement
stmt.Show = showPos
stmt.Create = createPos
stmt.Table = table
if stmt.TableName, err = p.parseIdent("table name"); err != nil {
return &stmt, err
}
return &stmt, nil
}
/*func (p *Parser) parseBeginStatement() (*BeginStatement, error) {
assert(p.peek() == BEGIN)

View file

@ -627,8 +627,8 @@ func TestParser_ParseStatement(t *testing.T) {
Show: pos(0),
Tables: pos(5),
})
AssertParseStatementError(t, `SHOW`, `1:4: expected TABLES, COLUMNS, found 'EOF'`)
AssertParseStatementError(t, `SHOW BLAH`, `1:6: expected TABLES, COLUMNS, found BLAH`)
AssertParseStatementError(t, `SHOW`, `1:4: expected TABLES, COLUMNS or CREATE, found 'EOF'`)
AssertParseStatementError(t, `SHOW BLAH`, `1:6: expected TABLES, COLUMNS or CREATE, found BLAH`)
})
t.Run("ShowColumns", func(t *testing.T) {
@ -641,13 +641,29 @@ func TestParser_ParseStatement(t *testing.T) {
NamePos: pos(18),
},
})
AssertParseStatementError(t, `SHOW`, `1:4: expected TABLES, COLUMNS, found 'EOF'`)
AssertParseStatementError(t, `SHOW`, `1:4: expected TABLES, COLUMNS or CREATE, found 'EOF'`)
AssertParseStatementError(t, `SHOW COLUMNS`, `1:12: expected FROM, found 'EOF'`)
AssertParseStatementError(t, `SHOW COLUMNS FOO`, `1:14: expected FROM, found FOO`)
AssertParseStatementError(t, `SHOW COLUMNS FROM`, `1:17: expected table name, found 'EOF'`)
AssertParseStatementError(t, `SHOW COLUMNS FROM 12`, `1:19: expected table name, found 12`)
})
t.Run("ShowCreateTable", func(t *testing.T) {
AssertParseStatement(t, `SHOW CREATE TABLE FOO`, &parser.ShowCreateTableStatement{
Show: pos(0),
Create: pos(5),
Table: pos(12),
TableName: &parser.Ident{
Name: "FOO",
NamePos: pos(18),
},
})
AssertParseStatementError(t, `SHOW`, `1:4: expected TABLES, COLUMNS or CREATE, found 'EOF'`)
AssertParseStatementError(t, `SHOW CREATE`, `1:11: expected TABLES, found 'EOF'`)
AssertParseStatementError(t, `SHOW CREATE TABLE`, `1:17: expected table name, found 'EOF'`)
AssertParseStatementError(t, `SHOW CREATE TABLE 12`, `1:19: expected table name, found 12`)
})
t.Run("Explain", func(t *testing.T) {
/*t.Run("", func(t *testing.T) {
AssertParseStatement(t, `EXPLAIN BEGIN`, &parser.ExplainStatement{

View file

@ -337,7 +337,7 @@ func (p *ExecutionPlanner) analyzeBulkInsertStatement(stmt *parser.BulkInsertSta
if stmt.TransformList != nil {
t := stmt.TransformList[idx]
if !typesAreAssignmentCompatible(colDataType, t.DataType()) {
return sql3.NewErrTypeAssignmentIncompatible(t.Pos().Line, t.Pos().Column, t.DataType().TypeName(), colDataType.TypeName())
return sql3.NewErrTypeAssignmentIncompatible(t.Pos().Line, t.Pos().Column, t.DataType().TypeDescription(), colDataType.TypeDescription())
}
} else {
// this assumes that map and col list have already been checked for length
@ -347,7 +347,7 @@ func (p *ExecutionPlanner) analyzeBulkInsertStatement(stmt *parser.BulkInsertSta
return err
}
if !typesAreAssignmentCompatible(colDataType, t) {
return sql3.NewErrTypeAssignmentIncompatible(me.MapExpr.Pos().Line, me.MapExpr.Pos().Column, t.TypeName(), colDataType.TypeName())
return sql3.NewErrTypeAssignmentIncompatible(me.MapExpr.Pos().Line, me.MapExpr.Pos().Column, t.TypeDescription(), colDataType.TypeDescription())
}
}
break

View file

@ -8,6 +8,7 @@ import (
"time"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/dax"
"github.com/molecula/featurebase/v3/pql"
"github.com/molecula/featurebase/v3/sql3"
"github.com/molecula/featurebase/v3/sql3/parser"
@ -49,7 +50,7 @@ func (p *ExecutionPlanner) compileCreateTableStatement(stmt *parser.CreateTableS
typeName := parser.IdentName(col.Type.Name)
if strings.ToLower(columnName) == "_id" {
if strings.EqualFold(typeName, parser.FieldTypeString) {
if strings.EqualFold(typeName, dax.BaseTypeString) {
isKeyed = true
}
continue
@ -181,10 +182,10 @@ func (p *ExecutionPlanner) compileColumn(col *parser.ColumnDefinition) (*createT
}
}
switch strings.ToUpper(typeName) {
case parser.FieldTypeBool:
switch strings.ToLower(typeName) {
case dax.BaseTypeBool:
column.fos = append(column.fos, pilosa.OptFieldTypeBool())
case parser.FieldTypeDecimal:
case dax.BaseTypeDecimal:
// Get the scale value.
scale, err = strconv.ParseInt(col.Type.Scale.Value, 10, 64)
if err != nil {
@ -201,27 +202,27 @@ func (p *ExecutionPlanner) compileColumn(col *parser.ColumnDefinition) (*createT
}
column.fos = append(column.fos, pilosa.OptFieldTypeDecimal(scale, min, max))
case parser.FieldTypeID:
case dax.BaseTypeID:
column.fos = append(column.fos, pilosa.OptFieldTypeMutex(cacheType, cacheSize))
case parser.FieldTypeIDSet:
case dax.BaseTypeIDSet:
if timeQuantum != "" {
column.fos = append(column.fos, pilosa.OptFieldTypeTime(timeQuantum, ttl))
} else {
column.fos = append(column.fos, pilosa.OptFieldTypeSet(cacheType, cacheSize))
}
case parser.FieldTypeInt:
case dax.BaseTypeInt:
column.fos = append(column.fos, pilosa.OptFieldTypeInt(min.ToInt64(0), max.ToInt64(0)))
case parser.FieldTypeString:
case dax.BaseTypeString:
column.fos = append(column.fos, pilosa.OptFieldTypeMutex(cacheType, cacheSize))
column.fos = append(column.fos, pilosa.OptFieldKeys())
case parser.FieldTypeStringSet:
case dax.BaseTypeStringSet:
if timeQuantum != "" {
column.fos = append(column.fos, pilosa.OptFieldTypeTime(timeQuantum, ttl))
} else {
column.fos = append(column.fos, pilosa.OptFieldTypeSet(cacheType, cacheSize))
}
column.fos = append(column.fos, pilosa.OptFieldKeys())
case parser.FieldTypeTimestamp:
case dax.BaseTypeTimestamp:
column.fos = append(column.fos, pilosa.OptFieldTypeTimestamp(epoch, timeUnit))
}
return column, nil
@ -246,7 +247,7 @@ func (p *ExecutionPlanner) analyzeCreateTableStatement(stmt *parser.CreateTableS
if strings.ToLower(columnName) == "_id" {
//check the type
if !(strings.EqualFold(typeName, parser.FieldTypeID) || strings.EqualFold(typeName, parser.FieldTypeString)) {
if !(strings.EqualFold(typeName, dax.BaseTypeID) || strings.EqualFold(typeName, dax.BaseTypeString)) {
return sql3.NewErrTableIDColumnType(col.Type.Name.NamePos.Line, col.Type.Name.NamePos.Column)
}
//make sure we have no constraints
@ -324,7 +325,7 @@ func (p *ExecutionPlanner) analyzeColumn(typeName string, col *parser.ColumnDefi
switch c := con.(type) {
case *parser.CacheTypeConstraint:
//make sure we have a set or mutex type
if !(strings.EqualFold(typeName, parser.FieldTypeString) || strings.EqualFold(typeName, parser.FieldTypeStringSet) || strings.EqualFold(typeName, parser.FieldTypeID) || strings.EqualFold(typeName, parser.FieldTypeIDSet)) {
if !(strings.EqualFold(typeName, dax.BaseTypeString) || strings.EqualFold(typeName, dax.BaseTypeStringSet) || strings.EqualFold(typeName, dax.BaseTypeID) || strings.EqualFold(typeName, dax.BaseTypeIDSet)) {
return sql3.NewErrBadColumnConstraint(col.Name.NamePos.Line, col.Name.NamePos.Column, "CACHETYPE", typeName)
}
//check the type of the expression for SIZE
@ -362,7 +363,7 @@ func (p *ExecutionPlanner) analyzeColumn(typeName string, col *parser.ColumnDefi
case *parser.TimeUnitConstraint:
//make sure we have an timestamp type
if !strings.EqualFold(typeName, parser.FieldTypeTimestamp) {
if !strings.EqualFold(typeName, dax.BaseTypeTimestamp) {
return sql3.NewErrBadColumnConstraint(col.Name.NamePos.Line, col.Name.NamePos.Column, "TIMEUNIT", typeName)
}
//check the type of the expression
@ -384,7 +385,7 @@ func (p *ExecutionPlanner) analyzeColumn(typeName string, col *parser.ColumnDefi
case *parser.TimeQuantumConstraint:
//make sure we have a set type
if !(strings.EqualFold(typeName, parser.FieldTypeStringSet) || strings.EqualFold(typeName, parser.FieldTypeIDSet)) {
if !(strings.EqualFold(typeName, dax.BaseTypeStringSet) || strings.EqualFold(typeName, dax.BaseTypeIDSet)) {
return sql3.NewErrBadColumnConstraint(col.Name.NamePos.Line, col.Name.NamePos.Column, "TIMEQUANTUM", typeName)
}
//check the type of the expression

View file

@ -176,7 +176,7 @@ func (p *ExecutionPlanner) analyzeInsertStatement(stmt *parser.InsertStatement)
// Type check against same ordinal position in column type list.
if !typesAreAssignmentCompatible(typeNames[i], e.DataType()) {
return sql3.NewErrTypeAssignmentIncompatible(expr.Pos().Line, expr.Pos().Column, e.DataType().TypeName(), typeNames[i].TypeName())
return sql3.NewErrTypeAssignmentIncompatible(expr.Pos().Line, expr.Pos().Column, e.DataType().TypeDescription(), typeNames[i].TypeDescription())
}
tuple.Exprs[i] = e

View file

@ -4,6 +4,7 @@ package planner
import (
"context"
"strings"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/sql3"
@ -18,32 +19,61 @@ func (p *ExecutionPlanner) compileShowTablesStatement(stmt parser.Statement) (ty
return nil, errors.Wrap(err, "getting schema")
}
columns := []types.PlanExpression{&qualifiedRefPlanExpression{
tableName: "fb$tables",
columnName: "name",
columnIndex: 0,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb$tables",
columnName: "created_at",
columnIndex: 1,
dataType: parser.NewDataTypeTimestamp(),
}, &qualifiedRefPlanExpression{
tableName: "fb$tables",
columnName: "track_existence",
columnIndex: 2,
dataType: parser.NewDataTypeBool(),
}, &qualifiedRefPlanExpression{
tableName: "fb$tables",
columnName: "keys",
columnIndex: 3,
dataType: parser.NewDataTypeBool(),
}, &qualifiedRefPlanExpression{
tableName: "fb$tables",
columnName: "shard_width",
columnIndex: 4,
dataType: parser.NewDataTypeInt(),
}}
columns := []types.PlanExpression{
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "_id",
columnIndex: 0,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "name",
columnIndex: 1,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "owner",
columnIndex: 2,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "last_updated_user",
columnIndex: 3,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "created_at",
columnIndex: 4,
dataType: parser.NewDataTypeTimestamp(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "track_existence",
columnIndex: 5,
dataType: parser.NewDataTypeBool(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "keys",
columnIndex: 6,
dataType: parser.NewDataTypeBool(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "shard_width",
columnIndex: 7,
dataType: parser.NewDataTypeInt(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "description",
columnIndex: 8,
dataType: parser.NewDataTypeString(),
}}
return NewPlanOpQuery(p, NewPlanOpProjection(columns, NewPlanOpFeatureBaseTables(indexInfo)), p.sql), nil
}
@ -59,76 +89,127 @@ func (p *ExecutionPlanner) compileShowColumnsStatement(stmt *parser.ShowColumnsS
}
columns := []types.PlanExpression{&qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "name",
tableName: "fb_table_columns",
columnName: "_id",
columnIndex: 0,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{ // the SQL3 data type description
tableName: "fb$table_columns",
columnName: "type",
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "name",
columnIndex: 1,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{ // the FeatureBase 'native' data type description
tableName: "fb$table_columns",
columnName: "internal_type",
}, &qualifiedRefPlanExpression{ // the SQL3 data type description
tableName: "fb_table_columns",
columnName: "type",
columnIndex: 2,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "created_at",
}, &qualifiedRefPlanExpression{ // the FeatureBase 'native' data type description
tableName: "fb_table_columns",
columnName: "internal_type",
columnIndex: 3,
dataType: parser.NewDataTypeTimestamp(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "keys",
columnIndex: 4,
dataType: parser.NewDataTypeBool(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "cache_type",
columnIndex: 5,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "cache_size",
columnIndex: 6,
dataType: parser.NewDataTypeInt(),
tableName: "fb_table_columns",
columnName: "created_at",
columnIndex: 4,
dataType: parser.NewDataTypeTimestamp(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "scale",
tableName: "fb_table_columns",
columnName: "keys",
columnIndex: 5,
dataType: parser.NewDataTypeBool(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "cache_type",
columnIndex: 6,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "cache_size",
columnIndex: 7,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "min",
tableName: "fb_table_columns",
columnName: "scale",
columnIndex: 8,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "max",
tableName: "fb_table_columns",
columnName: "min",
columnIndex: 9,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "timeunit",
tableName: "fb_table_columns",
columnName: "max",
columnIndex: 10,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "epoch",
columnIndex: 11,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "timequantum",
columnIndex: 12,
tableName: "fb_table_columns",
columnName: "timeunit",
columnIndex: 11,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb$table_columns",
columnName: "ttl",
tableName: "fb_table_columns",
columnName: "epoch",
columnIndex: 12,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "timequantum",
columnIndex: 13,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "ttl",
columnIndex: 14,
dataType: parser.NewDataTypeString(),
}}
return NewPlanOpQuery(p, NewPlanOpProjection(columns, NewPlanOpFeatureBaseColumns(index)), p.sql), nil
}
func (p *ExecutionPlanner) compileShowCreateTableStatement(stmt *parser.ShowCreateTableStatement) (_ types.PlanOperator, err error) {
tableName := parser.IdentName(stmt.TableName)
_, err = p.schemaAPI.IndexInfo(context.Background(), tableName)
if err != nil {
if errors.Is(err, pilosa.ErrIndexNotFound) {
return nil, sql3.NewErrTableNotFound(stmt.TableName.NamePos.Line, stmt.TableName.NamePos.Column, tableName)
}
return nil, err
}
// get the system table
systemTable, ok := systemTables[fbTableDDL]
if !ok {
return nil, sql3.NewErrInternalf("unable to find system table fb_table_ddl")
}
// make an op for the system table
systemTableScan := NewPlanOpSystemTable(p, systemTable)
// get the columns from the schmema
columns := systemTable.schema
// get the ref name column and build projections
projections := make([]types.PlanExpression, 0)
var nameRef *qualifiedRefPlanExpression
for idx, col := range columns {
if strings.EqualFold(col.ColumnName, "name") {
nameRef = newQualifiedRefPlanExpression(col.RelationName, col.ColumnName, idx, col.Type)
}
if strings.EqualFold(col.ColumnName, "ddl") {
projections = append(projections, newQualifiedRefPlanExpression(col.RelationName, col.ColumnName, idx, col.Type))
}
}
if nameRef == nil || len(projections) == 0 {
return nil, sql3.NewErrInternalf("unable to find system table columns")
}
// make a filter espression
filterExpr := newBinOpPlanExpression(nameRef, parser.EQ, newStringLiteralPlanExpression(tableName), parser.NewDataTypeBool())
// make a filter op
filter := NewPlanOpFilter(p, filterExpr, systemTableScan)
return NewPlanOpQuery(p, NewPlanOpProjection(projections, filter), p.sql), nil
}

View file

@ -68,6 +68,8 @@ func (p *ExecutionPlanner) CompilePlan(ctx context.Context, stmt parser.Statemen
rootOperator, err = p.compileShowTablesStatement(stmt)
case *parser.ShowColumnsStatement:
rootOperator, err = p.compileShowColumnsStatement(stmt)
case *parser.ShowCreateTableStatement:
rootOperator, err = p.compileShowCreateTableStatement(stmt)
case *parser.CreateTableStatement:
rootOperator, err = p.compileCreateTableStatement(stmt)
case *parser.AlterTableStatement:
@ -96,6 +98,8 @@ func (p *ExecutionPlanner) analyzePlan(stmt parser.Statement) error {
return nil
case *parser.ShowColumnsStatement:
return nil
case *parser.ShowCreateTableStatement:
return nil
case *parser.CreateTableStatement:
return p.analyzeCreateTableStatement(stmt)
case *parser.AlterTableStatement:

View file

@ -82,7 +82,7 @@ func coerceValue(sourceType parser.ExprDataType, targetType parser.ExprDataType,
} else if tm, err := time.ParseInLocation("2006-01-02", val, time.UTC); err == nil {
return tm, nil
} else {
return nil, sql3.NewErrInvalidTypeCoercion(0, 0, val, targetType.TypeName())
return nil, sql3.NewErrInvalidTypeCoercion(0, 0, val, targetType.TypeDescription())
}
}
@ -126,7 +126,7 @@ func coerceValue(sourceType parser.ExprDataType, targetType parser.ExprDataType,
default:
return nil, sql3.NewErrInternalf("unhandled source type '%T'", sourceType)
}
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, targetType.TypeName(), sourceType.TypeName())
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, targetType.TypeDescription(), sourceType.TypeDescription())
}
// unaryOpPlanExpression is a unary op
@ -173,7 +173,7 @@ func (n *unaryOpPlanExpression) String() string {
func (n *unaryOpPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["op"] = n.op
result["rhs"] = n.rhs.Plan()
return result
@ -649,7 +649,7 @@ func (n *binOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, e
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t', '%t'", nlok, nrok)
default:
return nil, sql3.NewErrInternalf("unhandled type '%s'", coercedDataType.TypeName())
return nil, sql3.NewErrInternalf("unhandled type '%s'", coercedDataType.TypeDescription())
}
}
@ -664,7 +664,7 @@ func (n *binOpPlanExpression) String() string {
func (n *binOpPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["op"] = n.op
result["lhs"] = n.lhs.Plan()
result["rhs"] = n.rhs.Plan()
@ -735,7 +735,7 @@ func (n *rangePlanExpression) String() string {
func (n *rangePlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["lhs"] = n.lhs.Plan()
result["rhs"] = n.rhs.Plan()
return result
@ -950,7 +950,7 @@ func (n *casePlanExpression) String() string {
func (n *casePlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
if n.baseExpr != nil {
result["baseExpr"] = n.baseExpr.Plan()
}
@ -1035,7 +1035,7 @@ func (n *caseBlockPlanExpression) String() string {
func (n *caseBlockPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["condition"] = n.condition.Plan()
result["body"] = n.body.Plan()
return result
@ -1104,7 +1104,7 @@ func (n *subqueryPlanExpression) String() string {
func (n *subqueryPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["subquery"] = n.op.Plan()
return result
}
@ -1212,7 +1212,7 @@ func (n *betweenOpPlanExpression) String() string {
func (n *betweenOpPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["lhs"] = n.lhs.Plan()
result["rhs"] = n.rhs.Plan()
return result
@ -1285,13 +1285,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeInt, *parser.DataTypeID:
nl, nlok := evalLhs.(int64)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.(int64)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if nl == l {
result = true
@ -1302,13 +1302,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeBool:
nl, nlok := evalLhs.(bool)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.(bool)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if nl == l {
result = true
@ -1319,13 +1319,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeDecimal:
nl, nlok := evalLhs.(pql.Decimal)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.(pql.Decimal)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if nl.EqualTo(l) {
result = true
@ -1336,13 +1336,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeIDSet:
nl, nlok := evalLhs.([]int64)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.([]int64)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if intSetContainsAll(nl, l) {
result = true
@ -1353,13 +1353,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeString:
nl, nlok := evalLhs.(string)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.(string)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if nl == l {
result = true
@ -1370,13 +1370,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeStringSet:
nl, nlok := evalLhs.([]string)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.([]string)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if stringSetContainsAll(nl, l) {
result = true
@ -1387,13 +1387,13 @@ func (n *inOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
case *parser.DataTypeTimestamp:
nl, nlok := evalLhs.(time.Time)
if !nlok {
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert lhs expression to type '%s'", n.lhs.Type().TypeDescription())
}
for _, lm := range listMembers {
l, lok := lm.(time.Time)
if !lok {
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeName())
return nil, sql3.NewErrInternalf("unable to convert list expression to type '%s'", n.lhs.Type().TypeDescription())
}
if nl == l {
result = true
@ -1430,7 +1430,7 @@ func (n *inOpPlanExpression) String() string {
func (n *inOpPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["lhs"] = n.lhs.Plan()
result["rhs"] = n.rhs.Plan()
return result
@ -1500,7 +1500,7 @@ func (n *callPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["name"] = n.name
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
ps := make([]interface{}, 0)
for _, e := range n.args {
ps = append(ps, e.Plan())
@ -1555,7 +1555,7 @@ func (n *aliasPlanExpression) String() string {
func (n *aliasPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["aliasName"] = n.aliasName
result["expr"] = n.expr.Plan()
return result
@ -1651,7 +1651,7 @@ func (n *qualifiedRefPlanExpression) Plan() map[string]interface{} {
result["tableName"] = n.tableName
result["columnName"] = n.columnName
result["columnIndex"] = n.columnIndex
result["dataType"] = n.dataType.TypeName()
result["dataType"] = n.dataType.TypeDescription()
return result
}
@ -1711,7 +1711,7 @@ func (n *variableRefPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["name"] = n.name
result["dataType"] = n.dataType.TypeName()
result["dataType"] = n.dataType.TypeDescription()
return result
}
@ -1745,7 +1745,7 @@ func (n *nullLiteralPlanExpression) String() string {
func (n *nullLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
return result
}
@ -1783,7 +1783,7 @@ func (n *intLiteralPlanExpression) String() string {
func (n *intLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["value"] = n.value
return result
}
@ -1823,7 +1823,7 @@ func (n *floatLiteralPlanExpression) String() string {
func (n *floatLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["value"] = n.value
return result
}
@ -1862,7 +1862,7 @@ func (n *boolLiteralPlanExpression) String() string {
func (n *boolLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["value"] = n.value
return result
}
@ -1901,7 +1901,7 @@ func (n *dateLiteralPlanExpression) String() string {
func (n *dateLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["value"] = n.value
return result
}
@ -1940,7 +1940,7 @@ func (n *stringLiteralPlanExpression) String() string {
func (n *stringLiteralPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["value"] = n.value
return result
}
@ -2158,13 +2158,13 @@ func (n *castPlanExpression) Type() parser.ExprDataType {
}
func (n *castPlanExpression) String() string {
return fmt.Sprintf("cast(%s as %s)", n.lhs.String(), n.targetType.TypeName())
return fmt.Sprintf("cast(%s as %s)", n.lhs.String(), n.targetType.TypeDescription())
}
func (n *castPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["lhs"] = n.lhs.Plan()
return result
}
@ -2346,7 +2346,7 @@ func (n *exprTupleLiteralPlanExpression) Evaluate(currentRow []interface{}) (int
// if it is a string, do a coercion
if val, ok := timestampEval.(string); ok {
if tm, err := timestampFromString(val); err != nil {
return nil, sql3.NewErrInvalidTypeCoercion(0, 0, val, n.members[0].Type().TypeName())
return nil, sql3.NewErrInvalidTypeCoercion(0, 0, val, n.members[0].Type().TypeDescription())
} else {
timestampEval = tm
}

View file

@ -68,7 +68,7 @@ func TestExpressions(t *testing.T) {
assert.Equal(t, slop.String(), "'foo'")
ctop := newCastPlanExpression(newIntLiteralPlanExpression(10), parser.NewDataTypeString())
assert.Equal(t, ctop.String(), "cast(10 as STRING)")
assert.Equal(t, ctop.String(), "cast(10 as string)")
elop := newExprListExpression([]types.PlanExpression{newStringLiteralPlanExpression("foo"), newStringLiteralPlanExpression("bar")})
assert.Equal(t, elop.String(), "('foo', 'bar')")

View file

@ -126,7 +126,7 @@ func (n *countPlanExpression) String() string {
func (n *countPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -194,7 +194,7 @@ func (n *countDistinctPlanExpression) String() string {
func (n *countDistinctPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -327,7 +327,7 @@ func (n *sumPlanExpression) String() string {
func (n *sumPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -500,7 +500,7 @@ func (n *avgPlanExpression) String() string {
func (n *avgPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -641,7 +641,7 @@ func (n *minPlanExpression) String() string {
func (n *minPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -783,7 +783,7 @@ func (n *maxPlanExpression) String() string {
func (n *maxPlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
return result
}
@ -855,7 +855,7 @@ func (n *percentilePlanExpression) String() string {
func (n *percentilePlanExpression) Plan() map[string]interface{} {
result := make(map[string]interface{})
result["_expr"] = fmt.Sprintf("%T", n)
result["dataType"] = n.Type().TypeName()
result["dataType"] = n.Type().TypeDescription()
result["arg"] = n.arg.Plan()
result["ntharg"] = n.nthArg.Plan()
return result

View file

@ -279,14 +279,14 @@ func (p *ExecutionPlanner) analyzeExpression(expr parser.Expr, scope parser.Stat
//now check all the other blocks to make sure that each body is assignment compatible with that type
for _, blk := range e.Blocks {
if !typesAreAssignmentCompatible(caseType, blk.Body.DataType()) {
return nil, sql3.NewErrTypeAssignmentIncompatible(blk.Body.Pos().Line, blk.Body.Pos().Column, caseType.TypeName(), blk.Body.DataType().TypeName())
return nil, sql3.NewErrTypeAssignmentIncompatible(blk.Body.Pos().Line, blk.Body.Pos().Column, caseType.TypeDescription(), blk.Body.DataType().TypeDescription())
}
}
//if there is an else check that too
if e.ElseExpr != nil {
if !typesAreAssignmentCompatible(caseType, e.ElseExpr.DataType()) {
return nil, sql3.NewErrTypeAssignmentIncompatible(e.ElseExpr.Pos().Line, e.ElseExpr.Pos().Column, caseType.TypeName(), e.ElseExpr.DataType().TypeName())
return nil, sql3.NewErrTypeAssignmentIncompatible(e.ElseExpr.Pos().Line, e.ElseExpr.Pos().Column, caseType.TypeDescription(), e.ElseExpr.DataType().TypeDescription())
}
}
@ -720,7 +720,7 @@ func (p *ExecutionPlanner) analyzeRangeExpression(expr *parser.Range, scope pars
return nil, sql3.NewErrTypeCannotBeUsedAsRangeSubscript(expr.Y.Pos().Line, expr.Y.Pos().Column, expr.Y.DataType().TypeDescription())
}
if !typesOfRangeBoundsAreTheSame(expr.X.DataType(), expr.Y.DataType()) {
return nil, sql3.NewErrIncompatibleTypesForRangeSubscripts(expr.Pos().Line, expr.Pos().Column, expr.X.DataType().TypeName(), expr.Y.DataType().TypeName())
return nil, sql3.NewErrIncompatibleTypesForRangeSubscripts(expr.Pos().Line, expr.Pos().Column, expr.X.DataType().TypeDescription(), expr.Y.DataType().TypeDescription())
}
expr.ResultDataType = parser.NewDataTypeRange(expr.X.DataType())

View file

@ -130,7 +130,7 @@ func (p *ExecutionPlanner) analyzeCallExpression(call *parser.Call, scope parser
//second column is the nth value
targetType := parser.NewDataTypeDecimal(4)
if !typesAreAssignmentCompatible(targetType, call.Args[1].DataType()) {
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[1].Pos().Line, call.Args[1].Pos().Column, targetType.TypeName(), call.Args[1].DataType().TypeName())
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[1].Pos().Line, call.Args[1].Pos().Column, targetType.TypeDescription(), call.Args[1].DataType().TypeDescription())
}
//make sure it's literal

View file

@ -225,7 +225,7 @@ func (p *ExecutionPlanner) generatePQLCallFromBinaryExpr(ctx context.Context, ex
if strings.EqualFold(lhs.columnName, "_id") {
return nil, sql3.NewErrInvalidColumnInFilterExpression(0, 0, "_id", "is/is not null")
}
return nil, sql3.NewErrInvalidTypeInFilterExpression(0, 0, typ.TypeName(), "is/is not null")
return nil, sql3.NewErrInvalidTypeInFilterExpression(0, 0, typ.TypeDescription(), "is/is not null")
case *parser.DataTypeInt, *parser.DataTypeDecimal, *parser.DataTypeTimestamp:
return &pql.Call{
@ -239,7 +239,7 @@ func (p *ExecutionPlanner) generatePQLCallFromBinaryExpr(ctx context.Context, ex
}, nil
default:
return nil, sql3.NewErrInvalidTypeInFilterExpression(0, 0, typ.TypeName(), "is/is not null")
return nil, sql3.NewErrInvalidTypeInFilterExpression(0, 0, typ.TypeDescription(), "is/is not null")
}
case parser.BETWEEN, parser.NOTBETWEEN:

View file

@ -7,6 +7,7 @@ import (
"strings"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/dax"
"github.com/molecula/featurebase/v3/sql3"
"github.com/molecula/featurebase/v3/sql3/parser"
)
@ -75,33 +76,33 @@ func fieldSQLDataType(f *pilosa.FieldInfo) parser.ExprDataType {
// resolves type names to type representations
func dataTypeFromParserType(typ *parser.Type) (parser.ExprDataType, error) {
typeName := parser.IdentName(typ.Name)
switch strings.ToUpper(typeName) {
case parser.FieldTypeBool:
switch strings.ToLower(typeName) {
case dax.BaseTypeBool:
return parser.NewDataTypeBool(), nil
case parser.FieldTypeDecimal:
case dax.BaseTypeDecimal:
scale, err := strconv.Atoi(typ.Scale.Value)
if err != nil {
return nil, err
}
return parser.NewDataTypeDecimal(int64(scale)), nil
case parser.FieldTypeID:
case dax.BaseTypeID:
return parser.NewDataTypeID(), nil
case parser.FieldTypeIDSet:
case dax.BaseTypeIDSet:
return parser.NewDataTypeIDSet(), nil
case parser.FieldTypeInt:
case dax.BaseTypeInt:
return parser.NewDataTypeInt(), nil
case parser.FieldTypeString:
case dax.BaseTypeString:
return parser.NewDataTypeString(), nil
case parser.FieldTypeStringSet:
case dax.BaseTypeStringSet:
return parser.NewDataTypeStringSet(), nil
case parser.FieldTypeTimestamp:
case dax.BaseTypeTimestamp:
return parser.NewDataTypeTimestamp(), nil
default:
@ -603,7 +604,7 @@ func typesCoercedForArithmeticOperator(testTypeL parser.ExprDataType, testTypeR
}
}
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, testTypeL.TypeName(), testTypeR.TypeName())
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, testTypeL.TypeDescription(), testTypeR.TypeDescription())
}
// returns the target type given two operand types for a bitwise operation (or an error)
@ -635,7 +636,7 @@ func typesCoercedForBitwiseOperator(testTypeL parser.ExprDataType, testTypeR par
return parser.NewDataTypeDecimal(rhsType.Scale), nil
}
}
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, testTypeL.TypeName(), testTypeR.TypeName())
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Column, testTypeL.TypeDescription(), testTypeR.TypeDescription())
}
// returns the target type given two operand types type coercion operation (or an error)
@ -709,7 +710,7 @@ func typeCoerceType(testTypeL parser.ExprDataType, testTypeR parser.ExprDataType
default:
return nil, sql3.NewErrInternalf("unhandled lhs type '%t'", testTypeL)
}
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Line, testTypeL.TypeName(), testTypeR.TypeName())
return nil, sql3.NewErrTypeMismatch(atPos.Line, atPos.Line, testTypeL.TypeDescription(), testTypeR.TypeDescription())
}
// returns true if source type can be cast to target type

View file

@ -28,13 +28,13 @@ func (p *ExecutionPlanner) analyzeFunctionDatePart(call *parser.Call, scope pars
// interval
intervalType := parser.NewDataTypeString()
if !typesAreAssignmentCompatible(intervalType, call.Args[0].DataType()) {
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[0].Pos().Line, call.Args[0].Pos().Column, call.Args[0].DataType().TypeName(), intervalType.TypeName())
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[0].Pos().Line, call.Args[0].Pos().Column, call.Args[0].DataType().TypeDescription(), intervalType.TypeDescription())
}
// date
dateType := parser.NewDataTypeTimestamp()
if !typesAreAssignmentCompatible(dateType, call.Args[1].DataType()) {
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[1].Pos().Line, call.Args[1].Pos().Column, call.Args[1].DataType().TypeName(), dateType.TypeName())
return nil, sql3.NewErrParameterTypeMistmatch(call.Args[1].Pos().Line, call.Args[1].Pos().Column, call.Args[1].DataType().TypeDescription(), dateType.TypeDescription())
}
//return int

View file

@ -76,7 +76,7 @@ func (p *PlanOpBulkInsert) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc
result["tableName"] = p.tableName
@ -99,7 +99,7 @@ func (p *PlanOpBulkInsert) Plan() map[string]interface{} {
for _, m := range p.options.mapExpressions {
mapItem := make(map[string]interface{})
options["name"] = m.name
options["type"] = m.colType.TypeName()
options["type"] = m.colType.TypeDescription()
options["expr"] = m.expr.Plan()
mapList = append(mapList, mapItem)
}
@ -274,15 +274,15 @@ func (i *bulkInsertSourceCSVRowIter) Next(ctx context.Context) (types.Row, error
case *parser.DataTypeID, *parser.DataTypeInt:
intVal, err := strconv.ParseInt(evalValue, 10, 64)
if err != nil {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
}
result[idx] = intVal
case *parser.DataTypeIDSet:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
case *parser.DataTypeStringSet:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
case *parser.DataTypeTimestamp:
intVal, err := strconv.ParseInt(evalValue, 10, 64)
@ -294,7 +294,7 @@ func (i *bulkInsertSourceCSVRowIter) Next(ctx context.Context) (types.Row, error
} else if tm, err := time.ParseInLocation("2006-01-02", evalValue, time.UTC); err == nil {
result[idx] = tm
} else {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
}
}
result[idx] = time.UnixMilli(intVal).UTC()
@ -305,14 +305,14 @@ func (i *bulkInsertSourceCSVRowIter) Next(ctx context.Context) (types.Row, error
case *parser.DataTypeBool:
bval, err := strconv.ParseInt(evalValue, 10, 64)
if err != nil {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
}
result[idx] = bval
case *parser.DataTypeDecimal:
dval, err := pql.ParseDecimal(evalValue)
if err != nil {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, evalValue, mapColumn.colType.TypeDescription())
}
result[idx] = dval
@ -494,24 +494,24 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
if v == float64(int64(v)) {
result[idx] = int64(v)
} else {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
case []interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case string:
intVal, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
result[idx] = intVal
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -520,31 +520,31 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
case *parser.DataTypeIDSet:
switch v := evalValue.(type) {
case float64:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case []interface{}:
setValue := make([]int64, 0)
for _, i := range v {
f, ok := i.(float64)
if !ok {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
if f == float64(int64(f)) {
setValue = append(setValue, int64(f))
} else {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
}
result[idx] = setValue
case string:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -553,27 +553,27 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
case *parser.DataTypeStringSet:
switch v := evalValue.(type) {
case float64:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case []interface{}:
setValue := make([]string, 0)
for _, i := range v {
f, ok := i.(string)
if !ok {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
setValue = append(setValue, f)
}
result[idx] = setValue
case string:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -586,11 +586,11 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
if v == float64(int64(v)) {
result[idx] = time.UnixMilli(int64(v)).UTC()
} else {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
case []interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case string:
if tm, err := time.ParseInLocation(time.RFC3339Nano, v, time.UTC); err == nil {
@ -600,14 +600,14 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
} else if tm, err := time.ParseInLocation("2006-01-02", v, time.UTC); err == nil {
result[idx] = tm
} else {
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
}
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -616,19 +616,19 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
case *parser.DataTypeString:
switch v := evalValue.(type) {
case float64:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case []interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case string:
result[idx] = v
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -637,19 +637,19 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
case *parser.DataTypeBool:
switch v := evalValue.(type) {
case float64:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case []interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case string:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case bool:
result[idx] = v
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)
@ -661,16 +661,16 @@ func (i *bulkInsertSourceNDJsonRowIter) Next(ctx context.Context) (types.Row, er
result[idx] = pql.FromFloat64(v)
case []interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case string:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case bool:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
case interface{}:
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeName())
return nil, sql3.NewErrTypeConversionOnMap(0, 0, v, mapColumn.colType.TypeDescription())
default:
return nil, sql3.NewErrInternalf("unhandled type '%T'", evalValue)

View file

@ -39,7 +39,7 @@ func (p *PlanOpCreateTable) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
result["name"] = p.tableName

View file

@ -30,7 +30,7 @@ func (p *PlanOpDropTable) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
result["tableName"] = p.index.Name

View file

@ -31,7 +31,7 @@ func (p *PlanOpFeatureBaseColumns) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
return result
@ -52,72 +52,77 @@ func (p *PlanOpFeatureBaseColumns) Warnings() []string {
func (p *PlanOpFeatureBaseColumns) Schema() types.Schema {
return types.Schema{
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "_id",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb_table_columns",
ColumnName: "name",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "type",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "internal_type",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "created_at",
Type: parser.NewDataTypeTimestamp(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "keys",
Type: parser.NewDataTypeBool(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "cache_type",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "cache_size",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "scale",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "min",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "max",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "timeunit",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "epoch",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "timequantum",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$table_columns",
RelationName: "fb_table_columns",
ColumnName: "ttl",
Type: parser.NewDataTypeInt(),
},
@ -153,7 +158,8 @@ func (i *showColumnsRowIter) Next(ctx context.Context) (types.Row, error) {
row := []interface{}{
fields[i.rowIndex].Name,
fieldSQLDataType(fields[i.rowIndex]).TypeName(),
fields[i.rowIndex].Name,
fieldSQLDataType(fields[i.rowIndex]).TypeDescription(),
fields[i.rowIndex].Options.Type,
tm.Format(time.RFC3339),
fields[i.rowIndex].Options.Keys,

View file

@ -31,7 +31,7 @@ func (p *PlanOpFeatureBaseTables) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
return result
@ -52,30 +52,50 @@ func (p *PlanOpFeatureBaseTables) Warnings() []string {
func (p *PlanOpFeatureBaseTables) Schema() types.Schema {
return types.Schema{
&types.PlannerColumn{
RelationName: "fb$tables",
RelationName: "fb_tables",
ColumnName: "_id",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb_tables",
ColumnName: "name",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb$tables",
RelationName: "fb_tables",
ColumnName: "owner",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb_tables",
ColumnName: "last_updated_user",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: "fb_tables",
ColumnName: "created_at",
Type: parser.NewDataTypeTimestamp(),
},
&types.PlannerColumn{
RelationName: "fb$tables",
RelationName: "fb_tables",
ColumnName: "track_existence",
Type: parser.NewDataTypeBool(),
},
&types.PlannerColumn{
RelationName: "fb$tables",
RelationName: "fb_tables",
ColumnName: "keys",
Type: parser.NewDataTypeBool(),
},
&types.PlannerColumn{
RelationName: "fb$tables",
RelationName: "fb_tables",
ColumnName: "shard_width",
Type: parser.NewDataTypeInt(),
},
&types.PlannerColumn{
RelationName: "fb_tables",
ColumnName: "description",
Type: parser.NewDataTypeString(),
},
}
}
@ -105,10 +125,14 @@ func (i *showTablesRowIter) Next(ctx context.Context) (types.Row, error) {
tm := time.Unix(0, i.indexInfo[i.rowIndex].CreatedAt)
row := []interface{}{
i.indexInfo[i.rowIndex].Name,
i.indexInfo[i.rowIndex].Name,
i.indexInfo[i.rowIndex].Owner,
i.indexInfo[i.rowIndex].LastUpdateUser,
tm.Format(time.RFC3339),
i.indexInfo[i.rowIndex].Options.TrackExistence,
i.indexInfo[i.rowIndex].Options.Keys,
i.indexInfo[i.rowIndex].ShardWidth,
i.indexInfo[i.rowIndex].Options.Description,
}
i.rowIndex += 1
return row, nil

View file

@ -58,7 +58,7 @@ func (p *PlanOpFilter) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
result["predicate"] = p.Predicate.Plan()

View file

@ -102,7 +102,7 @@ func (p *PlanOpGroupBy) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc
result["child"] = p.ChildOp.Plan()

View file

@ -39,7 +39,7 @@ func (p *PlanOpInsert) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc
result["tableName"] = p.tableName

View file

@ -33,7 +33,7 @@ func (p *PlanOpNestedLoops) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
result["top"] = p.top.Plan()

View file

@ -42,7 +42,7 @@ func (p *PlanOpNullTable) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
return result

View file

@ -88,7 +88,7 @@ func (n *PlanOpOrderBy) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", n)
sc := make([]string, 0)
for _, e := range n.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc
@ -97,7 +97,7 @@ func (n *PlanOpOrderBy) Plan() map[string]interface{} {
for _, e := range n.orderByFields {
ps = append(ps, &map[string]interface{}{
"index": e.Index,
"exprType": e.ExprType.TypeName(),
"exprType": e.ExprType.TypeDescription(),
"order": e.Order,
"nullOrdering": e.NullOrdering,
})

View file

@ -38,7 +38,7 @@ func (p *PlanOpPQLAggregate) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
result["tableName"] = p.tableName

View file

@ -40,7 +40,7 @@ func (p *PlanOpPQLGroupBy) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc
result["tableName"] = p.tableName

View file

@ -29,7 +29,7 @@ func (p *PlanOpPQLMultiAggregate) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -35,7 +35,7 @@ func (p *PlanOpPQLMultiGroupBy) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -39,7 +39,7 @@ func (p *PlanOpPQLTableScan) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -63,7 +63,7 @@ func (p *PlanOpProjection) Plan() map[string]interface{} {
result["__op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["__schema"] = sc

View file

@ -77,7 +77,7 @@ func (p *PlanOpQuery) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -55,7 +55,7 @@ func (p *PlanOpRelAlias) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -45,7 +45,7 @@ func (p *PlanOpSubquery) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -3,38 +3,25 @@
package planner
import (
"bytes"
"context"
"fmt"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/pql"
"github.com/molecula/featurebase/v3/sql3"
"github.com/molecula/featurebase/v3/sql3/parser"
"github.com/molecula/featurebase/v3/sql3/planner/types"
)
//fb_exec_requests
// session
// user
// start_time
// end_time
// status
// plan
// wait_type
// wait_time
// wait_resource
// cpu_time
// elapsed_time
// reads
// writes
// logical_reads
// row_count
// exclude this file from SonarCloud dupe eval
const (
fbClusterInfo = "fb_cluster_info"
fbClusterNodes = "fb_cluster_nodes"
fbExecRequests = "fb_exec_requests"
fbTableDDL = "fb_table_ddl"
)
type systemTable struct {
@ -209,6 +196,27 @@ var systemTables = map[string]*systemTable{
},
},
},
fbTableDDL: {
name: fbTableDDL,
schema: types.Schema{
&types.PlannerColumn{
RelationName: fbTableDDL,
ColumnName: "id",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: fbTableDDL,
ColumnName: "name",
Type: parser.NewDataTypeString(),
},
&types.PlannerColumn{
RelationName: fbTableDDL,
ColumnName: "ddl",
Type: parser.NewDataTypeString(),
},
},
},
}
// PlanOpSystemTable handles system tables
@ -231,7 +239,7 @@ func (p *PlanOpSystemTable) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
ps := make([]string, 0)
for _, e := range p.Schema() {
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
ps = append(ps, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = ps
return result
@ -271,6 +279,10 @@ func (p *PlanOpSystemTable) Iterator(ctx context.Context, row types.Row) (types.
return &fbExecRequestsRowIter{
planner: p.planner,
}, nil
case fbTableDDL:
return &fbTableDDLRowIter{
planner: p.planner,
}, nil
default:
return nil, sql3.NewErrInternalf("unable to find system table '%s'", p.table.name)
}
@ -379,3 +391,136 @@ func (i *fbExecRequestsRowIter) Next(ctx context.Context) (types.Row, error) {
}
return nil, types.ErrNoMoreRows
}
type fbTableDDLRow struct {
id string
name string
ddl string
}
type fbTableDDLRowIter struct {
planner *ExecutionPlanner
result []*fbTableDDLRow
}
var _ types.RowIterator = (*fbTableDDLRowIter)(nil)
func (i *fbTableDDLRowIter) Next(ctx context.Context) (types.Row, error) {
if i.result == nil {
schema, err := i.planner.schemaAPI.Schema(ctx, false)
if err != nil {
return nil, err
}
i.result = make([]*fbTableDDLRow, len(schema))
for idx, table := range schema {
index, err := i.planner.schemaAPI.IndexInfo(context.Background(), table.Name)
if err != nil {
return nil, err
}
// build the ddl for this table
var buf bytes.Buffer
buf.WriteString("create table ")
fmt.Fprintf(&buf, "%s", index.Name)
buf.WriteString(" (")
for idx, col := range index.Fields {
if idx > 0 {
buf.WriteString(", ")
}
fmt.Fprintf(&buf, "%s", col.Name)
dataType := fieldSQLDataType(col)
fmt.Fprintf(&buf, " %s", dataType.TypeDescription())
switch dt := dataType.(type) {
case *parser.DataTypeID, *parser.DataTypeString:
if col.Options.CacheType != pilosa.DefaultCacheType && len(col.Options.CacheType) > 0 {
fmt.Fprintf(&buf, " cachetype %s", col.Options.CacheType)
}
if col.Options.CacheSize != pilosa.DefaultCacheSize && col.Options.CacheSize > 0 {
fmt.Fprintf(&buf, " cachesize %d", col.Options.CacheSize)
}
case *parser.DataTypeIDSet, *parser.DataTypeStringSet:
if col.Options.CacheType != pilosa.DefaultCacheType && len(col.Options.CacheType) > 0 {
fmt.Fprintf(&buf, " cachetype %s", col.Options.CacheType)
}
if col.Options.CacheSize != pilosa.DefaultCacheSize && col.Options.CacheSize > 0 {
fmt.Fprintf(&buf, " cachesize %d", col.Options.CacheSize)
}
case *parser.DataTypeIDSetQuantum, *parser.DataTypeStringSetQuantum:
if col.Options.CacheType != pilosa.DefaultCacheType && len(col.Options.CacheType) > 0 {
fmt.Fprintf(&buf, " cachetype %s", col.Options.CacheType)
}
if col.Options.CacheSize != pilosa.DefaultCacheSize && col.Options.CacheSize > 0 {
fmt.Fprintf(&buf, " cachesize %d", col.Options.CacheSize)
}
if !col.Options.TimeQuantum.IsEmpty() {
fmt.Fprintf(&buf, " timequantum '%s'", col.Options.TimeQuantum)
}
if col.Options.TTL > 0 {
fmt.Fprintf(&buf, " ttl '%s'", col.Options.TTL.String())
}
case *parser.DataTypeInt:
minValue, maxValue := pql.MinMax(0)
min := col.Options.Min
if !min.EqualTo(minValue) {
fmt.Fprintf(&buf, " min %d", min.ToInt64(0))
}
max := col.Options.Max
if !max.EqualTo(maxValue) {
fmt.Fprintf(&buf, " max %d", max.ToInt64(0))
}
case *parser.DataTypeDecimal:
minValue, maxValue := pql.MinMax(dt.Scale)
min := col.Options.Min
if !min.EqualTo(minValue) {
fmt.Fprintf(&buf, " min %v", min)
}
max := col.Options.Max
if !max.EqualTo(maxValue) {
fmt.Fprintf(&buf, " max %v", max)
}
case *parser.DataTypeTimestamp:
if len(col.Options.TimeUnit) > 0 {
fmt.Fprintf(&buf, " timeunit '%s'", col.Options.TimeUnit)
}
// TODO(pok) how do we get epoch out of col?
}
}
buf.WriteString(");")
ddl := buf.String()
i.result[idx] = &fbTableDDLRow{
id: table.Name,
name: table.Name,
ddl: ddl,
}
}
}
if len(i.result) > 0 {
n := i.result[0]
row := []interface{}{
n.id,
n.name,
n.ddl,
}
// Move to next result element.
i.result = i.result[1:]
return row, nil
}
return nil, types.ErrNoMoreRows
}

View file

@ -59,7 +59,7 @@ func (p *PlanOpTableValuedFunction) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -55,7 +55,7 @@ func (p *PlanOpTop) Plan() map[string]interface{} {
result["_op"] = fmt.Sprintf("%T", p)
sc := make([]string, 0)
for _, e := range p.Schema() {
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeName()))
sc = append(sc, fmt.Sprintf("'%s', '%s', '%s'", e.ColumnName, e.RelationName, e.Type.TypeDescription()))
}
result["_schema"] = sc

View file

@ -158,16 +158,42 @@ func TestPlanner_Show(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if len(results) != 5 {
if len(results) != 6 {
t.Fatal(fmt.Errorf("unexpected result set length"))
}
if diff := cmp.Diff([]*pilosa.WireQueryField{
wireQueryFieldString("_id"),
wireQueryFieldString("name"),
wireQueryFieldString("owner"),
wireQueryFieldString("last_updated_user"),
wireQueryFieldTimestamp("created_at"),
wireQueryFieldBool("track_existence"),
wireQueryFieldBool("keys"),
wireQueryFieldInt("shard_width"),
wireQueryFieldString("description"),
}, columns); diff != "" {
t.Fatal(diff)
}
})
t.Run("ShowCreateTable", func(t *testing.T) {
results, columns, err := sql_test.MustQueryRows(t, c.GetNode(0).Server, fmt.Sprintf(`SHOW CREATE TABLE %i`, c))
if err != nil {
t.Fatal(err)
}
if len(results) != 1 {
t.Fatal(fmt.Errorf("unexpected result set length: %d", len(results)))
}
if diff := cmp.Diff([][]interface{}{
{string("create table testplannershowi (_id id, f int min 0 max 1000, x int min 0 max 1000);")},
}, results); diff != "" {
t.Fatal(diff)
}
if diff := cmp.Diff([]*pilosa.WireQueryField{
wireQueryFieldString("ddl"),
}, columns); diff != "" {
t.Fatal(diff)
}
@ -183,6 +209,7 @@ func TestPlanner_Show(t *testing.T) {
}
if diff := cmp.Diff([]*pilosa.WireQueryField{
wireQueryFieldString("_id"),
wireQueryFieldString("name"),
wireQueryFieldString("type"),
wireQueryFieldString("internal_type"),
@ -212,6 +239,7 @@ func TestPlanner_Show(t *testing.T) {
}
if diff := cmp.Diff([]*pilosa.WireQueryField{
wireQueryFieldString("_id"),
wireQueryFieldString("name"),
wireQueryFieldString("type"),
wireQueryFieldString("internal_type"),
@ -592,6 +620,7 @@ func TestPlanner_CreateTable(t *testing.T) {
t.Fatal(err)
}
if diff := cmp.Diff([]*pilosa.WireQueryField{
wireQueryFieldString("_id"),
wireQueryFieldString("name"),
wireQueryFieldString("type"),
wireQueryFieldString("internal_type"),
@ -1426,7 +1455,7 @@ func TestPlanner_BulkInsert(t *testing.T) {
}
_, _, err = sql_test.MustQueryRows(t, c.GetNode(0).Server, fmt.Sprintf(`bulk insert into j1 (_id, a, b) map (0 id, 1 int, 2 int) from '%s' WITH FORMAT 'CSV' INPUT 'FILE';`, tmpfile.Name()))
if err == nil || !strings.Contains(err.Error(), `value '_id' cannot be converted to type 'ID'`) {
if err == nil || !strings.Contains(err.Error(), `value '_id' cannot be converted to type 'id'`) {
t.Fatalf("unexpected error: %v", err)
}

View file

@ -48,13 +48,13 @@ var betweenTests = TableTest{
SQLs: sqls(
"select b1 between true and false from between_all_types",
),
ExpErr: "type 'BOOL' cannot be used as a range subscript",
ExpErr: "type 'bool' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select d1 between 1.23 and 4.56 from between_all_types",
),
ExpErr: "type 'DECIMAL(2)' cannot be used as a range subscript",
ExpErr: "type 'decimal(2)' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -72,19 +72,19 @@ var betweenTests = TableTest{
SQLs: sqls(
"select ids1 between [100, 102] and [456, 789] from between_all_types",
),
ExpErr: "type 'IDSET' cannot be used as a range subscript",
ExpErr: "type 'idset' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select s1 between 'foo' and 'bar' from between_all_types",
),
ExpErr: "type 'STRING' cannot be used as a range subscript",
ExpErr: "type 'string' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select ss1 between ['a', 'b'] and ['c', 'd'] from between_all_types",
),
ExpErr: "type 'STRINGSET' cannot be used as a range subscript",
ExpErr: "type 'stringset' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -149,13 +149,13 @@ var notBetweenTests = TableTest{
SQLs: sqls(
"select b1 not between true and false from not_between_all_types",
),
ExpErr: "type 'BOOL' cannot be used as a range subscript",
ExpErr: "type 'bool' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select d1 not between 1.23 and 4.56 from not_between_all_types",
),
ExpErr: "type 'DECIMAL(2)' cannot be used as a range subscript",
ExpErr: "type 'decimal(2)' cannot be used as a range subscript",
},
{
SQLs: sqls(
@ -173,19 +173,19 @@ var notBetweenTests = TableTest{
SQLs: sqls(
"select ids1 not between [100, 102] and [456, 789] from not_between_all_types",
),
ExpErr: "type 'IDSET' cannot be used as a range subscript",
ExpErr: "type 'idset' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select s1 not between 'foo' and 'bar' from not_between_all_types",
),
ExpErr: "type 'STRING' cannot be used as a range subscript",
ExpErr: "type 'string' cannot be used as a range subscript",
},
{
SQLs: sqls(
"select ss1 not between ['a', 'b'] and ['c', 'd'] from not_between_all_types",
),
ExpErr: "type 'STRINGSET' cannot be used as a range subscript",
ExpErr: "type 'stringset' cannot be used as a range subscript",
},
{
SQLs: sqls(

File diff suppressed because it is too large Load diff

View file

@ -81,7 +81,7 @@ var castIntLiteral = TableTest{
SQLs: sqls(
"select cast(1 as idset)",
),
ExpErr: "'INT' cannot be cast to 'IDSET'",
ExpErr: "'int' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -99,7 +99,7 @@ var castIntLiteral = TableTest{
SQLs: sqls(
"select cast(1 as stringset)",
),
ExpErr: "'INT' cannot be cast to 'STRINGSET'",
ExpErr: "'int' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
@ -191,7 +191,7 @@ var castInt = TableTest{
SQLs: sqls(
"select _id, cast(i1 as idset) from cast_int",
),
ExpErr: "'INT' cannot be cast to 'IDSET'",
ExpErr: "'int' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -210,7 +210,7 @@ var castInt = TableTest{
SQLs: sqls(
"select _id, cast(i1 as stringset) from cast_int",
),
ExpErr: "'INT' cannot be cast to 'STRINGSET'",
ExpErr: "'int' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
@ -277,19 +277,19 @@ var castBool = TableTest{
SQLs: sqls(
"select _id, cast(b1 as decimal(2)) from cast_bool",
),
ExpErr: "'BOOL' cannot be cast to 'DECIMAL(2)'",
ExpErr: "'bool' cannot be cast to 'decimal(2)'",
},
{
SQLs: sqls(
"select _id, cast(b1 as id) from cast_bool",
),
ExpErr: "'BOOL' cannot be cast to 'ID'",
ExpErr: "'bool' cannot be cast to 'id'",
},
{
SQLs: sqls(
"select _id, cast(b1 as idset) from cast_bool",
),
ExpErr: "'BOOL' cannot be cast to 'IDSET'",
ExpErr: "'bool' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -308,13 +308,13 @@ var castBool = TableTest{
SQLs: sqls(
"select _id, cast(b1 as stringset) from cast_bool",
),
ExpErr: "'BOOL' cannot be cast to 'STRINGSET'",
ExpErr: "'bool' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
"select _id, cast(b1 as timestamp) from cast_bool",
),
ExpErr: "'BOOL' cannot be cast to 'TIMESTAMP'",
ExpErr: "'bool' cannot be cast to 'timestamp'",
},
},
}
@ -342,13 +342,13 @@ var castDecimal = TableTest{
SQLs: sqls(
"select _id, cast(d1 as int) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'INT'",
ExpErr: "'decimal(2)' cannot be cast to 'int'",
},
{
SQLs: sqls(
"select _id, cast(d1 as bool) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'BOOL'",
ExpErr: "'decimal(2)' cannot be cast to 'bool'",
},
{
SQLs: sqls(
@ -367,13 +367,13 @@ var castDecimal = TableTest{
SQLs: sqls(
"select _id, cast(d1 as id) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'ID'",
ExpErr: "'decimal(2)' cannot be cast to 'id'",
},
{
SQLs: sqls(
"select _id, cast(d1 as idset) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'IDSET'",
ExpErr: "'decimal(2)' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -392,13 +392,13 @@ var castDecimal = TableTest{
SQLs: sqls(
"select _id, cast(d1 as stringset) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'STRINGSET'",
ExpErr: "'decimal(2)' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
"select _id, cast(d1 as timestamp) from cast_dec",
),
ExpErr: "'DECIMAL(2)' cannot be cast to 'TIMESTAMP'",
ExpErr: "'decimal(2)' cannot be cast to 'timestamp'",
},
},
}
@ -478,25 +478,25 @@ var castID = TableTest{
SQLs: sqls(
"select _id, cast(id1 as idset) from cast_id",
),
ExpErr: "'ID' cannot be cast to 'IDSET'",
ExpErr: "'id' cannot be cast to 'idset'",
},
{
SQLs: sqls(
"select _id, cast(id1 as string) from cast_id",
),
ExpErr: "'ID' cannot be cast to 'STRING'",
ExpErr: "'id' cannot be cast to 'string'",
},
{
SQLs: sqls(
"select _id, cast(id1 as stringset) from cast_id",
),
ExpErr: "'ID' cannot be cast to 'STRINGSET'",
ExpErr: "'id' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
"select _id, cast(id1 as timestamp) from cast_id",
),
ExpErr: "'ID' cannot be cast to 'TIMESTAMP'",
ExpErr: "'id' cannot be cast to 'timestamp'",
},
},
}
@ -524,25 +524,25 @@ var castIDSet = TableTest{
SQLs: sqls(
"select _id, cast(ids1 as int) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'INT'",
ExpErr: "'idset' cannot be cast to 'int'",
},
{
SQLs: sqls(
"select _id, cast(ids1 as bool) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'BOOL'",
ExpErr: "'idset' cannot be cast to 'bool'",
},
{
SQLs: sqls(
"select _id, cast(ids1 as decimal(2)) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'DECIMAL(2)'",
ExpErr: "'idset' cannot be cast to 'decimal(2)'",
},
{
SQLs: sqls(
"select _id, cast(ids1 as id) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'ID'",
ExpErr: "'idset' cannot be cast to 'id'",
},
{
SQLs: sqls(
@ -574,13 +574,13 @@ var castIDSet = TableTest{
SQLs: sqls(
"select _id, cast(ids1 as stringset) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'STRINGSET'",
ExpErr: "'idset' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
"select _id, cast(ids1 as timestamp) from cast_ids",
),
ExpErr: "'IDSET' cannot be cast to 'TIMESTAMP'",
ExpErr: "'idset' cannot be cast to 'timestamp'",
},
},
}
@ -608,7 +608,7 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as int) from cast_string",
),
ExpErr: "'foo' cannot be cast to 'INT'",
ExpErr: "'foo' cannot be cast to 'int'",
},
{
SQLs: sqls(
@ -627,7 +627,7 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as bool) from cast_string",
),
ExpErr: "'foo' cannot be cast to 'BOOL'",
ExpErr: "'foo' cannot be cast to 'bool'",
},
{
SQLs: sqls(
@ -646,7 +646,7 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as decimal(2)) from cast_string",
),
ExpErr: "'foo' cannot be cast to 'DECIMAL(2)'",
ExpErr: "'foo' cannot be cast to 'decimal(2)'",
},
{
SQLs: sqls(
@ -665,7 +665,7 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as id) from cast_string",
),
ExpErr: "'foo' cannot be cast to 'ID'",
ExpErr: "'foo' cannot be cast to 'id'",
},
{
SQLs: sqls(
@ -684,7 +684,7 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as idset) from cast_string",
),
ExpErr: "'STRING' cannot be cast to 'IDSET'",
ExpErr: "'string' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -703,13 +703,13 @@ var castString = TableTest{
SQLs: sqls(
"select _id, cast(s1 as stringset) from cast_string",
),
ExpErr: "'STRING' cannot be cast to 'STRINGSET'",
ExpErr: "'string' cannot be cast to 'stringset'",
},
{
SQLs: sqls(
"select _id, cast(s1 as timestamp) from cast_string",
),
ExpErr: "'foo' cannot be cast to 'TIMESTAMP'",
ExpErr: "'foo' cannot be cast to 'timestamp'",
},
{
SQLs: sqls(
@ -750,31 +750,31 @@ var castStringSet = TableTest{
SQLs: sqls(
"select _id, cast(ss1 as int) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'INT'",
ExpErr: "'stringset' cannot be cast to 'int'",
},
{
SQLs: sqls(
"select _id, cast(ss1 as bool) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'BOOL'",
ExpErr: "'stringset' cannot be cast to 'bool'",
},
{
SQLs: sqls(
"select _id, cast(ss1 as decimal(2)) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'DECIMAL(2)'",
ExpErr: "'stringset' cannot be cast to 'decimal(2)'",
},
{
SQLs: sqls(
"select _id, cast(ss1 as id) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'ID'",
ExpErr: "'stringset' cannot be cast to 'id'",
},
{
SQLs: sqls(
"select _id, cast(ss1 as idset) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'IDSET'",
ExpErr: "'stringset' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -807,7 +807,7 @@ var castStringSet = TableTest{
SQLs: sqls(
"select _id, cast(ss1 as timestamp) from cast_ss",
),
ExpErr: "'STRINGSET' cannot be cast to 'TIMESTAMP'",
ExpErr: "'stringset' cannot be cast to 'timestamp'",
},
},
}
@ -848,25 +848,25 @@ var castTimestamp = TableTest{
SQLs: sqls(
"select _id, cast(t1 as bool) from cast_ts",
),
ExpErr: "'TIMESTAMP' cannot be cast to 'BOOL'",
ExpErr: "'timestamp' cannot be cast to 'bool'",
},
{
SQLs: sqls(
"select _id, cast(t1 as decimal(2)) from cast_ts",
),
ExpErr: "'TIMESTAMP' cannot be cast to 'DECIMAL(2)'",
ExpErr: "'timestamp' cannot be cast to 'decimal(2)'",
},
{
SQLs: sqls(
"select _id, cast(t1 as id) from cast_ts",
),
ExpErr: "'TIMESTAMP' cannot be cast to 'ID'",
ExpErr: "'timestamp' cannot be cast to 'id'",
},
{
SQLs: sqls(
"select _id, cast(t1 as idset) from cast_ts",
),
ExpErr: "'TIMESTAMP' cannot be cast to 'IDSET'",
ExpErr: "'timestamp' cannot be cast to 'idset'",
},
{
SQLs: sqls(
@ -885,7 +885,7 @@ var castTimestamp = TableTest{
SQLs: sqls(
"select _id, cast(t1 as stringset) from cast_ts",
),
ExpErr: "'TIMESTAMP' cannot be cast to 'STRINGSET'",
ExpErr: "'timestamp' cannot be cast to 'stringset'",
},
{
SQLs: sqls(

View file

@ -26,13 +26,13 @@ var datePartTests = TableTest{
SQLs: sqls(
"select datepart(1, 2)",
),
ExpErr: "an expression of type 'INT' cannot be passed to a parameter of type 'STRING'",
ExpErr: "an expression of type 'int' cannot be passed to a parameter of type 'string'",
},
{
SQLs: sqls(
"select datepart('1', 2)",
),
ExpErr: "an expression of type 'INT' cannot be passed to a parameter of type 'TIMESTAMP'",
ExpErr: "an expression of type 'int' cannot be passed to a parameter of type 'timestamp'",
},
{
SQLs: sqls(

View file

@ -115,14 +115,14 @@ var insertTest = TableTest{
SQLs: sqls(
"insert into testinsert (_id, a, event) values (4, 40, [101, 150])",
),
ExpErr: "an expression of type 'IDSET' cannot be assigned to type 'STRINGSET'",
ExpErr: "an expression of type 'idset' cannot be assigned to type 'stringset'",
},
{
// InsertSetsTypeError2
SQLs: sqls(
"insert into testinsert (_id, a, ievent) values (4, 40, ['POST', 'GET'])",
),
ExpErr: "an expression of type 'STRINGSET' cannot be assigned to type 'IDSET'",
ExpErr: "an expression of type 'stringset' cannot be assigned to type 'idset'",
},
},
}

View file

@ -24,37 +24,37 @@ var likeTests = TableTest{
SQLs: sqls(
"select _id like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'ID'",
ExpErr: "operator 'LIKE' incompatible with type 'id'",
},
{
SQLs: sqls(
"select i1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'INT'",
ExpErr: "operator 'LIKE' incompatible with type 'int'",
},
{
SQLs: sqls(
"select b1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'BOOL'",
ExpErr: "operator 'LIKE' incompatible with type 'bool'",
},
{
SQLs: sqls(
"select d1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'DECIMAL(2)'",
ExpErr: "operator 'LIKE' incompatible with type 'decimal(2)'",
},
{
SQLs: sqls(
"select id1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'ID'",
ExpErr: "operator 'LIKE' incompatible with type 'id'",
},
{
SQLs: sqls(
"select ids1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'IDSET'",
ExpErr: "operator 'LIKE' incompatible with type 'idset'",
},
{
SQLs: sqls(
@ -72,13 +72,13 @@ var likeTests = TableTest{
SQLs: sqls(
"select ss1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'STRINGSET'",
ExpErr: "operator 'LIKE' incompatible with type 'stringset'",
},
{
SQLs: sqls(
"select t1 like '%f_' from like_all_types",
),
ExpErr: "operator 'LIKE' incompatible with type 'TIMESTAMP'",
ExpErr: "operator 'LIKE' incompatible with type 'timestamp'",
},
},
}
@ -107,37 +107,37 @@ var notLikeTests = TableTest{
SQLs: sqls(
"select _id not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'ID'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'id'",
},
{
SQLs: sqls(
"select i1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'INT'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'int'",
},
{
SQLs: sqls(
"select b1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'BOOL'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'bool'",
},
{
SQLs: sqls(
"select d1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'DECIMAL(2)'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'decimal(2)'",
},
{
SQLs: sqls(
"select id1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'ID'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'id'",
},
{
SQLs: sqls(
"select ids1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'IDSET'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'idset'",
},
{
SQLs: sqls(
@ -155,13 +155,13 @@ var notLikeTests = TableTest{
SQLs: sqls(
"select ss1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'STRINGSET'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'stringset'",
},
{
SQLs: sqls(
"select t1 not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'TIMESTAMP'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'timestamp'",
},
},
}

View file

@ -338,13 +338,13 @@ var nullFilterTests = TableTest{
SQLs: sqls(
"select _id from null_filter_all_types where b1 is null",
),
ExpErr: "unsupported type 'BOOL' for is/is not null filter expression",
ExpErr: "unsupported type 'bool' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where b1 is not null",
),
ExpErr: "unsupported type 'BOOL' for is/is not null filter expression",
ExpErr: "unsupported type 'bool' for is/is not null filter expression",
},
{
SQLs: sqls(
@ -374,49 +374,49 @@ var nullFilterTests = TableTest{
SQLs: sqls(
"select _id from null_filter_all_types where id1 is null",
),
ExpErr: "unsupported type 'ID' for is/is not null filter expression",
ExpErr: "unsupported type 'id' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where id1 is not null",
),
ExpErr: "unsupported type 'ID' for is/is not null filter expression",
ExpErr: "unsupported type 'id' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where ids1 is null",
),
ExpErr: "unsupported type 'IDSET' for is/is not null filter expression",
ExpErr: "unsupported type 'idset' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where ids1 is not null",
),
ExpErr: "unsupported type 'IDSET' for is/is not null filter expression",
ExpErr: "unsupported type 'idset' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where s1 is null",
),
ExpErr: "unsupported type 'STRING' for is/is not null filter expression",
ExpErr: "unsupported type 'string' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where s1 is not null",
),
ExpErr: "unsupported type 'STRING' for is/is not null filter expression",
ExpErr: "unsupported type 'string' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where ss1 is null",
),
ExpErr: "unsupported type 'STRINGSET' for is/is not null filter expression",
ExpErr: "unsupported type 'stringset' for is/is not null filter expression",
},
{
SQLs: sqls(
"select _id from null_filter_all_types where ss1 is not null",
),
ExpErr: "unsupported type 'STRINGSET' for is/is not null filter expression",
ExpErr: "unsupported type 'stringset' for is/is not null filter expression",
},
{
SQLs: sqls(

View file

@ -26,14 +26,14 @@ var orderByTests = TableTest{
SQLs: sqls(
"select * from order_by_test order by a_string_set asc",
),
ExpErr: "unable to sort a column of type 'STRINGSET'",
ExpErr: "unable to sort a column of type 'stringset'",
},
{
name: "order-by-idset",
SQLs: sqls(
"select * from order_by_test order by an_id_set asc",
),
ExpErr: "unable to sort a column of type 'IDSET'",
ExpErr: "unable to sort a column of type 'idset'",
},
},
}

View file

@ -209,7 +209,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(event, 1)",
),
ExpErr: "types 'STRINGSET' and 'INT' are not equatable",
ExpErr: "types 'stringset' and 'int' are not equatable",
},
{
// SetContainsWrongTypeInt
@ -217,7 +217,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(ievent, 'foo')",
),
ExpErr: "types 'IDSET' and 'STRING' are not equatable",
ExpErr: "types 'idset' and 'string' are not equatable",
},
{
// SetContainsWrongTypeSet
@ -225,7 +225,7 @@ var setFunctionTests = TableTest{
SQLs: sqls(
"select * from selectwithset where setcontains(event, ['foo'])",
),
ExpErr: "types 'STRINGSET' and 'STRINGSET' are not equatable",
ExpErr: "types 'stringset' and 'stringset' are not equatable",
},
},
}
@ -265,13 +265,13 @@ var setParameterTests = TableTest{
SQLs: sqls(
"select setcontains(['POST', 'GET'], 1)",
),
ExpErr: "types 'STRINGSET' and 'INT' are not equatable",
ExpErr: "types 'stringset' and 'int' are not equatable",
},
{
SQLs: sqls(
"select setcontains([1, 2], '1')",
),
ExpErr: "types 'IDSET' and 'STRING' are not equatable",
ExpErr: "types 'idset' and 'string' are not equatable",
},
{
@ -293,14 +293,14 @@ var setParameterTests = TableTest{
"select setcontainsall(['POST', 'GET'], [1, 2])",
"select setcontainsany(['POST', 'GET'], [1, 2])",
),
ExpErr: "types 'STRING' and 'ID' are not equatable",
ExpErr: "types 'string' and 'id' are not equatable",
},
{
SQLs: sqls(
"select setcontainsall([1, 2], ['1', '2'])",
"select setcontainsany([1, 2], ['1', '2'])",
),
ExpErr: "types 'ID' and 'STRING' are not equatable",
ExpErr: "types 'id' and 'string' are not equatable",
},
},
}

View file

@ -47,7 +47,7 @@ var timeQuantumQueryTest = TableTest{
SQLs: sqls(
"select _id not like '%f_' from not_like_all_types",
),
ExpErr: "operator 'NOTLIKE' incompatible with type 'ID'",
ExpErr: "operator 'NOTLIKE' incompatible with type 'id'",
},
},
}

View file

@ -73,19 +73,19 @@ var unaryOpExprWithBool = TableTest{
SQLs: sqls(
"select -i from unoptest_b;",
),
ExpErr: "operator '-' incompatible with type 'BOOL'",
ExpErr: "operator '-' incompatible with type 'bool'",
},
{
SQLs: sqls(
"select !i from unoptest_b;",
),
ExpErr: "operator '!' incompatible with type 'BOOL'",
ExpErr: "operator '!' incompatible with type 'bool'",
},
{
SQLs: sqls(
"select +i from unoptest_b;",
),
ExpErr: "operator '+' incompatible with type 'BOOL'",
ExpErr: "operator '+' incompatible with type 'bool'",
},
},
}
@ -169,7 +169,7 @@ var unaryOpExprWithDecimal = TableTest{
SQLs: sqls(
"select !d from unoptestd;",
),
ExpErr: "operator '!' incompatible with type 'DECIMAL(2)'",
ExpErr: "operator '!' incompatible with type 'decimal(2)'",
},
{
SQLs: sqls(
@ -202,19 +202,19 @@ var unaryOpExprWithTimestamp = TableTest{
SQLs: sqls(
"select -ts from unoptestts;",
),
ExpErr: "operator '-' incompatible with type 'TIMESTAMP'",
ExpErr: "operator '-' incompatible with type 'timestamp'",
},
{
SQLs: sqls(
"select !ts from unoptestts;",
),
ExpErr: "operator '!' incompatible with type 'TIMESTAMP'",
ExpErr: "operator '!' incompatible with type 'timestamp'",
},
{
SQLs: sqls(
"select +ts from unoptestts;",
),
ExpErr: "operator '+' incompatible with type 'TIMESTAMP'",
ExpErr: "operator '+' incompatible with type 'timestamp'",
},
},
}
@ -235,19 +235,19 @@ var unaryOpExprWithIDSet = TableTest{
SQLs: sqls(
"select -ids from unoptestids;",
),
ExpErr: "operator '-' incompatible with type 'IDSET'",
ExpErr: "operator '-' incompatible with type 'idset'",
},
{
SQLs: sqls(
"select !ids from unoptestids;",
),
ExpErr: "operator '!' incompatible with type 'IDSET'",
ExpErr: "operator '!' incompatible with type 'idset'",
},
{
SQLs: sqls(
"select +ids from unoptestids;",
),
ExpErr: "operator '+' incompatible with type 'IDSET'",
ExpErr: "operator '+' incompatible with type 'idset'",
},
},
}
@ -268,19 +268,19 @@ var unaryOpExprWithString = TableTest{
SQLs: sqls(
"select -s from unoptest_s;",
),
ExpErr: "operator '-' incompatible with type 'STRING'",
ExpErr: "operator '-' incompatible with type 'string'",
},
{
SQLs: sqls(
"select !s from unoptest_s;",
),
ExpErr: "operator '!' incompatible with type 'STRING'",
ExpErr: "operator '!' incompatible with type 'string'",
},
{
SQLs: sqls(
"select +s from unoptest_s;",
),
ExpErr: "operator '+' incompatible with type 'STRING'",
ExpErr: "operator '+' incompatible with type 'string'",
},
},
}
@ -301,19 +301,19 @@ var unaryOpExprWithStringSet = TableTest{
SQLs: sqls(
"select -s from unoptestss;",
),
ExpErr: "operator '-' incompatible with type 'STRINGSET'",
ExpErr: "operator '-' incompatible with type 'stringset'",
},
{
SQLs: sqls(
"select !s from unoptestss;",
),
ExpErr: "operator '!' incompatible with type 'STRINGSET'",
ExpErr: "operator '!' incompatible with type 'stringset'",
},
{
SQLs: sqls(
"select +s from unoptestss;",
),
ExpErr: "operator '+' incompatible with type 'STRINGSET'",
ExpErr: "operator '+' incompatible with type 'stringset'",
},
},
}

View file

@ -3,7 +3,6 @@ package test
import (
"context"
"strings"
"testing"
featurebase "github.com/molecula/featurebase/v3"
@ -59,8 +58,8 @@ func MustQueryRows(tb testing.TB, svr *featurebase.Server, q string) ([][]interf
for _, oc := range ocolumns {
cols = append(cols, &featurebase.WireQueryField{
Name: dax.FieldName(oc.ColumnName),
Type: strings.ToLower(oc.Type.TypeDescription()),
BaseType: dax.BaseType(strings.ToLower(oc.Type.TypeName())),
Type: oc.Type.TypeDescription(),
BaseType: dax.BaseType(oc.Type.BaseTypeName()),
TypeInfo: oc.Type.TypeInfo(),
})
}