mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
A bug fix roundup (#2242)
* fb-1940 re-implemented some changes that got missed private-public * fb-1939 fixes to between + decimals * fb-1935 - avg() on and id type + fixed some tests * fb-1953 add min/max for string types * fb-1938 - remove internal_type column from show columns * fb-1964 - fix space_used in fb_cluster_nodes to be int * fb-1996 - make sure all Idents that are being used as object references to schema objects are lowercased * fixed failing test * added some missed changes * fb-1969 found another case issue with identifier used for column idents
This commit is contained in:
parent
e803a000b8
commit
5c74b64722
30 changed files with 1150 additions and 207 deletions
94
executor.go
94
executor.go
|
|
@ -810,7 +810,7 @@ func (e *executor) executeCall(ctx context.Context, qcx *Qcx, index string, c *p
|
||||||
return res, errors.Wrap(err, "executeUnionRows")
|
return res, errors.Wrap(err, "executeUnionRows")
|
||||||
case "ConstRow":
|
case "ConstRow":
|
||||||
statFn(CounterQueryConstRowTotal)
|
statFn(CounterQueryConstRowTotal)
|
||||||
res, err := e.executeConstRow(ctx, index, c)
|
res, err := e.executeConstRow(ctx, qcx, index, c, opt)
|
||||||
return res, errors.Wrap(err, "executeConstRow")
|
return res, errors.Wrap(err, "executeConstRow")
|
||||||
case "Limit":
|
case "Limit":
|
||||||
statFn(CounterQueryLimitTotal)
|
statFn(CounterQueryLimitTotal)
|
||||||
|
|
@ -5356,14 +5356,96 @@ func (e *executor) executeNotShard(ctx context.Context, qcx *Qcx, index string,
|
||||||
return existenceRow.Difference(row), nil
|
return existenceRow.Difference(row), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *executor) executeConstRow(ctx context.Context, index string, c *pql.Call) (res *Row, err error) {
|
func (e *executor) executeConstRow(ctx context.Context, qcx *Qcx, index string, c *pql.Call, opt *ExecOptions) (res *Row, err error) {
|
||||||
|
idx := e.Holder.Index(index)
|
||||||
|
if idx == nil {
|
||||||
|
return nil, newNotFoundError(ErrIndexNotFound, index)
|
||||||
|
} else if idx.existenceField() == nil {
|
||||||
|
ids, ok := c.Args["columns"].([]uint64)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("missing columns list")
|
||||||
|
}
|
||||||
|
return NewRow(ids...), nil
|
||||||
|
}
|
||||||
// Fetch user-provided columns list.
|
// Fetch user-provided columns list.
|
||||||
ids, ok := c.Args["columns"].([]uint64)
|
availableBitmap := roaring.NewBitmap()
|
||||||
if !ok {
|
var records []uint64
|
||||||
return nil, errors.New("missing columns list")
|
if opt.Remote {
|
||||||
|
ids, _ := c.Args["columns"].([]interface{})
|
||||||
|
if len(ids) == 0 {
|
||||||
|
return NewRow(), nil
|
||||||
|
}
|
||||||
|
for _, idi := range ids {
|
||||||
|
id := idi.(int64)
|
||||||
|
availableBitmap.Add(uint64(id) / ShardWidth)
|
||||||
|
records = append(records, uint64(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ids, ok := c.Args["columns"].([]uint64)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("missing columns list")
|
||||||
|
}
|
||||||
|
if len(ids) == 0 {
|
||||||
|
return NewRow(), nil
|
||||||
|
}
|
||||||
|
for _, id := range ids {
|
||||||
|
availableBitmap.Add(id / ShardWidth)
|
||||||
|
records = append(records, id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewRow(ids...), nil
|
filteredShards := availableBitmap.Slice()
|
||||||
|
// Execute calls in bulk on each remote node and merge.
|
||||||
|
mapFn := func(ctx context.Context, shard uint64, mopt *mapOptions) (_ interface{}, err error) {
|
||||||
|
return e.executeConstRowShard(ctx, qcx, index, c, shard, NewRow(records...))
|
||||||
|
}
|
||||||
|
// Merge returned results at coordinating node.
|
||||||
|
reduceFn := func(ctx context.Context, prev, v interface{}) interface{} {
|
||||||
|
other, _ := prev.(*Row)
|
||||||
|
if other == nil {
|
||||||
|
other = NewRow()
|
||||||
|
}
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
other.Merge(v.(*Row))
|
||||||
|
return other
|
||||||
|
}
|
||||||
|
|
||||||
|
other, err := e.mapReduce(ctx, index, filteredShards, c, opt, mapFn, reduceFn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "map reduce")
|
||||||
|
}
|
||||||
|
|
||||||
|
row, _ := other.(*Row)
|
||||||
|
|
||||||
|
return row, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executor) executeConstRowShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64, src *Row) (res *Row, err error) {
|
||||||
|
idx := e.Holder.Index(index)
|
||||||
|
var existenceRow *Row
|
||||||
|
existenceFrag := e.Holder.fragment(index, existenceFieldName, viewStandard, shard)
|
||||||
|
if existenceFrag == nil {
|
||||||
|
existenceRow = NewRow()
|
||||||
|
} else {
|
||||||
|
tx, finisher, err := qcx.GetTx(Txo{Write: !writable, Index: idx, Fragment: existenceFrag, Shard: shard})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer finisher(&err)
|
||||||
|
|
||||||
|
if existenceRow, err = existenceFrag.row(tx, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return src.Intersect(existenceRow), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *executor) executeUnionRows(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *ExecOptions) (*Row, error) {
|
func (e *executor) executeUnionRows(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shards []uint64, opt *ExecOptions) (*Row, error) {
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var TempDir = getTempDirString()
|
||||||
TempDir = getTempDirString()
|
|
||||||
)
|
|
||||||
|
|
||||||
func getTempDirString() (td *string) {
|
func getTempDirString() (td *string) {
|
||||||
tdflag := flag.Lookup("temp-dir")
|
tdflag := flag.Lookup("temp-dir")
|
||||||
|
|
@ -1024,7 +1022,6 @@ func TestExecutor(t *testing.T) {
|
||||||
if columns := responses[4].Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(columns, []uint64{2}) {
|
if columns := responses[4].Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(columns, []uint64{2}) {
|
||||||
t.Fatalf("unexpected columns: %+v", columns)
|
t.Fatalf("unexpected columns: %+v", columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
// Ensure that ClearRow returns false when the row to clear needs translation.
|
// Ensure that ClearRow returns false when the row to clear needs translation.
|
||||||
t.Run("WithKeys", func(t *testing.T) {
|
t.Run("WithKeys", func(t *testing.T) {
|
||||||
|
|
@ -1198,6 +1195,7 @@ func TestExecutor_Execute_ConstRow(t *testing.T) {
|
||||||
c := test.MustRunCluster(t, 3)
|
c := test.MustRunCluster(t, 3)
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
// without track existnce you just get back the columns you request
|
||||||
c.CreateField(t, c.Idx(), pilosa.IndexOptions{}, "h")
|
c.CreateField(t, c.Idx(), pilosa.IndexOptions{}, "h")
|
||||||
c.ImportBits(t, c.Idx(), "h", [][2]uint64{
|
c.ImportBits(t, c.Idx(), "h", [][2]uint64{
|
||||||
{1, 2},
|
{1, 2},
|
||||||
|
|
@ -1205,7 +1203,27 @@ func TestExecutor_Execute_ConstRow(t *testing.T) {
|
||||||
{5, 6},
|
{5, 6},
|
||||||
})
|
})
|
||||||
|
|
||||||
resp := c.Query(t, c.Idx(), `ConstRow(columns=[2,6])`)
|
resp := c.Query(t, c.Idx(), `ConstRow(columns=[2,6,7])`)
|
||||||
|
expect := []uint64{2, 6, 7}
|
||||||
|
got := resp.Results[0].(*pilosa.Row).Columns()
|
||||||
|
if !reflect.DeepEqual(expect, got) {
|
||||||
|
t.Errorf("expected %v but got %v", expect, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExecutor_Execute_ConstRowTrackExistence(t *testing.T) {
|
||||||
|
c := test.MustRunCluster(t, 3)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
// with track existnce you
|
||||||
|
c.CreateField(t, c.Idx(), pilosa.IndexOptions{TrackExistence: true}, "h")
|
||||||
|
c.ImportBits(t, c.Idx(), "h", [][2]uint64{
|
||||||
|
{1, 2},
|
||||||
|
{3, 4},
|
||||||
|
{5, 6},
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := c.Query(t, c.Idx(), `ConstRow(columns=[2,6,7])`)
|
||||||
expect := []uint64{2, 6}
|
expect := []uint64{2, 6}
|
||||||
got := resp.Results[0].(*pilosa.Row).Columns()
|
got := resp.Results[0].(*pilosa.Row).Columns()
|
||||||
if !reflect.DeepEqual(expect, got) {
|
if !reflect.DeepEqual(expect, got) {
|
||||||
|
|
@ -1332,7 +1350,6 @@ func TestExecutor_Execute_Xor(t *testing.T) {
|
||||||
t.Fatalf("unexpected columns: %+v", columns)
|
t.Fatalf("unexpected columns: %+v", columns)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure a count query can be executed.
|
// Ensure a count query can be executed.
|
||||||
|
|
@ -1476,7 +1493,6 @@ func TestExecutor_Execute_Set(t *testing.T) {
|
||||||
} else if !res.Results[0].(bool) {
|
} else if !res.Results[0].(bool) {
|
||||||
t.Fatalf("expected column changed with integer column key")
|
t.Fatalf("expected column changed with integer column key")
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -3049,7 +3065,8 @@ func TestExecutor_Execute_Row_BSIGroup(t *testing.T) {
|
||||||
// EQ null
|
// EQ null
|
||||||
if result, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: c.Idx(), Query: `Row(other == null)`}); err != nil {
|
if result, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: c.Idx(), Query: `Row(other == null)`}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if !reflect.DeepEqual([]uint64{1,
|
} else if !reflect.DeepEqual([]uint64{
|
||||||
|
1,
|
||||||
50,
|
50,
|
||||||
ShardWidth,
|
ShardWidth,
|
||||||
ShardWidth + 1,
|
ShardWidth + 1,
|
||||||
|
|
@ -3148,7 +3165,7 @@ func TestExecutor_Execute_Row_BSIGroup(t *testing.T) {
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(fmt.Sprintf("#%d_%s", i, test.q), func(t *testing.T) {
|
t.Run(fmt.Sprintf("#%d_%s", i, test.q), func(t *testing.T) {
|
||||||
var expected = []uint64{}
|
expected := []uint64{}
|
||||||
if test.exp {
|
if test.exp {
|
||||||
expected = []uint64{0}
|
expected = []uint64{0}
|
||||||
}
|
}
|
||||||
|
|
@ -3585,7 +3602,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("json format groupBy on timestamps", func(t *testing.T) {
|
t.Run("json format groupBy on timestamps", func(t *testing.T) {
|
||||||
//SUP-138
|
// SUP-138
|
||||||
c.CreateField(t, c.Idx("t"), pilosa.IndexOptions{TrackExistence: true}, "timestamp", pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds))
|
c.CreateField(t, c.Idx("t"), pilosa.IndexOptions{TrackExistence: true}, "timestamp", pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds))
|
||||||
c.Query(t, c.Idx("t"), `
|
c.Query(t, c.Idx("t"), `
|
||||||
Set(8, timestamp='2021-01-27T08:00:00Z')
|
Set(8, timestamp='2021-01-27T08:00:00Z')
|
||||||
|
|
@ -3816,7 +3833,7 @@ func TestExecutor_Time_Clear_Quantums(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
hldr := c.GetHolder(0)
|
hldr := c.GetHolder(0)
|
||||||
|
|
||||||
var rangeTests = []struct {
|
rangeTests := []struct {
|
||||||
quantum pilosa.TimeQuantum
|
quantum pilosa.TimeQuantum
|
||||||
expected []uint64
|
expected []uint64
|
||||||
}{
|
}{
|
||||||
|
|
@ -3942,10 +3959,11 @@ func TestExecutor_Execute_Existence(t *testing.T) {
|
||||||
|
|
||||||
node0 := c.GetNode(0)
|
node0 := c.GetNode(0)
|
||||||
// Set bits.
|
// Set bits.
|
||||||
if _, err := node0.API.Query(context.Background(), &pilosa.QueryRequest{Index: c.Idx(), Query: `` +
|
if _, err := node0.API.Query(context.Background(), &pilosa.QueryRequest{
|
||||||
fmt.Sprintf("Set(%d, f=%d)\n", 3, 10) +
|
Index: c.Idx(), Query: `` +
|
||||||
fmt.Sprintf("Set(%d, f=%d)\n", ShardWidth+1, 10) +
|
fmt.Sprintf("Set(%d, f=%d)\n", 3, 10) +
|
||||||
fmt.Sprintf("Set(%d, f=%d)\n", ShardWidth+2, 20),
|
fmt.Sprintf("Set(%d, f=%d)\n", ShardWidth+1, 10) +
|
||||||
|
fmt.Sprintf("Set(%d, f=%d)\n", ShardWidth+2, 20),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -9199,6 +9217,8 @@ func TestExternalLookup(t *testing.T) {
|
||||||
// Populate a field with some data that can be used in queries.
|
// Populate a field with some data that can be used in queries.
|
||||||
c.CreateField(t, c.Idx(), pilosa.IndexOptions{TrackExistence: true}, "f")
|
c.CreateField(t, c.Idx(), pilosa.IndexOptions{TrackExistence: true}, "f")
|
||||||
c.ImportBits(t, c.Idx(), "f", [][2]uint64{
|
c.ImportBits(t, c.Idx(), "f", [][2]uint64{
|
||||||
|
{0, 0},
|
||||||
|
{0, 4},
|
||||||
{1, 1},
|
{1, 1},
|
||||||
{1, 3},
|
{1, 3},
|
||||||
{2, 2},
|
{2, 2},
|
||||||
|
|
|
||||||
|
|
@ -17,26 +17,27 @@ const (
|
||||||
ErrUnknownType errors.Code = "ErrUnknownType"
|
ErrUnknownType errors.Code = "ErrUnknownType"
|
||||||
ErrUnknownIdentifier errors.Code = "ErrUnknownIdentifier"
|
ErrUnknownIdentifier errors.Code = "ErrUnknownIdentifier"
|
||||||
|
|
||||||
ErrTypeIncompatibleWithBitwiseOperator errors.Code = "ErrTypeIncompatibleWithBitwiseOperator"
|
ErrTypeIncompatibleWithBitwiseOperator errors.Code = "ErrTypeIncompatibleWithBitwiseOperator"
|
||||||
ErrTypeIncompatibleWithLogicalOperator errors.Code = "ErrTypeIncompatibleWithLogicalOperator"
|
ErrTypeIncompatibleWithLogicalOperator errors.Code = "ErrTypeIncompatibleWithLogicalOperator"
|
||||||
ErrTypeIncompatibleWithEqualityOperator errors.Code = "ErrTypeIncompatibleWithEqualityOperator"
|
ErrTypeIncompatibleWithEqualityOperator errors.Code = "ErrTypeIncompatibleWithEqualityOperator"
|
||||||
ErrTypeIncompatibleWithComparisonOperator errors.Code = "ErrTypeIncompatibleWithComparisonOperator"
|
ErrTypeIncompatibleWithComparisonOperator errors.Code = "ErrTypeIncompatibleWithComparisonOperator"
|
||||||
ErrTypeIncompatibleWithArithmeticOperator errors.Code = "ErrTypeIncompatibleWithArithmeticOperator"
|
ErrTypeIncompatibleWithArithmeticOperator errors.Code = "ErrTypeIncompatibleWithArithmeticOperator"
|
||||||
ErrTypeIncompatibleWithConcatOperator errors.Code = "ErrTypeIncompatibleWithConcatOperator"
|
ErrTypeIncompatibleWithConcatOperator errors.Code = "ErrTypeIncompatibleWithConcatOperator"
|
||||||
ErrTypeIncompatibleWithLikeOperator errors.Code = "ErrTypeIncompatibleWithLikeOperator"
|
ErrTypeIncompatibleWithLikeOperator errors.Code = "ErrTypeIncompatibleWithLikeOperator"
|
||||||
ErrTypeIncompatibleWithBetweenOperator errors.Code = "ErrTypeIncompatibleWithBetweenOperator"
|
ErrTypeIncompatibleWithBetweenOperator errors.Code = "ErrTypeIncompatibleWithBetweenOperator"
|
||||||
ErrTypeCannotBeUsedAsRangeSubscript errors.Code = "ErrTypeCannotBeUsedAsRangeSubscript"
|
ErrTypeCannotBeUsedAsRangeSubscript errors.Code = "ErrTypeCannotBeUsedAsRangeSubscript"
|
||||||
ErrTypesAreNotEquatable errors.Code = "ErrTypesAreNotEquatable"
|
ErrTypesAreNotEquatable errors.Code = "ErrTypesAreNotEquatable"
|
||||||
ErrTypeMismatch errors.Code = "ErrTypeMismatch"
|
ErrTypeMismatch errors.Code = "ErrTypeMismatch"
|
||||||
ErrIncompatibleTypesForRangeSubscripts errors.Code = "ErrIncompatibleTypesForRangeSubscripts"
|
ErrIncompatibleTypesForRangeSubscripts errors.Code = "ErrIncompatibleTypesForRangeSubscripts"
|
||||||
ErrExpressionListExpected errors.Code = "ErrExpressionListExpected"
|
ErrExpressionListExpected errors.Code = "ErrExpressionListExpected"
|
||||||
ErrBooleanExpressionExpected errors.Code = "ErrBooleanExpressionExpected"
|
ErrBooleanExpressionExpected errors.Code = "ErrBooleanExpressionExpected"
|
||||||
ErrIntExpressionExpected errors.Code = "ErrIntExpressionExpected"
|
ErrIntExpressionExpected errors.Code = "ErrIntExpressionExpected"
|
||||||
ErrIntOrDecimalExpressionExpected errors.Code = "ErrIntOrDecimalExpressionExpected"
|
ErrIntOrDecimalExpressionExpected errors.Code = "ErrIntOrDecimalExpressionExpected"
|
||||||
ErrIntOrDecimalOrTimestampExpressionExpected errors.Code = "ErrIntOrDecimalOrTimestampExpressionExpected"
|
ErrIntOrDecimalOrTimestampExpressionExpected errors.Code = "ErrIntOrDecimalOrTimestampExpressionExpected"
|
||||||
ErrStringExpressionExpected errors.Code = "ErrStringExpressionExpected"
|
ErrIntOrDecimalOrTimestampOrStringExpressionExpected errors.Code = "ErrIntOrDecimalOrTimestampOrStringExpressionExpected"
|
||||||
ErrSetExpressionExpected errors.Code = "ErrSetExpressionExpected"
|
ErrStringExpressionExpected errors.Code = "ErrStringExpressionExpected"
|
||||||
ErrSingleRowExpected errors.Code = "ErrSingleRowExpected"
|
ErrSetExpressionExpected errors.Code = "ErrSetExpressionExpected"
|
||||||
|
ErrSingleRowExpected errors.Code = "ErrSingleRowExpected"
|
||||||
|
|
||||||
// type related errors
|
// type related errors
|
||||||
|
|
||||||
|
|
@ -369,7 +370,7 @@ func NewErrTypeCannotBeUsedAsRangeSubscript(line, col int, type1 string) error {
|
||||||
func NewErrIncompatibleTypesForRangeSubscripts(line, col int, type1 string, type2 string) error {
|
func NewErrIncompatibleTypesForRangeSubscripts(line, col int, type1 string, type2 string) error {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
ErrIncompatibleTypesForRangeSubscripts,
|
ErrIncompatibleTypesForRangeSubscripts,
|
||||||
fmt.Sprintf("[%d:%d] incompatible types '%s' and '%s' useds as range subscripts", line, col, type1, type2),
|
fmt.Sprintf("[%d:%d] incompatible types '%s' and '%s' used as range subscripts", line, col, type1, type2),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,6 +423,13 @@ func NewErrIntOrDecimalOrTimestampExpressionExpected(line, col int) error {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewErrIntOrDecimalOrTimestampOrStringExpressionExpected(line, col int) error {
|
||||||
|
return errors.New(
|
||||||
|
ErrIntOrDecimalOrTimestampOrStringExpressionExpected,
|
||||||
|
fmt.Sprintf("[%d:%d] integer, decimal, timestamp or string expression expected", line, col),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func NewErrStringExpressionExpected(line, col int) error {
|
func NewErrStringExpressionExpected(line, col int) error {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
ErrStringExpressionExpected,
|
ErrStringExpressionExpected,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/dax"
|
"github.com/featurebasedb/featurebase/v3/dax"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3"
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
||||||
|
|
@ -14,7 +15,7 @@ import (
|
||||||
// compileAlterDatabaseStatement compiles an ALTER DATABASE statement into a
|
// compileAlterDatabaseStatement compiles an ALTER DATABASE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileAlterDatabaseStatement(ctx context.Context, stmt *parser.AlterDatabaseStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileAlterDatabaseStatement(ctx context.Context, stmt *parser.AlterDatabaseStatement) (_ types.PlanOperator, err error) {
|
||||||
databaseName := parser.IdentName(stmt.Name)
|
databaseName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
|
|
||||||
// does the database exist
|
// does the database exist
|
||||||
dbname := dax.DatabaseName(databaseName)
|
dbname := dax.DatabaseName(databaseName)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ const (
|
||||||
// compileAlterTableStatement compiles an ALTER TABLE statement into a
|
// compileAlterTableStatement compiles an ALTER TABLE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileAlterTableStatement(ctx context.Context, stmt *parser.AlterTableStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileAlterTableStatement(ctx context.Context, stmt *parser.AlterTableStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.Name)
|
tableName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
|
|
||||||
// does the table exist
|
// does the table exist
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
|
|
@ -37,7 +37,7 @@ func (p *ExecutionPlanner) compileAlterTableStatement(ctx context.Context, stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
if stmt.Drop.IsValid() {
|
if stmt.Drop.IsValid() {
|
||||||
columnName := parser.IdentName(stmt.DropColumnName)
|
columnName := strings.ToLower(parser.IdentName(stmt.DropColumnName))
|
||||||
|
|
||||||
// does this column exist
|
// does this column exist
|
||||||
found := false
|
found := false
|
||||||
|
|
@ -54,7 +54,7 @@ func (p *ExecutionPlanner) compileAlterTableStatement(ctx context.Context, stmt
|
||||||
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpDrop, columnName, "", nil), p.sql), nil
|
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpDrop, columnName, "", nil), p.sql), nil
|
||||||
} else if stmt.Add.IsValid() {
|
} else if stmt.Add.IsValid() {
|
||||||
col := stmt.ColumnDef
|
col := stmt.ColumnDef
|
||||||
columnName := parser.IdentName(col.Name)
|
columnName := strings.ToLower(parser.IdentName(col.Name))
|
||||||
|
|
||||||
// does this column exist
|
// does this column exist
|
||||||
for _, f := range tbl.Fields {
|
for _, f := range tbl.Fields {
|
||||||
|
|
@ -70,8 +70,8 @@ func (p *ExecutionPlanner) compileAlterTableStatement(ctx context.Context, stmt
|
||||||
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpAdd, "", columnName, column), p.sql), nil
|
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpAdd, "", columnName, column), p.sql), nil
|
||||||
|
|
||||||
} else if stmt.Rename.IsValid() {
|
} else if stmt.Rename.IsValid() {
|
||||||
oldColumnName := parser.IdentName(stmt.OldColumnName)
|
oldColumnName := strings.ToLower(parser.IdentName(stmt.OldColumnName))
|
||||||
newColumnName := parser.IdentName(stmt.NewColumnName)
|
newColumnName := strings.ToLower(parser.IdentName(stmt.NewColumnName))
|
||||||
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpRename, oldColumnName, newColumnName, nil), p.sql), nil
|
return NewPlanOpQuery(p, NewPlanOpAlterTable(p, tableName, alterOpRename, oldColumnName, newColumnName, nil), p.sql), nil
|
||||||
} else {
|
} else {
|
||||||
return nil, sql3.NewErrInternal("unhandled alter operation")
|
return nil, sql3.NewErrInternal("unhandled alter operation")
|
||||||
|
|
@ -86,7 +86,7 @@ func (p *ExecutionPlanner) analyzeAlterTableStatement(stmt *parser.AlterTableSta
|
||||||
//no checks for now
|
//no checks for now
|
||||||
} else if stmt.Add.IsValid() {
|
} else if stmt.Add.IsValid() {
|
||||||
col := stmt.ColumnDef
|
col := stmt.ColumnDef
|
||||||
columnName := parser.IdentName(col.Name)
|
columnName := strings.ToLower(parser.IdentName(col.Name))
|
||||||
typeName := parser.IdentName(col.Type.Name)
|
typeName := parser.IdentName(col.Type.Name)
|
||||||
if !parser.IsValidTypeName(typeName) {
|
if !parser.IsValidTypeName(typeName) {
|
||||||
return sql3.NewErrUnknownType(col.Type.Name.NamePos.Line, col.Type.Name.NamePos.Column, typeName)
|
return sql3.NewErrUnknownType(col.Type.Name.NamePos.Line, col.Type.Name.NamePos.Column, typeName)
|
||||||
|
|
@ -103,8 +103,8 @@ func (p *ExecutionPlanner) analyzeAlterTableStatement(stmt *parser.AlterTableSta
|
||||||
}
|
}
|
||||||
} else if stmt.Rename.IsValid() {
|
} else if stmt.Rename.IsValid() {
|
||||||
//check the new and old are not the same
|
//check the new and old are not the same
|
||||||
oldColumnName := parser.IdentName(stmt.OldColumnName)
|
oldColumnName := strings.ToLower(parser.IdentName(stmt.OldColumnName))
|
||||||
newColumnName := parser.IdentName(stmt.NewColumnName)
|
newColumnName := strings.ToLower(parser.IdentName(stmt.NewColumnName))
|
||||||
if strings.EqualFold(oldColumnName, newColumnName) {
|
if strings.EqualFold(oldColumnName, newColumnName) {
|
||||||
return sql3.NewErrDuplicateColumn(stmt.NewColumnName.NamePos.Line, stmt.NewColumnName.NamePos.Column, newColumnName)
|
return sql3.NewErrDuplicateColumn(stmt.NewColumnName.NamePos.Line, stmt.NewColumnName.NamePos.Column, newColumnName)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
// compileBulkInsertStatement compiles a BULK INSERT statement into a
|
// compileBulkInsertStatement compiles a BULK INSERT statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileBulkInsertStatement(ctx context.Context, stmt *parser.BulkInsertStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileBulkInsertStatement(ctx context.Context, stmt *parser.BulkInsertStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.Table)
|
tableName := strings.ToLower(parser.IdentName(stmt.Table))
|
||||||
|
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
||||||
|
|
@ -114,7 +114,7 @@ func (p *ExecutionPlanner) compileBulkInsertStatement(ctx context.Context, stmt
|
||||||
for _, m := range stmt.Columns {
|
for _, m := range stmt.Columns {
|
||||||
for idx, fld := range tbl.Fields {
|
for idx, fld := range tbl.Fields {
|
||||||
if strings.EqualFold(string(fld.Name), m.Name) {
|
if strings.EqualFold(string(fld.Name), m.Name) {
|
||||||
options.targetColumns = append(options.targetColumns, newQualifiedRefPlanExpression(tableName, m.Name, idx, fieldSQLDataType(pilosa.FieldToFieldInfo(fld))))
|
options.targetColumns = append(options.targetColumns, newQualifiedRefPlanExpression(tableName, strings.ToLower(m.Name), idx, fieldSQLDataType(pilosa.FieldToFieldInfo(fld))))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,7 @@ func (p *ExecutionPlanner) compileBulkInsertStatement(ctx context.Context, stmt
|
||||||
// error if anything is invalid.
|
// error if anything is invalid.
|
||||||
func (p *ExecutionPlanner) analyzeBulkInsertStatement(ctx context.Context, stmt *parser.BulkInsertStatement) error {
|
func (p *ExecutionPlanner) analyzeBulkInsertStatement(ctx context.Context, stmt *parser.BulkInsertStatement) error {
|
||||||
// check referred to table exists
|
// check referred to table exists
|
||||||
tableName := parser.IdentName(stmt.Table)
|
tableName := strings.ToLower(parser.IdentName(stmt.Table))
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3"
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
||||||
|
|
@ -13,7 +14,7 @@ import (
|
||||||
// compileCreateDatabaseStatement compiles a CREATE DATABASE statement into a
|
// compileCreateDatabaseStatement compiles a CREATE DATABASE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileCreateDatabaseStatement(stmt *parser.CreateDatabaseStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileCreateDatabaseStatement(stmt *parser.CreateDatabaseStatement) (_ types.PlanOperator, err error) {
|
||||||
databaseName := parser.IdentName(stmt.Name)
|
databaseName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
failIfExists := !stmt.IfNotExists.IsValid()
|
failIfExists := !stmt.IfNotExists.IsValid()
|
||||||
|
|
||||||
units := 0
|
units := 0
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ type createTableField struct {
|
||||||
// compileCreateTableStatement compiles a CREATE TABLE statement into a
|
// compileCreateTableStatement compiles a CREATE TABLE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileCreateTableStatement(ctx context.Context, stmt *parser.CreateTableStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileCreateTableStatement(ctx context.Context, stmt *parser.CreateTableStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.Name)
|
tableName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
failIfExists := !stmt.IfNotExists.IsValid()
|
failIfExists := !stmt.IfNotExists.IsValid()
|
||||||
|
|
||||||
// apply table options
|
// apply table options
|
||||||
|
|
@ -51,7 +51,7 @@ func (p *ExecutionPlanner) compileCreateTableStatement(ctx context.Context, stmt
|
||||||
|
|
||||||
var columns = []*createTableField{}
|
var columns = []*createTableField{}
|
||||||
for _, col := range stmt.Columns {
|
for _, col := range stmt.Columns {
|
||||||
columnName := parser.IdentName(col.Name)
|
columnName := strings.ToLower(parser.IdentName(col.Name))
|
||||||
typeName := parser.IdentName(col.Type.Name)
|
typeName := parser.IdentName(col.Type.Name)
|
||||||
|
|
||||||
if strings.ToLower(columnName) == "_id" {
|
if strings.ToLower(columnName) == "_id" {
|
||||||
|
|
@ -78,7 +78,7 @@ func (p *ExecutionPlanner) compileCreateTableStatement(ctx context.Context, stmt
|
||||||
// compiles a column def
|
// compiles a column def
|
||||||
func (p *ExecutionPlanner) compileColumn(ctx context.Context, col *parser.ColumnDefinition) (*createTableField, error) {
|
func (p *ExecutionPlanner) compileColumn(ctx context.Context, col *parser.ColumnDefinition) (*createTableField, error) {
|
||||||
var err error
|
var err error
|
||||||
columnName := parser.IdentName(col.Name)
|
columnName := strings.ToLower(parser.IdentName(col.Name))
|
||||||
typeName := parser.IdentName(col.Type.Name)
|
typeName := parser.IdentName(col.Type.Name)
|
||||||
|
|
||||||
column := &createTableField{
|
column := &createTableField{
|
||||||
|
|
@ -251,7 +251,7 @@ func (p *ExecutionPlanner) analyzeCreateTableStatement(stmt *parser.CreateTableS
|
||||||
//iterate columns, check types, check constraints, ensure we have no dupe names and make sure there is an _id column
|
//iterate columns, check types, check constraints, ensure we have no dupe names and make sure there is an _id column
|
||||||
checkedColumns := make(map[string]string)
|
checkedColumns := make(map[string]string)
|
||||||
for _, col := range stmt.Columns {
|
for _, col := range stmt.Columns {
|
||||||
columnName := parser.IdentName(col.Name)
|
columnName := strings.ToLower(parser.IdentName(col.Name))
|
||||||
_, ok := checkedColumns[strings.ToLower(columnName)]
|
_, ok := checkedColumns[strings.ToLower(columnName)]
|
||||||
if ok {
|
if ok {
|
||||||
return sql3.NewErrDuplicateColumn(col.Name.NamePos.Line, col.Name.NamePos.Column, columnName)
|
return sql3.NewErrDuplicateColumn(col.Name.NamePos.Line, col.Name.NamePos.Column, columnName)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
||||||
|
|
@ -11,7 +12,7 @@ import (
|
||||||
|
|
||||||
// compileCreateViewStatement compiles a parser.CreateViewStatement AST into a PlanOperator
|
// compileCreateViewStatement compiles a parser.CreateViewStatement AST into a PlanOperator
|
||||||
func (p *ExecutionPlanner) compileCreateViewStatement(stmt *parser.CreateViewStatement) (types.PlanOperator, error) {
|
func (p *ExecutionPlanner) compileCreateViewStatement(stmt *parser.CreateViewStatement) (types.PlanOperator, error) {
|
||||||
viewName := parser.IdentName(stmt.Name)
|
viewName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
view := &viewSystemObject{
|
view := &viewSystemObject{
|
||||||
name: viewName,
|
name: viewName,
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +30,7 @@ func (p *ExecutionPlanner) compileCreateViewStatement(stmt *parser.CreateViewSta
|
||||||
|
|
||||||
// compileAlterViewStatement compiles a parser.AlterViewStatement AST into a PlanOperator
|
// compileAlterViewStatement compiles a parser.AlterViewStatement AST into a PlanOperator
|
||||||
func (p *ExecutionPlanner) compileAlterViewStatement(stmt *parser.AlterViewStatement) (types.PlanOperator, error) {
|
func (p *ExecutionPlanner) compileAlterViewStatement(stmt *parser.AlterViewStatement) (types.PlanOperator, error) {
|
||||||
viewName := parser.IdentName(stmt.Name)
|
viewName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
view := &viewSystemObject{
|
view := &viewSystemObject{
|
||||||
name: viewName,
|
name: viewName,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
||||||
|
|
@ -13,7 +14,7 @@ import (
|
||||||
func (p *ExecutionPlanner) compileDeleteStatement(stmt *parser.DeleteStatement) (types.PlanOperator, error) {
|
func (p *ExecutionPlanner) compileDeleteStatement(stmt *parser.DeleteStatement) (types.PlanOperator, error) {
|
||||||
query := NewPlanOpQuery(p, NewPlanOpNullTable(), p.sql)
|
query := NewPlanOpQuery(p, NewPlanOpNullTable(), p.sql)
|
||||||
|
|
||||||
tableName := parser.IdentName(stmt.TableName.Name)
|
tableName := strings.ToLower(parser.IdentName(stmt.TableName.Name))
|
||||||
|
|
||||||
// source expression
|
// source expression
|
||||||
source, err := p.compileSource(query, stmt.Source)
|
source, err := p.compileSource(query, stmt.Source)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/dax"
|
"github.com/featurebasedb/featurebase/v3/dax"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3"
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
||||||
|
|
@ -14,7 +15,7 @@ import (
|
||||||
// compileDropDatabaseStatement compiles a DROP DATABASE statement into a
|
// compileDropDatabaseStatement compiles a DROP DATABASE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileDropDatabaseStatement(ctx context.Context, stmt *parser.DropDatabaseStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileDropDatabaseStatement(ctx context.Context, stmt *parser.DropDatabaseStatement) (_ types.PlanOperator, err error) {
|
||||||
databaseName := parser.IdentName(stmt.Name)
|
databaseName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
dbname := dax.DatabaseName(databaseName)
|
dbname := dax.DatabaseName(databaseName)
|
||||||
db, err := p.schemaAPI.DatabaseByName(ctx, dbname)
|
db, err := p.schemaAPI.DatabaseByName(ctx, dbname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
pilosa "github.com/featurebasedb/featurebase/v3"
|
pilosa "github.com/featurebasedb/featurebase/v3"
|
||||||
"github.com/featurebasedb/featurebase/v3/dax"
|
"github.com/featurebasedb/featurebase/v3/dax"
|
||||||
|
|
@ -15,7 +16,7 @@ import (
|
||||||
// compileDropTableStatement compiles a DROP TABLE statement into a
|
// compileDropTableStatement compiles a DROP TABLE statement into a
|
||||||
// PlanOperator.
|
// PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileDropTableStatement(ctx context.Context, stmt *parser.DropTableStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileDropTableStatement(ctx context.Context, stmt *parser.DropTableStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.Name)
|
tableName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package planner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3"
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
||||||
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
||||||
|
|
@ -12,7 +13,7 @@ import (
|
||||||
|
|
||||||
// compileDropViewStatement compiles a DROP VIEW statement into a PlanOperator.
|
// compileDropViewStatement compiles a DROP VIEW statement into a PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileDropViewStatement(ctx context.Context, stmt *parser.DropViewStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileDropViewStatement(ctx context.Context, stmt *parser.DropViewStatement) (_ types.PlanOperator, err error) {
|
||||||
viewName := parser.IdentName(stmt.Name)
|
viewName := strings.ToLower(parser.IdentName(stmt.Name))
|
||||||
v, err := p.getViewByName(ctx, viewName)
|
v, err := p.getViewByName(ctx, viewName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
// compileInsertStatement compiles an INSERT statement into a PlanOperator.
|
// compileInsertStatement compiles an INSERT statement into a PlanOperator.
|
||||||
func (p *ExecutionPlanner) compileInsertStatement(ctx context.Context, stmt *parser.InsertStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileInsertStatement(ctx context.Context, stmt *parser.InsertStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.Table)
|
tableName := strings.ToLower(parser.IdentName(stmt.Table))
|
||||||
|
|
||||||
targetColumns := []*qualifiedRefPlanExpression{}
|
targetColumns := []*qualifiedRefPlanExpression{}
|
||||||
insertValues := [][]types.PlanExpression{}
|
insertValues := [][]types.PlanExpression{}
|
||||||
|
|
@ -31,7 +31,7 @@ func (p *ExecutionPlanner) compileInsertStatement(ctx context.Context, stmt *par
|
||||||
|
|
||||||
if len(stmt.Columns) > 0 {
|
if len(stmt.Columns) > 0 {
|
||||||
for _, columnIdent := range stmt.Columns {
|
for _, columnIdent := range stmt.Columns {
|
||||||
colName := parser.IdentName(columnIdent)
|
colName := strings.ToLower(parser.IdentName(columnIdent))
|
||||||
|
|
||||||
if strings.EqualFold(colName, "_id") {
|
if strings.EqualFold(colName, "_id") {
|
||||||
targetColumns = append(targetColumns, newQualifiedRefPlanExpression(tableName, colName, 0, parser.NewDataTypeID()))
|
targetColumns = append(targetColumns, newQualifiedRefPlanExpression(tableName, colName, 0, parser.NewDataTypeID()))
|
||||||
|
|
@ -74,7 +74,7 @@ func (p *ExecutionPlanner) compileInsertStatement(ctx context.Context, stmt *par
|
||||||
// anything is invalid.
|
// anything is invalid.
|
||||||
func (p *ExecutionPlanner) analyzeInsertStatement(ctx context.Context, stmt *parser.InsertStatement) error {
|
func (p *ExecutionPlanner) analyzeInsertStatement(ctx context.Context, stmt *parser.InsertStatement) error {
|
||||||
// Check that referred table exists.
|
// Check that referred table exists.
|
||||||
tableName := parser.IdentName(stmt.Table)
|
tableName := strings.ToLower(parser.IdentName(stmt.Table))
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -108,7 +108,7 @@ func (p *ExecutionPlanner) analyzeInsertStatement(ctx context.Context, stmt *par
|
||||||
// dupes.
|
// dupes.
|
||||||
columnNameMap := make(map[string]struct{})
|
columnNameMap := make(map[string]struct{})
|
||||||
for _, columnIdent := range stmt.Columns {
|
for _, columnIdent := range stmt.Columns {
|
||||||
colName := parser.IdentName(columnIdent)
|
colName := strings.ToLower(parser.IdentName(columnIdent))
|
||||||
var typeName parser.ExprDataType
|
var typeName parser.ExprDataType
|
||||||
|
|
||||||
if strings.EqualFold(colName, "_id") {
|
if strings.EqualFold(colName, "_id") {
|
||||||
|
|
|
||||||
|
|
@ -309,10 +309,10 @@ func (p *ExecutionPlanner) compileSource(scope *PlanOpQuery, source parser.Sourc
|
||||||
|
|
||||||
case *parser.QualifiedTableName:
|
case *parser.QualifiedTableName:
|
||||||
|
|
||||||
tableName := parser.IdentName(sourceExpr.Name)
|
tableName := strings.ToLower(parser.IdentName(sourceExpr.Name))
|
||||||
|
|
||||||
// doing this check here because we don't have a 'system' flag that exists in the FB schema
|
// doing this check here because we don't have a 'system' flag that exists in the FB schema
|
||||||
st, ok := systemTables[strings.ToLower(tableName)]
|
st, ok := systemTables[tableName]
|
||||||
if ok {
|
if ok {
|
||||||
var op types.PlanOperator
|
var op types.PlanOperator
|
||||||
op = NewPlanOpSystemTable(p, st)
|
op = NewPlanOpSystemTable(p, st)
|
||||||
|
|
@ -418,7 +418,7 @@ func (p *ExecutionPlanner) analyzeSource(ctx context.Context, source parser.Sour
|
||||||
|
|
||||||
case *parser.QualifiedTableName:
|
case *parser.QualifiedTableName:
|
||||||
|
|
||||||
objectName := parser.IdentName(source.Name)
|
objectName := strings.ToLower(parser.IdentName(source.Name))
|
||||||
|
|
||||||
// check views first
|
// check views first
|
||||||
view, err := p.getViewByName(ctx, objectName)
|
view, err := p.getViewByName(ctx, objectName)
|
||||||
|
|
@ -620,7 +620,7 @@ func (p *ExecutionPlanner) analyzeSelectStatementWildcards(stmt *parser.SelectSt
|
||||||
} else {
|
} else {
|
||||||
//handle the case of a qualified ref with a *
|
//handle the case of a qualified ref with a *
|
||||||
if ref, ok := col.Expr.(*parser.QualifiedRef); ok && ref.Star.IsValid() {
|
if ref, ok := col.Expr.(*parser.QualifiedRef); ok && ref.Star.IsValid() {
|
||||||
refName := parser.IdentName(ref.Table)
|
refName := strings.ToLower(parser.IdentName(ref.Table))
|
||||||
src := stmt.Source.SourceFromAlias(refName)
|
src := stmt.Source.SourceFromAlias(refName)
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return sql3.NewErrTableNotFound(ref.Table.NamePos.Line, ref.Table.NamePos.Column, refName)
|
return sql3.NewErrTableNotFound(ref.Table.NamePos.Line, ref.Table.NamePos.Column, refName)
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ func (p *ExecutionPlanner) compileShowTablesStatement(ctx context.Context, stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecutionPlanner) compileShowColumnsStatement(ctx context.Context, stmt *parser.ShowColumnsStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileShowColumnsStatement(ctx context.Context, stmt *parser.ShowColumnsStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.TableName)
|
tableName := strings.ToLower(parser.IdentName(stmt.TableName))
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
tbl, err := p.schemaAPI.TableByName(ctx, tname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -159,70 +159,65 @@ func (p *ExecutionPlanner) compileShowColumnsStatement(ctx context.Context, stmt
|
||||||
columnName: "name",
|
columnName: "name",
|
||||||
columnIndex: 1,
|
columnIndex: 1,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}, &qualifiedRefPlanExpression{ // the SQL3 data type description
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "type",
|
columnName: "type",
|
||||||
columnIndex: 2,
|
columnIndex: 2,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}, &qualifiedRefPlanExpression{ // the FeatureBase 'native' data type description
|
|
||||||
tableName: "fb_table_columns",
|
|
||||||
columnName: "internal_type",
|
|
||||||
columnIndex: 3,
|
|
||||||
dataType: parser.NewDataTypeString(),
|
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "created_at",
|
columnName: "created_at",
|
||||||
columnIndex: 4,
|
columnIndex: 3,
|
||||||
dataType: parser.NewDataTypeTimestamp(),
|
dataType: parser.NewDataTypeTimestamp(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "keys",
|
columnName: "keys",
|
||||||
columnIndex: 5,
|
columnIndex: 4,
|
||||||
dataType: parser.NewDataTypeBool(),
|
dataType: parser.NewDataTypeBool(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "cache_type",
|
columnName: "cache_type",
|
||||||
columnIndex: 6,
|
columnIndex: 5,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "cache_size",
|
columnName: "cache_size",
|
||||||
columnIndex: 7,
|
columnIndex: 6,
|
||||||
dataType: parser.NewDataTypeInt(),
|
dataType: parser.NewDataTypeInt(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "scale",
|
columnName: "scale",
|
||||||
columnIndex: 8,
|
columnIndex: 7,
|
||||||
dataType: parser.NewDataTypeInt(),
|
dataType: parser.NewDataTypeInt(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "min",
|
columnName: "min",
|
||||||
columnIndex: 9,
|
columnIndex: 8,
|
||||||
dataType: parser.NewDataTypeInt(),
|
dataType: parser.NewDataTypeInt(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "max",
|
columnName: "max",
|
||||||
columnIndex: 10,
|
columnIndex: 9,
|
||||||
dataType: parser.NewDataTypeInt(),
|
dataType: parser.NewDataTypeInt(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "timeunit",
|
columnName: "timeunit",
|
||||||
columnIndex: 11,
|
columnIndex: 10,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "epoch",
|
columnName: "epoch",
|
||||||
columnIndex: 12,
|
columnIndex: 11,
|
||||||
dataType: parser.NewDataTypeInt(),
|
dataType: parser.NewDataTypeInt(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "timequantum",
|
columnName: "timequantum",
|
||||||
columnIndex: 13,
|
columnIndex: 12,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}, &qualifiedRefPlanExpression{
|
}, &qualifiedRefPlanExpression{
|
||||||
tableName: "fb_table_columns",
|
tableName: "fb_table_columns",
|
||||||
columnName: "ttl",
|
columnName: "ttl",
|
||||||
columnIndex: 14,
|
columnIndex: 13,
|
||||||
dataType: parser.NewDataTypeString(),
|
dataType: parser.NewDataTypeString(),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
@ -230,7 +225,7 @@ func (p *ExecutionPlanner) compileShowColumnsStatement(ctx context.Context, stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ExecutionPlanner) compileShowCreateTableStatement(ctx context.Context, stmt *parser.ShowCreateTableStatement) (_ types.PlanOperator, err error) {
|
func (p *ExecutionPlanner) compileShowCreateTableStatement(ctx context.Context, stmt *parser.ShowCreateTableStatement) (_ types.PlanOperator, err error) {
|
||||||
tableName := parser.IdentName(stmt.TableName)
|
tableName := strings.ToLower(parser.IdentName(stmt.TableName))
|
||||||
tname := dax.TableName(tableName)
|
tname := dax.TableName(tableName)
|
||||||
if _, err := p.schemaAPI.TableByName(ctx, tname); err != nil {
|
if _, err := p.schemaAPI.TableByName(ctx, tname); err != nil {
|
||||||
if isTableNotFoundError(err) {
|
if isTableNotFoundError(err) {
|
||||||
|
|
|
||||||
|
|
@ -1170,7 +1170,7 @@ func (n *betweenOpPlanExpression) Evaluate(currentRow []interface{}) (interface{
|
||||||
|
|
||||||
switch rType := n.rhs.Type().(type) {
|
switch rType := n.rhs.Type().(type) {
|
||||||
case *parser.DataTypeRange:
|
case *parser.DataTypeRange:
|
||||||
switch rType.SubscriptType.(type) {
|
switch sType := rType.SubscriptType.(type) {
|
||||||
case *parser.DataTypeInt:
|
case *parser.DataTypeInt:
|
||||||
|
|
||||||
nl, nlok := evalLhs.(int64)
|
nl, nlok := evalLhs.(int64)
|
||||||
|
|
@ -1201,8 +1201,40 @@ func (n *betweenOpPlanExpression) Evaluate(currentRow []interface{}) (interface{
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
|
||||||
|
nl, nlok := evalLhs.(pql.Decimal)
|
||||||
|
if !(nlok) {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t'", nlok)
|
||||||
|
}
|
||||||
|
|
||||||
|
crl, err := coerceValue(exprRange.lhs.Type(), sType, rangeLower, parser.Pos{Line: 0, Column: 0})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rl, ok := crl.(pql.Decimal)
|
||||||
|
if !(ok) {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t'", crl)
|
||||||
|
}
|
||||||
|
|
||||||
|
cru, err := coerceValue(exprRange.rhs.Type(), sType, rangeUpper, parser.Pos{Line: 0, Column: 0})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ru, ok := cru.(pql.Decimal)
|
||||||
|
if !(ok) {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t'", cru)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := nl.GreaterThanOrEqualTo(rl) && nl.LessThanOrEqualTo(ru)
|
||||||
|
if n.op == parser.NOTBETWEEN {
|
||||||
|
result = !result
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, sql3.NewErrInternalf("unexpected range type '%T'", rType.SubscriptType)
|
return nil, sql3.NewErrInternalf("unexpected range type '%T'", sType)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -2560,7 +2592,7 @@ func (p *ExecutionPlanner) compileExpr(expr parser.Expr) (_ types.PlanExpression
|
||||||
return ref, nil
|
return ref, nil
|
||||||
|
|
||||||
case *parser.QualifiedRef:
|
case *parser.QualifiedRef:
|
||||||
ref := newQualifiedRefPlanExpression(parser.IdentName(expr.Table), parser.IdentName(expr.Column), expr.ColumnIndex, expr.DataType())
|
ref := newQualifiedRefPlanExpression(strings.ToLower(parser.IdentName(expr.Table)), strings.ToLower(parser.IdentName(expr.Column)), expr.ColumnIndex, expr.DataType())
|
||||||
return ref, nil
|
return ref, nil
|
||||||
|
|
||||||
case *parser.Range:
|
case *parser.Range:
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,15 @@ func (a *aggregateAvg) Update(ctx context.Context, row types.Row) error {
|
||||||
thisVal := pql.FromInt64(thisIVal, returnType.Scale)
|
thisVal := pql.FromInt64(thisIVal, returnType.Scale)
|
||||||
a.sum = pql.AddDecimal(thisVal, aggVal)
|
a.sum = pql.AddDecimal(thisVal, aggVal)
|
||||||
|
|
||||||
|
case *parser.DataTypeID:
|
||||||
|
thisIVal, ok := v.(uint64)
|
||||||
|
if !ok {
|
||||||
|
return sql3.NewErrInternalf("unexpected type conversion '%T'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
thisVal := pql.FromInt64(int64(thisIVal), returnType.Scale)
|
||||||
|
a.sum = pql.AddDecimal(thisVal, aggVal)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
||||||
}
|
}
|
||||||
|
|
@ -610,6 +619,21 @@ func (m *aggregateMin) Update(ctx context.Context, row types.Row) error {
|
||||||
m.val = thisVal
|
m.val = thisVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *parser.DataTypeString:
|
||||||
|
thisVal, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return sql3.NewErrInternalf("unexpected type conversion '%T'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
aggVal, ok := m.val.(string)
|
||||||
|
if !ok {
|
||||||
|
return sql3.NewErrInternalf("unexpected type conversion '%T'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if thisVal < aggVal {
|
||||||
|
m.val = thisVal
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
||||||
}
|
}
|
||||||
|
|
@ -752,6 +776,21 @@ func (m *aggregateMax) Update(ctx context.Context, row types.Row) error {
|
||||||
m.val = thisVal
|
m.val = thisVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *parser.DataTypeString:
|
||||||
|
thisVal, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return sql3.NewErrInternalf("unexpected type conversion '%T'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
aggVal, ok := m.val.(string)
|
||||||
|
if !ok {
|
||||||
|
return sql3.NewErrInternalf("unexpected type conversion '%T'", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if thisVal > aggVal {
|
||||||
|
m.val = thisVal
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
return sql3.NewErrInternalf("unhandled aggregate expression datatype '%T'", dataType)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -440,6 +440,19 @@ func (p *ExecutionPlanner) analyzeBinaryExpression(ctx context.Context, expr *pa
|
||||||
if !typeIsCompatibleWithEqualityOperator(y.DataType()) {
|
if !typeIsCompatibleWithEqualityOperator(y.DataType()) {
|
||||||
return nil, sql3.NewErrTypeIncompatibleWithEqualityOperator(y.Pos().Line, y.Pos().Column, op.String(), y.DataType().TypeDescription())
|
return nil, sql3.NewErrTypeIncompatibleWithEqualityOperator(y.Pos().Line, y.Pos().Column, op.String(), y.DataType().TypeDescription())
|
||||||
}
|
}
|
||||||
|
if typeIsTimestamp(x.DataType()) && y.IsLiteral() && typeIsString(y.DataType()) {
|
||||||
|
// we have a string literal on the rhs being compared to a date so
|
||||||
|
// try to convert to a date literal
|
||||||
|
rhs, ok := y.(*parser.StringLit)
|
||||||
|
if !ok {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected expression type '%T'", y)
|
||||||
|
}
|
||||||
|
newRhs := rhs.ConvertToTimestamp()
|
||||||
|
if newRhs != nil {
|
||||||
|
expr.Y = newRhs
|
||||||
|
y = newRhs
|
||||||
|
}
|
||||||
|
}
|
||||||
if !typesAreComparable(x.DataType(), y.DataType()) {
|
if !typesAreComparable(x.DataType(), y.DataType()) {
|
||||||
return nil, sql3.NewErrTypesAreNotEquatable(x.Pos().Line, x.Pos().Column, x.DataType().TypeDescription(), y.DataType().TypeDescription())
|
return nil, sql3.NewErrTypesAreNotEquatable(x.Pos().Line, x.Pos().Column, x.DataType().TypeDescription(), y.DataType().TypeDescription())
|
||||||
}
|
}
|
||||||
|
|
@ -794,11 +807,11 @@ func (p *ExecutionPlanner) analyzeRangeExpression(ctx context.Context, expr *par
|
||||||
if !typeCanBeUsedInRange(expr.Y.DataType()) {
|
if !typeCanBeUsedInRange(expr.Y.DataType()) {
|
||||||
return nil, sql3.NewErrTypeCannotBeUsedAsRangeSubscript(expr.Y.Pos().Line, expr.Y.Pos().Column, expr.Y.DataType().TypeDescription())
|
return nil, sql3.NewErrTypeCannotBeUsedAsRangeSubscript(expr.Y.Pos().Line, expr.Y.Pos().Column, expr.Y.DataType().TypeDescription())
|
||||||
}
|
}
|
||||||
if !typesOfRangeBoundsAreTheSame(expr.X.DataType(), expr.Y.DataType()) {
|
canbeUsed, coercedType := typesOfRangeBoundsAreTheSame(expr.X.DataType(), expr.Y.DataType())
|
||||||
|
if !canbeUsed {
|
||||||
return nil, sql3.NewErrIncompatibleTypesForRangeSubscripts(expr.Pos().Line, expr.Pos().Column, expr.X.DataType().TypeDescription(), expr.Y.DataType().TypeDescription())
|
return nil, sql3.NewErrIncompatibleTypesForRangeSubscripts(expr.Pos().Line, expr.Pos().Column, expr.X.DataType().TypeDescription(), expr.Y.DataType().TypeDescription())
|
||||||
}
|
}
|
||||||
|
expr.ResultDataType = parser.NewDataTypeRange(coercedType)
|
||||||
expr.ResultDataType = parser.NewDataTypeRange(expr.X.DataType())
|
|
||||||
|
|
||||||
return expr, nil
|
return expr, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,8 +165,8 @@ func (p *ExecutionPlanner) analyzeCallExpression(ctx context.Context, call *pars
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the ref is min/max-able
|
// make sure the ref is min/max-able
|
||||||
if !(typeIsInteger(ref.DataType()) || typeIsDecimal(ref.DataType()) || typeIsTimestamp(ref.DataType())) {
|
if !(typeIsInteger(ref.DataType()) || typeIsDecimal(ref.DataType()) || typeIsTimestamp(ref.DataType()) || typeIsString(ref.DataType())) {
|
||||||
return nil, sql3.NewErrIntOrDecimalOrTimestampExpressionExpected(ref.Table.NamePos.Line, ref.Table.NamePos.Column)
|
return nil, sql3.NewErrIntOrDecimalOrTimestampOrStringExpressionExpected(ref.Table.NamePos.Line, ref.Table.NamePos.Column)
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the data type of the referenced column
|
// return the data type of the referenced column
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,166 @@ func (p *ExecutionPlanner) generatePQLCallFromBinaryExpr(ctx context.Context, ex
|
||||||
Children: []*pql.Call{x, y},
|
Children: []*pql.Call{x, y},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case parser.EQ, parser.NE, parser.LT, parser.LE, parser.GT, parser.GE:
|
case parser.EQ:
|
||||||
|
lhs, ok := expr.lhs.(*qualifiedRefPlanExpression)
|
||||||
|
if !ok {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected lhs %T", expr.lhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pqlValue, err := planExprToValue(expr.rhs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typ := expr.lhs.Type().(type) {
|
||||||
|
case *parser.DataTypeInt:
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.EQ,
|
||||||
|
Value: pqlValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeID:
|
||||||
|
if strings.EqualFold(lhs.columnName, "_id") {
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "ConstRow",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
"columns": []interface{}{pqlValue},
|
||||||
|
},
|
||||||
|
Type: pql.PrecallGlobal,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: pqlValue,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeString:
|
||||||
|
if strings.EqualFold(lhs.columnName, "_id") {
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "ConstRow",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
"columns": []interface{}{pqlValue},
|
||||||
|
},
|
||||||
|
Type: pql.PrecallGlobal,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: pqlValue,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeTimestamp:
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.EQ,
|
||||||
|
Value: pqlValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeBool:
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: pqlValue,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
val, ok := pqlValue.(float64)
|
||||||
|
if !ok {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected type '%T", pqlValue)
|
||||||
|
}
|
||||||
|
d := pql.FromFloat64(val)
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.EQ,
|
||||||
|
Value: d,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, sql3.NewErrInternalf("unsupported type for binary expression: %v (%T)", typ, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
case parser.NE:
|
||||||
|
lhs, ok := expr.lhs.(*qualifiedRefPlanExpression)
|
||||||
|
if !ok {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected lhs %T", expr.lhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pqlValue, err := planExprToValue(expr.rhs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typ := expr.lhs.Type().(type) {
|
||||||
|
case *parser.DataTypeInt:
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.NEQ,
|
||||||
|
Value: pqlValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeID:
|
||||||
|
return nil, sql3.NewErrUnsupported(0, 0, true, "not equal operator on id typed columns")
|
||||||
|
|
||||||
|
case *parser.DataTypeString:
|
||||||
|
return nil, sql3.NewErrUnsupported(0, 0, true, "not equal operator on string typed columns")
|
||||||
|
|
||||||
|
case *parser.DataTypeTimestamp:
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.NEQ,
|
||||||
|
Value: pqlValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case *parser.DataTypeBool:
|
||||||
|
return nil, sql3.NewErrUnsupported(0, 0, true, "not equal operator on bool typed columns")
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
val, ok := pqlValue.(float64)
|
||||||
|
if !ok {
|
||||||
|
return nil, sql3.NewErrInternalf("unexpected type '%T", pqlValue)
|
||||||
|
}
|
||||||
|
d := pql.FromFloat64(val)
|
||||||
|
return &pql.Call{
|
||||||
|
Name: "Row",
|
||||||
|
Args: map[string]interface{}{
|
||||||
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pql.NEQ,
|
||||||
|
Value: d,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, sql3.NewErrInternalf("unsupported type for binary expression: %v (%T)", typ, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
case parser.LT, parser.LE, parser.GT, parser.GE:
|
||||||
lhs, ok := expr.lhs.(*qualifiedRefPlanExpression)
|
lhs, ok := expr.lhs.(*qualifiedRefPlanExpression)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, sql3.NewErrInternalf("unexpected lhs %T", expr.lhs)
|
return nil, sql3.NewErrInternalf("unexpected lhs %T", expr.lhs)
|
||||||
|
|
@ -208,82 +367,32 @@ func (p *ExecutionPlanner) generatePQLCallFromBinaryExpr(ctx context.Context, ex
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case *parser.DataTypeID:
|
case *parser.DataTypeID:
|
||||||
// TODO (pok) range queries on _id are not supported
|
return nil, sql3.NewErrUnsupported(0, 0, false, "range queries on id typed columns")
|
||||||
if strings.EqualFold(lhs.columnName, "_id") {
|
|
||||||
cr := &pql.Call{
|
|
||||||
Name: "ConstRow",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
"columns": []interface{}{pqlValue},
|
|
||||||
},
|
|
||||||
Type: pql.PrecallGlobal,
|
|
||||||
}
|
|
||||||
// TODO (pok) when we fix FB-1828 (https://molecula.atlassian.net/browse/FB-1828)
|
|
||||||
// we can remove this - ConstRow returns a ghost record, thus to eliminate
|
|
||||||
// we interset with All
|
|
||||||
return &pql.Call{
|
|
||||||
Name: "Intersect",
|
|
||||||
Children: []*pql.Call{
|
|
||||||
{
|
|
||||||
Name: "All",
|
|
||||||
},
|
|
||||||
cr,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return &pql.Call{
|
|
||||||
Name: "Row",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
lhs.columnName: pqlValue,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
case *parser.DataTypeString:
|
case *parser.DataTypeString:
|
||||||
// TODO (pok) range queries on _id are not supported
|
return nil, sql3.NewErrUnsupported(0, 0, false, "range queries on string typed columns")
|
||||||
if strings.EqualFold(lhs.columnName, "_id") {
|
|
||||||
cr := &pql.Call{
|
case *parser.DataTypeTimestamp:
|
||||||
Name: "ConstRow",
|
pqlOp, err := sqlToPQLOp(op)
|
||||||
Args: map[string]interface{}{
|
if err != nil {
|
||||||
"columns": []interface{}{pqlValue},
|
return nil, err
|
||||||
},
|
|
||||||
Type: pql.PrecallGlobal,
|
|
||||||
}
|
|
||||||
// TODO (pok) when we fix FB-1828 (https://molecula.atlassian.net/browse/FB-1828)
|
|
||||||
// we can remove this - ConstRow returns a ghost record, thus to eliminate
|
|
||||||
// we interset with All
|
|
||||||
return &pql.Call{
|
|
||||||
Name: "Intersect",
|
|
||||||
Children: []*pql.Call{
|
|
||||||
{
|
|
||||||
Name: "All",
|
|
||||||
},
|
|
||||||
cr,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
return &pql.Call{
|
return &pql.Call{
|
||||||
Name: "Row",
|
Name: "Row",
|
||||||
Args: map[string]interface{}{
|
Args: map[string]interface{}{
|
||||||
lhs.columnName: pqlValue,
|
lhs.columnName: &pql.Condition{
|
||||||
},
|
Op: pqlOp,
|
||||||
}, nil
|
Value: pqlValue,
|
||||||
|
},
|
||||||
case *parser.DataTypeTimestamp:
|
|
||||||
return &pql.Call{
|
|
||||||
Name: "Row",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
lhs.columnName: pqlValue,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
case *parser.DataTypeBool:
|
|
||||||
return &pql.Call{
|
|
||||||
Name: "Row",
|
|
||||||
Args: map[string]interface{}{
|
|
||||||
lhs.columnName: pqlValue,
|
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case *parser.DataTypeDecimal:
|
case *parser.DataTypeDecimal:
|
||||||
|
|
||||||
|
pqlOp, err := sqlToPQLOp(op)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
val, ok := pqlValue.(float64)
|
val, ok := pqlValue.(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, sql3.NewErrInternalf("unexpected type '%T", pqlValue)
|
return nil, sql3.NewErrInternalf("unexpected type '%T", pqlValue)
|
||||||
|
|
@ -292,7 +401,10 @@ func (p *ExecutionPlanner) generatePQLCallFromBinaryExpr(ctx context.Context, ex
|
||||||
return &pql.Call{
|
return &pql.Call{
|
||||||
Name: "Row",
|
Name: "Row",
|
||||||
Args: map[string]interface{}{
|
Args: map[string]interface{}{
|
||||||
lhs.columnName: d,
|
lhs.columnName: &pql.Condition{
|
||||||
|
Op: pqlOp,
|
||||||
|
Value: d,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,20 +181,34 @@ func typesAreRangeComparable(testTypeL parser.ExprDataType, testTypeR parser.Exp
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false, sql3.NewErrInternalf("unhandled rhs type '%T' for lhs type '%T'", rhsType, lhsType)
|
return false, sql3.NewErrInternalf("unhandled rhs type '%T' for lhs type '%T'", rhsType, lhsType)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case *parser.DataTypeInt, *parser.DataTypeID:
|
case *parser.DataTypeInt, *parser.DataTypeID:
|
||||||
switch lhsType := testTypeL.(type) {
|
switch lhsType := testTypeL.(type) {
|
||||||
case *parser.DataTypeID:
|
case *parser.DataTypeID:
|
||||||
return true, nil
|
return true, nil
|
||||||
case *parser.DataTypeInt:
|
case *parser.DataTypeInt:
|
||||||
return true, nil
|
return true, nil
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
// change subscript type to be decimal
|
||||||
|
rhsType.SubscriptType = lhsType
|
||||||
|
return true, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false, sql3.NewErrInternalf("unhandled rhs type '%T' for lhs type '%T'", rhsType, lhsType)
|
return false, sql3.NewErrInternalf("unhandled rhs type '%T' for lhs type '%T'", rhsType, lhsType)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
switch lhsType := testTypeL.(type) {
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, sql3.NewErrInternalf("unhandled rhs type '%T' for lhs type '%T'", rhsType, lhsType)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false, sql3.NewErrInternalf("type '%T' is not a range type", rhsType)
|
return false, sql3.NewErrInternalf("type '%T' is not a range type", rhsType)
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +377,7 @@ func typesAreAssignmentCompatible(targetType parser.ExprDataType, sourceType par
|
||||||
// returns true if the type can be used as a range subscript
|
// returns true if the type can be used as a range subscript
|
||||||
func typeCanBeUsedInRange(testType parser.ExprDataType) bool {
|
func typeCanBeUsedInRange(testType parser.ExprDataType) bool {
|
||||||
switch testType.(type) {
|
switch testType.(type) {
|
||||||
case *parser.DataTypeID, *parser.DataTypeInt, *parser.DataTypeTimestamp:
|
case *parser.DataTypeID, *parser.DataTypeInt, *parser.DataTypeTimestamp, *parser.DataTypeDecimal:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|
@ -371,43 +385,62 @@ func typeCanBeUsedInRange(testType parser.ExprDataType) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the types can be considered the same when used as a range bounds
|
// returns true if the types can be considered the same when used as a range bounds
|
||||||
func typesOfRangeBoundsAreTheSame(testTypeL parser.ExprDataType, testTypeR parser.ExprDataType) bool {
|
func typesOfRangeBoundsAreTheSame(testTypeL parser.ExprDataType, testTypeR parser.ExprDataType) (bool, parser.ExprDataType) {
|
||||||
switch testTypeL.(type) {
|
switch testTypeL.(type) {
|
||||||
case *parser.DataTypeInt:
|
case *parser.DataTypeInt:
|
||||||
switch testTypeR.(type) {
|
switch testTypeR.(type) {
|
||||||
case *parser.DataTypeInt:
|
case *parser.DataTypeInt:
|
||||||
return true
|
return true, testTypeL
|
||||||
|
|
||||||
case *parser.DataTypeID:
|
case *parser.DataTypeID:
|
||||||
return true
|
return true, testTypeL
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
// 'widen' both to decimal
|
||||||
|
return true, testTypeR
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case *parser.DataTypeID:
|
case *parser.DataTypeID:
|
||||||
switch testTypeR.(type) {
|
switch testTypeR.(type) {
|
||||||
case *parser.DataTypeID:
|
case *parser.DataTypeID:
|
||||||
return true
|
return true, testTypeL
|
||||||
|
|
||||||
case *parser.DataTypeInt:
|
case *parser.DataTypeInt:
|
||||||
return true
|
return true, testTypeL
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case *parser.DataTypeTimestamp:
|
case *parser.DataTypeTimestamp:
|
||||||
switch testTypeR.(type) {
|
switch testTypeR.(type) {
|
||||||
case *parser.DataTypeTimestamp:
|
case *parser.DataTypeTimestamp:
|
||||||
return true
|
return true, testTypeL
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
switch testTypeR.(type) {
|
||||||
|
case *parser.DataTypeInt:
|
||||||
|
return true, testTypeL
|
||||||
|
|
||||||
|
case *parser.DataTypeID:
|
||||||
|
return true, testTypeL
|
||||||
|
|
||||||
|
case *parser.DataTypeDecimal:
|
||||||
|
return true, testTypeL
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,6 @@ func (p *PlanOpFeatureBaseColumns) Schema() types.Schema {
|
||||||
ColumnName: "type",
|
ColumnName: "type",
|
||||||
Type: parser.NewDataTypeString(),
|
Type: parser.NewDataTypeString(),
|
||||||
},
|
},
|
||||||
&types.PlannerColumn{
|
|
||||||
RelationName: "fb_table_columns",
|
|
||||||
ColumnName: "internal_type",
|
|
||||||
Type: parser.NewDataTypeString(),
|
|
||||||
},
|
|
||||||
&types.PlannerColumn{
|
&types.PlannerColumn{
|
||||||
RelationName: "fb_table_columns",
|
RelationName: "fb_table_columns",
|
||||||
ColumnName: "created_at",
|
ColumnName: "created_at",
|
||||||
|
|
@ -156,7 +151,6 @@ func (i *showColumnsRowIter) Next(ctx context.Context) (types.Row, error) {
|
||||||
fields[i.rowIndex].Name,
|
fields[i.rowIndex].Name,
|
||||||
fields[i.rowIndex].Name,
|
fields[i.rowIndex].Name,
|
||||||
fields[i.rowIndex].Type,
|
fields[i.rowIndex].Type,
|
||||||
fields[i.rowIndex].Type,
|
|
||||||
tm.Format(time.RFC3339),
|
tm.Format(time.RFC3339),
|
||||||
fields[i.rowIndex].StringKeys(),
|
fields[i.rowIndex].StringKeys(),
|
||||||
fields[i.rowIndex].Options.CacheType,
|
fields[i.rowIndex].Options.CacheType,
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ var systemTables = map[string]*systemTable{
|
||||||
&types.PlannerColumn{
|
&types.PlannerColumn{
|
||||||
RelationName: fbClusterNodes,
|
RelationName: fbClusterNodes,
|
||||||
ColumnName: "space_used",
|
ColumnName: "space_used",
|
||||||
Type: parser.NewDataTypeBool(),
|
Type: parser.NewDataTypeInt(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
requiresFanout: false,
|
requiresFanout: false,
|
||||||
|
|
|
||||||
|
|
@ -636,6 +636,18 @@ func tryToReplaceGroupByWithPQLAggregate(ctx context.Context, a *ExecutionPlanne
|
||||||
return thisNode, true, nil
|
return thisNode, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure all the aggregates are bsi types
|
||||||
|
for _, agg := range thisNode.Aggregates {
|
||||||
|
aggregable, ok := agg.(types.Aggregable)
|
||||||
|
if !ok {
|
||||||
|
return n, false, sql3.NewErrInternalf("unexpected aggregate function arg type '%T'", agg)
|
||||||
|
}
|
||||||
|
switch aggregable.AggExpression().Type().(type) {
|
||||||
|
case *parser.DataTypeID, *parser.DataTypeString:
|
||||||
|
return thisNode, true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ops := make([]*PlanOpPQLAggregate, 0)
|
ops := make([]*PlanOpPQLAggregate, 0)
|
||||||
|
|
||||||
for _, agg := range thisNode.Aggregates {
|
for _, agg := range thisNode.Aggregates {
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ func TestPlanner_Show(t *testing.T) {
|
||||||
wireQueryFieldString("uri"),
|
wireQueryFieldString("uri"),
|
||||||
wireQueryFieldString("grpc_uri"),
|
wireQueryFieldString("grpc_uri"),
|
||||||
wireQueryFieldBool("is_primary"),
|
wireQueryFieldBool("is_primary"),
|
||||||
wireQueryFieldBool("space_used"),
|
wireQueryFieldInt("space_used"),
|
||||||
}, columns); diff != "" {
|
}, columns); diff != "" {
|
||||||
t.Fatal(diff)
|
t.Fatal(diff)
|
||||||
}
|
}
|
||||||
|
|
@ -318,7 +318,6 @@ func TestPlanner_Show(t *testing.T) {
|
||||||
wireQueryFieldString("_id"),
|
wireQueryFieldString("_id"),
|
||||||
wireQueryFieldString("name"),
|
wireQueryFieldString("name"),
|
||||||
wireQueryFieldString("type"),
|
wireQueryFieldString("type"),
|
||||||
wireQueryFieldString("internal_type"),
|
|
||||||
wireQueryFieldTimestamp("created_at"),
|
wireQueryFieldTimestamp("created_at"),
|
||||||
wireQueryFieldBool("keys"),
|
wireQueryFieldBool("keys"),
|
||||||
wireQueryFieldString("cache_type"),
|
wireQueryFieldString("cache_type"),
|
||||||
|
|
@ -348,7 +347,6 @@ func TestPlanner_Show(t *testing.T) {
|
||||||
wireQueryFieldString("_id"),
|
wireQueryFieldString("_id"),
|
||||||
wireQueryFieldString("name"),
|
wireQueryFieldString("name"),
|
||||||
wireQueryFieldString("type"),
|
wireQueryFieldString("type"),
|
||||||
wireQueryFieldString("internal_type"),
|
|
||||||
wireQueryFieldTimestamp("created_at"),
|
wireQueryFieldTimestamp("created_at"),
|
||||||
wireQueryFieldBool("keys"),
|
wireQueryFieldBool("keys"),
|
||||||
wireQueryFieldString("cache_type"),
|
wireQueryFieldString("cache_type"),
|
||||||
|
|
@ -688,6 +686,20 @@ func TestPlanner_CreateTable(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("CreateTableMixedCaseColumn", func(t *testing.T) {
|
||||||
|
_, _, err := sql_test.MustQueryRows(t, server, `create table lowercase (_id id, name string, SomeColumn string, legalname string);`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("CreateTableMixedCaseColumn", func(t *testing.T) {
|
||||||
|
_, _, err := sql_test.MustQueryRows(t, server, `create table MixedCcase (_id id, name string, SomeColumn string, legalname string);`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("DropTable1", func(t *testing.T) {
|
t.Run("DropTable1", func(t *testing.T) {
|
||||||
_, _, err := sql_test.MustQueryRows(t, server, `drop table allcoltypes`)
|
_, _, err := sql_test.MustQueryRows(t, server, `drop table allcoltypes`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -730,7 +742,6 @@ func TestPlanner_CreateTable(t *testing.T) {
|
||||||
wireQueryFieldString("_id"),
|
wireQueryFieldString("_id"),
|
||||||
wireQueryFieldString("name"),
|
wireQueryFieldString("name"),
|
||||||
wireQueryFieldString("type"),
|
wireQueryFieldString("type"),
|
||||||
wireQueryFieldString("internal_type"),
|
|
||||||
wireQueryFieldTimestamp("created_at"),
|
wireQueryFieldTimestamp("created_at"),
|
||||||
wireQueryFieldBool("keys"),
|
wireQueryFieldBool("keys"),
|
||||||
wireQueryFieldString("cache_type"),
|
wireQueryFieldString("cache_type"),
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@ var TableTests []TableTest = []TableTest{
|
||||||
selectTests,
|
selectTests,
|
||||||
selectKeyedTests,
|
selectKeyedTests,
|
||||||
selectHavingTests,
|
selectHavingTests,
|
||||||
|
filterPredicates,
|
||||||
|
filterPredicatesIdKey,
|
||||||
|
filterPredicatesId,
|
||||||
|
filterPredicatesInt,
|
||||||
|
filterPredicatesBool,
|
||||||
|
filterPredicatesTimestamp,
|
||||||
|
filterPredicatesDecimal,
|
||||||
|
filterPredicatesString,
|
||||||
orderByTests,
|
orderByTests,
|
||||||
distinctTests,
|
distinctTests,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -288,14 +288,15 @@ var avgTests = TableTest{
|
||||||
srcHdr("i1", fldTypeInt, "min 0", "max 1000"),
|
srcHdr("i1", fldTypeInt, "min 0", "max 1000"),
|
||||||
srcHdr("d1", fldTypeDecimal2),
|
srcHdr("d1", fldTypeDecimal2),
|
||||||
srcHdr("s1", fldTypeString),
|
srcHdr("s1", fldTypeString),
|
||||||
|
srcHdr("id1", fldTypeID),
|
||||||
),
|
),
|
||||||
srcRows(
|
srcRows(
|
||||||
srcRow(int64(1), int64(10), float64(10), string("foo")),
|
srcRow(int64(1), int64(10), float64(10), string("foo"), int64(10)),
|
||||||
srcRow(int64(2), int64(10), float64(10), string("foo")),
|
srcRow(int64(2), int64(10), float64(10), string("foo"), int64(11)),
|
||||||
srcRow(int64(3), int64(11), float64(11), string("foo")),
|
srcRow(int64(3), int64(11), float64(11), string("foo"), int64(12)),
|
||||||
srcRow(int64(4), int64(12), float64(12), string("foo")),
|
srcRow(int64(4), int64(12), float64(12), string("foo"), int64(13)),
|
||||||
srcRow(int64(5), int64(12), float64(12), string("foo")),
|
srcRow(int64(5), int64(12), float64(12), string("foo"), int64(14)),
|
||||||
srcRow(int64(6), int64(13), float64(13), string("foo")),
|
srcRow(int64(6), int64(13), float64(13), string("foo"), int64(15)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SQLTests: []SQLTest{
|
SQLTests: []SQLTest{
|
||||||
|
|
@ -323,6 +324,22 @@ var avgTests = TableTest{
|
||||||
),
|
),
|
||||||
ExpErr: "integer or decimal expression expected",
|
ExpErr: "integer or decimal expression expected",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"SELECT avg(id1) AS avg_rows FROM avg_test",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("avg_rows", featurebase.WireQueryField{
|
||||||
|
Type: dax.BaseTypeDecimal + "(4)",
|
||||||
|
BaseType: dax.BaseTypeDecimal,
|
||||||
|
TypeInfo: map[string]interface{}{"scale": int64(4)},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(pql.NewDecimal(125000, 4)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"SELECT avg(i1) AS avg_rows FROM avg_test",
|
"SELECT avg(i1) AS avg_rows FROM avg_test",
|
||||||
|
|
@ -430,12 +447,12 @@ var minmaxTests = TableTest{
|
||||||
srcHdr("ts1", fldTypeTimestamp),
|
srcHdr("ts1", fldTypeTimestamp),
|
||||||
),
|
),
|
||||||
srcRows(
|
srcRows(
|
||||||
srcRow(int64(1), int64(10), float64(10), string("foo"), timestampFromString("2013-07-15T01:18:46Z")),
|
srcRow(int64(1), int64(10), float64(10), string("afoo"), timestampFromString("2013-07-15T01:18:46Z")),
|
||||||
srcRow(int64(2), int64(10), float64(10), string("foo"), timestampFromString("2014-07-15T01:18:46Z")),
|
srcRow(int64(2), int64(10), float64(10), string("bfoo"), timestampFromString("2014-07-15T01:18:46Z")),
|
||||||
srcRow(int64(3), int64(11), float64(11), string("foo"), timestampFromString("2015-07-15T01:18:46Z")),
|
srcRow(int64(3), int64(11), float64(11), string("cfoo"), timestampFromString("2015-07-15T01:18:46Z")),
|
||||||
srcRow(int64(4), int64(12), float64(12), string("foo"), timestampFromString("2016-07-15T01:18:46Z")),
|
srcRow(int64(4), int64(12), float64(12), string("dfoo"), timestampFromString("2016-07-15T01:18:46Z")),
|
||||||
srcRow(int64(5), int64(12), float64(12), string("foo"), timestampFromString("2017-07-15T01:18:46Z")),
|
srcRow(int64(5), int64(12), float64(12), string("efoo"), timestampFromString("2017-07-15T01:18:46Z")),
|
||||||
srcRow(int64(6), int64(13), float64(13), string("foo"), timestampFromString("2018-07-15T01:18:46Z")),
|
srcRow(int64(6), int64(13), float64(13), string("ffoo"), timestampFromString("2018-07-15T01:18:46Z")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SQLTests: []SQLTest{
|
SQLTests: []SQLTest{
|
||||||
|
|
@ -470,9 +487,26 @@ var minmaxTests = TableTest{
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"SELECT min(s1) AS p_rows FROM minmax_test",
|
"SELECT min(s1) AS p_rows FROM minmax_test",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("p_rows", fldTypeString),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(string("afoo")),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
"SELECT max(s1) AS p_rows FROM minmax_test",
|
"SELECT max(s1) AS p_rows FROM minmax_test",
|
||||||
),
|
),
|
||||||
ExpErr: "integer, decimal or timestamp expression expected",
|
ExpHdrs: hdrs(
|
||||||
|
hdr("p_rows", fldTypeString),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(string("ffoo")),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,18 @@ var betweenTests = TableTest{
|
||||||
),
|
),
|
||||||
Compare: CompareExactUnordered,
|
Compare: CompareExactUnordered,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select d1 between 10 and 15 from between_all_types",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("", fldTypeBool),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(bool(true)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"select b1 between true and false from between_all_types",
|
"select b1 between true and false from between_all_types",
|
||||||
|
|
@ -54,7 +66,13 @@ var betweenTests = TableTest{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"select d1 between 1.23 and 4.56 from between_all_types",
|
"select d1 between 1.23 and 4.56 from between_all_types",
|
||||||
),
|
),
|
||||||
ExpErr: "type 'decimal(2)' cannot be used as a range subscript",
|
ExpHdrs: hdrs(
|
||||||
|
hdr("", fldTypeBool),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(bool(false)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
|
|
@ -145,6 +163,18 @@ var notBetweenTests = TableTest{
|
||||||
),
|
),
|
||||||
Compare: CompareExactUnordered,
|
Compare: CompareExactUnordered,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select d1 not between 10 and 15 from between_all_types",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("", fldTypeBool),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(bool(false)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"select b1 not between true and false from not_between_all_types",
|
"select b1 not between true and false from not_between_all_types",
|
||||||
|
|
@ -155,7 +185,13 @@ var notBetweenTests = TableTest{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
"select d1 not between 1.23 and 4.56 from not_between_all_types",
|
"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",
|
ExpHdrs: hdrs(
|
||||||
|
hdr("", fldTypeBool),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(bool(true)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQLs: sqls(
|
SQLs: sqls(
|
||||||
|
|
|
||||||
507
sql3/test/defs/defs_filterpredicates.go
Normal file
507
sql3/test/defs/defs_filterpredicates.go
Normal file
|
|
@ -0,0 +1,507 @@
|
||||||
|
package defs
|
||||||
|
|
||||||
|
var filterPredicates = TableTest{
|
||||||
|
Table: tbl(
|
||||||
|
"filter_predicates",
|
||||||
|
srcHdrs(
|
||||||
|
srcHdr("_id", fldTypeID),
|
||||||
|
srcHdr("i1", fldTypeInt),
|
||||||
|
srcHdr("b1", fldTypeBool),
|
||||||
|
srcHdr("id1", fldTypeID),
|
||||||
|
srcHdr("ids1", fldTypeIDSet),
|
||||||
|
srcHdr("d1", fldTypeDecimal2),
|
||||||
|
srcHdr("s1", fldTypeString),
|
||||||
|
srcHdr("ss1", fldTypeStringSet),
|
||||||
|
srcHdr("ts1", fldTypeTimestamp),
|
||||||
|
),
|
||||||
|
srcRows(
|
||||||
|
srcRow(int64(1), int64(10), bool(false), int64(1), []int64{10, 20, 30}, float64(10.00), string("10"), []string{"10", "20", "30"}, string("2001-11-01T22:08:41+00:00")),
|
||||||
|
srcRow(int64(2), int64(20), bool(true), int64(2), []int64{11, 21, 31}, float64(20.00), string("20"), []string{"11", "21", "31"}, string("2002-11-01T22:08:41+00:00")),
|
||||||
|
srcRow(int64(3), int64(30), bool(false), int64(3), []int64{12, 22, 32}, float64(30.00), string("30"), []string{"12", "22", "32"}, string("2003-11-01T22:08:41+00:00")),
|
||||||
|
srcRow(int64(4), int64(40), bool(false), int64(4), []int64{10, 20, 30}, float64(40.00), string("40"), []string{"10", "20", "30"}, string("2004-11-01T22:08:41+00:00")),
|
||||||
|
srcRow(int64(5), int64(50), bool(true), int64(5), []int64{11, 21, 31}, float64(50.00), string("50"), []string{"11", "21", "31"}, string("2005-11-01T22:08:41+00:00")),
|
||||||
|
srcRow(int64(6), int64(60), bool(false), int64(6), []int64{12, 22, 32}, float64(60.00), string("60"), []string{"12", "22", "32"}, string("2006-11-01T22:08:41+00:00")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesIdKey = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id != 1",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id = 1",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id > 5",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id >= 5",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id < 2",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where _id <= 2",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(2)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesId = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 != 1",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 = 1",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 > 5",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 >= 5",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 < 2",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where id1 <= 2",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(2)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesInt = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 != 10",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 = 10",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 > 50",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 >= 50",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 < 20",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where i1 <= 20",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(2)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesBool = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where b1 != true",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where b1 = true",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(5)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesTimestamp = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 != '2001-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 = '2001-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 > '2005-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 >= '2005-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 < '2002-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where ts1 <= '2002-11-01T22:08:41+00:00'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(2)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesDecimal = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 != 10.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 = 10.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 > 50.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 >= 50.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 < 20.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where d1 <= 20.00",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
row(int64(2)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterPredicatesString = TableTest{
|
||||||
|
SQLTests: []SQLTest{
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where s1 != '10'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(2)),
|
||||||
|
row(int64(3)),
|
||||||
|
row(int64(4)),
|
||||||
|
row(int64(5)),
|
||||||
|
row(int64(6)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SQLs: sqls(
|
||||||
|
"select _id from filter_predicates where s1 = '10'",
|
||||||
|
),
|
||||||
|
ExpHdrs: hdrs(
|
||||||
|
hdr("_id", fldTypeID),
|
||||||
|
),
|
||||||
|
ExpRows: rows(
|
||||||
|
row(int64(1)),
|
||||||
|
),
|
||||||
|
Compare: CompareExactUnordered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue