diff --git a/db/check.go b/db/check.go index 146b13ac..d4cca2a3 100644 --- a/db/check.go +++ b/db/check.go @@ -24,12 +24,25 @@ import ( func (d *document) check(ctx context.Context, cond sql.Expr) (ok bool, err error) { - val, err := d.i.e.fetch(ctx, cond, d.current) - if val, ok := val.(bool); ok { - return val, err + // If no condition expression has been + // defined then we can ignore this, and + // process the current document. + + if cond == nil { + return true, nil } - return true, err + // If a condition expression has been + // defined then let's process it to see + // what value it returns or error. + + val, err := d.i.e.fetch(ctx, cond, d.current) + + // If the condition expression result is + // not a boolean value, then let's see + // if the value can be equated to a bool. + + return calcAsBool(val), err } diff --git a/db/fetch.go b/db/fetch.go index e2b707ae..edec04ee 100644 --- a/db/fetch.go +++ b/db/fetch.go @@ -20,6 +20,7 @@ import ( "reflect" "regexp" "strconv" + "strings" "time" "github.com/abcum/surreal/cnf" @@ -36,6 +37,8 @@ func (e *executor) fetch(ctx context.Context, val interface{}, doc *data.Doc) (o switch val := val.(type) { default: return val, nil + case *sql.Null: + return nil, nil case *sql.Thing: return val, nil case *sql.Value: @@ -202,7 +205,13 @@ func (e *executor) fetch(ctx context.Context, val interface{}, doc *data.Doc) (o return binaryBool(val.Op, l, r), nil case sql.ADD, sql.SUB, sql.MUL, sql.DIV, sql.INC, sql.DEC: return binaryMath(val.Op, l, r), nil - case sql.EQ, sql.NEQ, sql.ANY, sql.LT, sql.LTE, sql.GT, sql.GTE, sql.SIN, sql.SNI, sql.INS, sql.NIS: + case sql.EQ, sql.NEQ, sql.ANY, sql.LT, sql.LTE, sql.GT, sql.GTE: + return binaryCheck(val.Op, l, r, val.LHS, val.RHS, doc), nil + case sql.SIN, sql.SNI, sql.INS, sql.NIS: + return binaryCheck(val.Op, l, r, val.LHS, val.RHS, doc), nil + case sql.CONTAINSALL, sql.CONTAINSSOME, sql.CONTAINSNONE: + return binaryCheck(val.Op, l, r, val.LHS, val.RHS, doc), nil + case sql.ALLCONTAINEDIN, sql.SOMECONTAINEDIN, sql.NONECONTAINEDIN: return binaryCheck(val.Op, l, r, val.LHS, val.RHS, doc), nil } @@ -228,8 +237,11 @@ func (e *executor) fetchPaths(ctx context.Context, doc *data.Doc, exprs ...sql.E case sql.DOT: return e.fetchPaths(ctx, doc, exprs...) case sql.OEDGE: + return nil, featureNotImplemented case sql.IEDGE: + return nil, featureNotImplemented case sql.BEDGE: + return nil, featureNotImplemented } case *sql.PartExpression: switch val := val.Part.(type) { @@ -443,62 +455,42 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ switch lo.(type) { case *sql.Void: switch ro.(type) { - default: - return op == sql.NEQ - case nil: + case *sql.Null: return op == sql.NEQ case *sql.Void: return op == sql.EQ case *sql.Empty: return op == sql.EQ - case *sql.Ident: - break } case *sql.Empty: switch ro.(type) { - default: - return op == sql.NEQ - case nil: + case *sql.Null: return op == sql.EQ case *sql.Void: return op == sql.EQ case *sql.Empty: return op == sql.EQ - case *sql.Param: - break - case *sql.Ident: - break } } switch ro.(type) { case *sql.Void: switch lo.(type) { - default: - return op == sql.NEQ - case nil: + case *sql.Null: return op == sql.NEQ case *sql.Void: return op == sql.EQ case *sql.Empty: return op == sql.EQ - case *sql.Ident: - break } case *sql.Empty: switch lo.(type) { - default: - return op == sql.NEQ - case nil: + case *sql.Null: return op == sql.EQ case *sql.Void: return op == sql.EQ case *sql.Empty: return op == sql.EQ - case *sql.Param: - break - case *sql.Ident: - break } } @@ -523,7 +515,7 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return d.Exists(r.ID) == true && d.Get(r.ID).Data() != nil } } - case nil: + case *sql.Null: switch r := ro.(type) { case *sql.Ident: if op == sql.EQ { @@ -553,7 +545,7 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return d.Exists(l.ID) == true && d.Get(l.ID).Data() != nil } } - case nil: + case *sql.Null: switch l := lo.(type) { case *sql.Ident: if op == sql.EQ { @@ -568,20 +560,36 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ switch l := l.(type) { - case *sql.Empty: - switch r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE - case nil: - return op == sql.EQ - } - case nil: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case nil: return op == sql.EQ + case *sql.Null: + return op == sql.EQ + case *sql.Empty: + return op == sql.EQ + case []interface{}: + return chkArrayR(op, l, r) + } + + case *sql.Null: + switch r := r.(type) { + case nil: + return op == sql.EQ + case *sql.Null: + return op == sql.EQ + case *sql.Empty: + return op == sql.EQ + case []interface{}: + return chkArrayR(op, l, r) + } + + case *sql.Empty: + switch r := r.(type) { + case nil: + return op == sql.EQ + case *sql.Null: + return op == sql.EQ case *sql.Empty: return op == sql.EQ case []interface{}: @@ -592,8 +600,6 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ case *sql.Thing: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case *sql.Thing: return chkThing(op, l, r) case string: @@ -604,44 +610,34 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ case bool: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case bool: return chkBool(op, l, r) case string: if b, err := strconv.ParseBool(r); err == nil { return chkBool(op, l, b) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case *regexp.Regexp: return chkRegex(op, strconv.FormatBool(l), r) case []interface{}: return chkArrayR(op, l, r) - case map[string]interface{}: - return chkObject(op, r, l) } case string: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case bool: if b, err := strconv.ParseBool(l); err == nil { return chkBool(op, r, b) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case string: return chkString(op, l, r) case int64: if n, err := strconv.ParseInt(l, 10, 64); err == nil { return chkInt(op, r, n) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case float64: if n, err := strconv.ParseFloat(l, 64); err == nil { return chkFloat(op, r, n) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case time.Time: return chkString(op, l, r.String()) case *sql.Thing: @@ -650,19 +646,14 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return chkRegex(op, l, r) case []interface{}: return chkArrayR(op, l, r) - case map[string]interface{}: - return chkObject(op, r, l) } case int64: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case string: if n, err := strconv.ParseInt(r, 10, 64); err == nil { return chkInt(op, l, n) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case int64: return chkInt(op, l, r) case float64: @@ -673,19 +664,14 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return chkRegex(op, strconv.FormatInt(l, 10), r) case []interface{}: return chkArrayR(op, l, r) - case map[string]interface{}: - return chkObject(op, r, l) } case float64: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case string: if n, err := strconv.ParseFloat(r, 64); err == nil { return chkFloat(op, l, n) } - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case int64: return chkFloat(op, l, float64(r)) case float64: @@ -696,14 +682,10 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return chkRegex(op, strconv.FormatFloat(l, 'g', -1, 64), r) case []interface{}: return chkArrayR(op, l, r) - case map[string]interface{}: - return chkObject(op, r, l) } case time.Time: switch r := r.(type) { - default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE case string: return chkString(op, l.String(), r) case int64: @@ -716,8 +698,6 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ return chkRegex(op, l.String(), r) case []interface{}: return chkArrayR(op, l, r) - case map[string]interface{}: - return chkObject(op, r, l) } case []interface{}: @@ -745,7 +725,7 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ case map[string]interface{}: switch r := r.(type) { default: - return op == sql.NEQ || op == sql.SNI || op == sql.NIS || op == sql.CONTAINSNONE + return chkObject(op, l, r) case []interface{}: return chkArrayR(op, l, r) case map[string]interface{}: @@ -754,16 +734,39 @@ func binaryCheck(op sql.Token, l, r, lo, ro interface{}, d *data.Doc) interface{ } - return nil + return negOp(op) } -func chkVoid(op sql.Token, a, b bool) (val bool) { - return +func posOp(op sql.Token) bool { + return chkOp(op) > 1 } -func chkNull(op sql.Token, a, b bool) (val bool) { - return +func negOp(op sql.Token) bool { + return chkOp(op) < 0 +} + +func chkOp(op sql.Token) int8 { + switch op { + case sql.EQ, sql.SIN, sql.INS: + return +1 + case sql.NEQ, sql.SNI, sql.NIS: + return -1 + case sql.CONTAINSALL: + return +1 + case sql.CONTAINSSOME: + return +1 + case sql.CONTAINSNONE: + return -1 + case sql.ALLCONTAINEDIN: + return +1 + case sql.SOMECONTAINEDIN: + return +1 + case sql.NONECONTAINEDIN: + return -1 + default: + return 0 + } } func chkBool(op sql.Token, a, b bool) (val bool) { @@ -772,14 +775,8 @@ func chkBool(op sql.Token, a, b bool) (val bool) { return a == b case sql.NEQ: return a != b - case sql.SNI: - return true - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkString(op sql.Token, a, b string) (val bool) { @@ -796,14 +793,16 @@ func chkString(op sql.Token, a, b string) (val bool) { return a > b case sql.GTE: return a >= b - case sql.SNI: - return true + case sql.INS: + return strings.Contains(b, a) == true case sql.NIS: - return true - case sql.CONTAINSNONE: - return true + return strings.Contains(b, a) == false + case sql.SIN: + return strings.Contains(a, b) == true + case sql.SNI: + return strings.Contains(a, b) == false } - return + return negOp(op) } func chkInt(op sql.Token, a, b int64) (val bool) { @@ -820,14 +819,8 @@ func chkInt(op sql.Token, a, b int64) (val bool) { return a > b case sql.GTE: return a >= b - case sql.SNI: - return true - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkFloat(op sql.Token, a, b float64) (val bool) { @@ -844,14 +837,8 @@ func chkFloat(op sql.Token, a, b float64) (val bool) { return a > b case sql.GTE: return a >= b - case sql.SNI: - return true - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkThing(op sql.Token, a, b *sql.Thing) (val bool) { @@ -860,14 +847,8 @@ func chkThing(op sql.Token, a, b *sql.Thing) (val bool) { return a.TB == b.TB && a.ID == b.ID case sql.NEQ: return a.TB != b.TB || a.ID != b.ID - case sql.SNI: - return true - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkRegex(op sql.Token, a string, r *regexp.Regexp) (val bool) { @@ -879,83 +860,95 @@ func chkRegex(op sql.Token, a string, r *regexp.Regexp) (val bool) { case sql.ANY: return r.MatchString(a) == true } - return + return negOp(op) } func chkObject(op sql.Token, m map[string]interface{}, i interface{}) (val bool) { switch op { case sql.EQ: - if reflect.TypeOf(m) == reflect.TypeOf(i) && reflect.DeepEqual(m, i) == true { - return true + switch i.(type) { + case *sql.Empty: + return len(m) == 0 + default: + return reflect.TypeOf(m) == reflect.TypeOf(i) && reflect.DeepEqual(m, i) == true } case sql.NEQ: - if reflect.TypeOf(m) != reflect.TypeOf(i) || reflect.DeepEqual(m, i) == false { - return true + switch i.(type) { + case *sql.Empty: + return len(m) != 0 + default: + return reflect.TypeOf(m) != reflect.TypeOf(i) || reflect.DeepEqual(m, i) == false } - case sql.SNI: - return true - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkArrayL(op sql.Token, a []interface{}, i interface{}) (val bool) { switch op { case sql.EQ: - return false + switch i.(type) { + case *sql.Empty: + return len(a) == 0 + default: + return false + } case sql.NEQ: - return true + switch i.(type) { + case *sql.Empty: + return len(a) != 0 + default: + return true + } case sql.SIN: - if i == nil { + switch i.(type) { + case nil, *sql.Null: return data.Consume(a).Contains(nil) == true - } else { + default: return data.Consume(a).Contains(i) == true } case sql.SNI: - if i == nil { + switch i.(type) { + case nil, *sql.Null: return data.Consume(a).Contains(nil) == false - } else { + default: return data.Consume(a).Contains(i) == false } - case sql.INS: - return false - case sql.NIS: - return true - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkArrayR(op sql.Token, i interface{}, a []interface{}) (val bool) { switch op { case sql.EQ: - return false + switch i.(type) { + case *sql.Empty: + return len(a) == 0 + default: + return false + } case sql.NEQ: - return true - case sql.SIN: - return false - case sql.SNI: - return true + switch i.(type) { + case *sql.Empty: + return len(a) != 0 + default: + return true + } case sql.INS: - if i == nil { + switch i.(type) { + case nil, *sql.Null: return data.Consume(a).Contains(nil) == true - } else { + default: return data.Consume(a).Contains(i) == true } case sql.NIS: - if i == nil { + switch i.(type) { + case nil, *sql.Null: return data.Consume(a).Contains(nil) == false - } else { + default: return data.Consume(a).Contains(i) == false } - case sql.CONTAINSNONE: - return true } - return + return negOp(op) } func chkArray(op sql.Token, a []interface{}, b []interface{}) (val bool) { @@ -997,6 +990,27 @@ func chkArray(op sql.Token, a []interface{}, b []interface{}) (val bool) { } } return true + case sql.ALLCONTAINEDIN: + for _, v := range a { + if data.Consume(b).Contains(v) == false { + return false + } + } + return true + case sql.SOMECONTAINEDIN: + for _, v := range a { + if data.Consume(b).Contains(v) == true { + return true + } + } + return false + case sql.NONECONTAINEDIN: + for _, v := range a { + if data.Consume(b).Contains(v) == true { + return false + } + } + return true } return } diff --git a/db/fetch_test.go b/db/fetch_test.go new file mode 100644 index 00000000..921505b8 --- /dev/null +++ b/db/fetch_test.go @@ -0,0 +1,902 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package db + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestFetch(t *testing.T) { + + Convey("Check calc-as-bool expressions", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + SELECT * FROM "test" WHERE gone; + SELECT * FROM "test" WHERE true; + SELECT * FROM "test" WHERE 0; + SELECT * FROM "test" WHERE -1; + SELECT * FROM "test" WHERE +1; + SELECT * FROM "test" WHERE "test"; + SELECT * FROM "test" WHERE time.now(); + + SELECT * FROM "test" WHERE []; + SELECT * FROM "test" WHERE [1,2,3]; + + SELECT * FROM "test" WHERE {}; + SELECT * FROM "test" WHERE {test:true}; + + SELECT * FROM "test" WHERE gone OR gone; + SELECT * FROM "test" WHERE true OR true; + SELECT * FROM "test" WHERE gone OR true; + + SELECT * FROM "test" WHERE gone AND gone; + SELECT * FROM "test" WHERE true AND true; + SELECT * FROM "test" WHERE gone AND true; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 18) + + So(res[1].Result, ShouldHaveLength, 0) + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 0) + So(res[4].Result, ShouldHaveLength, 0) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 1) + So(res[7].Result, ShouldHaveLength, 1) + + So(res[8].Result, ShouldHaveLength, 0) + So(res[9].Result, ShouldHaveLength, 1) + + So(res[10].Result, ShouldHaveLength, 0) + So(res[11].Result, ShouldHaveLength, 1) + + So(res[12].Result, ShouldHaveLength, 0) + So(res[13].Result, ShouldHaveLength, 1) + So(res[14].Result, ShouldHaveLength, 1) + + So(res[15].Result, ShouldHaveLength, 0) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 0) + + }) + + Convey("Check calc-as-math expressions", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + SELECT * FROM "test" WHERE 0 + false; + SELECT * FROM "test" WHERE 1 + false; + + SELECT * FROM "test" WHERE 0 + true; + SELECT * FROM "test" WHERE 1 + true; + + SELECT * FROM "test" WHERE time.now() + 1; + + SELECT * FROM "test" WHERE [] + []; + SELECT * FROM "test" WHERE {} + {}; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 8) + + So(res[1].Result, ShouldHaveLength, 0) + So(res[2].Result, ShouldHaveLength, 1) + + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + + So(res[5].Result, ShouldHaveLength, 1) + + So(res[6].Result, ShouldHaveLength, 0) + So(res[7].Result, ShouldHaveLength, 0) + + }) + + Convey("Check binary math comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + SELECT * FROM "test" WHERE 1 = 1; + SELECT * FROM "test" WHERE 1 != 1; + + SELECT * FROM "test" WHERE 1 < 2; + SELECT * FROM "test" WHERE 1 > 2; + SELECT * FROM "test" WHERE 1 <= 2; + SELECT * FROM "test" WHERE 1 >= 2; + + SELECT * FROM "test" WHERE 10-10 = 0; + SELECT * FROM "test" WHERE 10+10 = 20; + SELECT * FROM "test" WHERE 10*10 = 100; + SELECT * FROM "test" WHERE 10/10 = 1; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 11) + + So(res[1].Result, ShouldHaveLength, 1) + So(res[2].Result, ShouldHaveLength, 0) + + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 0) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 0) + + So(res[7].Result, ShouldHaveLength, 1) + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 1) + So(res[10].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary NULL comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET var = NULL; + + SELECT * FROM "test" WHERE NULL = ""; + SELECT * FROM "test" WHERE NULL = []; + SELECT * FROM "test" WHERE NULL = {}; + SELECT * FROM "test" WHERE NULL = $var; + SELECT * FROM "test" WHERE NULL = VOID; + SELECT * FROM "test" WHERE NULL = NULL; + SELECT * FROM "test" WHERE NULL = EMPTY; + SELECT * FROM "test" WHERE NULL = something; + + SELECT * FROM "test" WHERE "" = NULL; + SELECT * FROM "test" WHERE [] = NULL; + SELECT * FROM "test" WHERE {} = NULL; + SELECT * FROM "test" WHERE $var = NULL; + SELECT * FROM "test" WHERE VOID = NULL; + SELECT * FROM "test" WHERE NULL = NULL; + SELECT * FROM "test" WHERE EMPTY = NULL; + SELECT * FROM "test" WHERE something = NULL; + + SELECT * FROM "test" WHERE NULL != ""; + SELECT * FROM "test" WHERE NULL != []; + SELECT * FROM "test" WHERE NULL != {}; + SELECT * FROM "test" WHERE NULL != $var; + SELECT * FROM "test" WHERE NULL != VOID; + SELECT * FROM "test" WHERE NULL != NULL; + SELECT * FROM "test" WHERE NULL != EMPTY; + SELECT * FROM "test" WHERE NULL != something; + + SELECT * FROM "test" WHERE "" != NULL; + SELECT * FROM "test" WHERE [] != NULL; + SELECT * FROM "test" WHERE {} != NULL; + SELECT * FROM "test" WHERE $var != NULL; + SELECT * FROM "test" WHERE VOID != NULL; + SELECT * FROM "test" WHERE NULL != NULL; + SELECT * FROM "test" WHERE EMPTY != NULL; + SELECT * FROM "test" WHERE something != NULL; + + SELECT * FROM "test" WHERE NULL ∈ []; + SELECT * FROM "test" WHERE NULL ∉ []; + SELECT * FROM "test" WHERE NULL ∋ []; + SELECT * FROM "test" WHERE NULL ∌ []; + + SELECT * FROM "test" WHERE [] ∈ NULL; + SELECT * FROM "test" WHERE [] ∉ NULL; + SELECT * FROM "test" WHERE [] ∋ NULL; + SELECT * FROM "test" WHERE [] ∌ NULL; + + SELECT * FROM "test" WHERE NULL ∈ [null]; + SELECT * FROM "test" WHERE NULL ∉ [null]; + SELECT * FROM "test" WHERE [null] ∋ NULL; + SELECT * FROM "test" WHERE [null] ∌ NULL; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 46) + + So(res[2].Result, ShouldHaveLength, 0) + So(res[3].Result, ShouldHaveLength, 0) + So(res[4].Result, ShouldHaveLength, 0) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 0) + So(res[7].Result, ShouldHaveLength, 1) + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 0) + + So(res[10].Result, ShouldHaveLength, 0) + So(res[11].Result, ShouldHaveLength, 0) + So(res[12].Result, ShouldHaveLength, 0) + So(res[13].Result, ShouldHaveLength, 1) + So(res[14].Result, ShouldHaveLength, 0) + So(res[15].Result, ShouldHaveLength, 1) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 0) + + So(res[18].Result, ShouldHaveLength, 1) + So(res[19].Result, ShouldHaveLength, 1) + So(res[20].Result, ShouldHaveLength, 1) + So(res[21].Result, ShouldHaveLength, 0) + So(res[22].Result, ShouldHaveLength, 1) + So(res[23].Result, ShouldHaveLength, 0) + So(res[24].Result, ShouldHaveLength, 0) + So(res[25].Result, ShouldHaveLength, 1) + + So(res[26].Result, ShouldHaveLength, 1) + So(res[27].Result, ShouldHaveLength, 1) + So(res[28].Result, ShouldHaveLength, 1) + So(res[29].Result, ShouldHaveLength, 0) + So(res[30].Result, ShouldHaveLength, 1) + So(res[31].Result, ShouldHaveLength, 0) + So(res[32].Result, ShouldHaveLength, 0) + So(res[33].Result, ShouldHaveLength, 1) + + So(res[34].Result, ShouldHaveLength, 0) + So(res[35].Result, ShouldHaveLength, 1) + So(res[36].Result, ShouldHaveLength, 0) + So(res[37].Result, ShouldHaveLength, 1) + + So(res[38].Result, ShouldHaveLength, 0) + So(res[39].Result, ShouldHaveLength, 1) + So(res[40].Result, ShouldHaveLength, 0) + So(res[41].Result, ShouldHaveLength, 1) + + So(res[42].Result, ShouldHaveLength, 1) + So(res[43].Result, ShouldHaveLength, 0) + So(res[44].Result, ShouldHaveLength, 1) + So(res[45].Result, ShouldHaveLength, 0) + + }) + + Convey("Check binary VOID comparisons", t, func() { + + txt := ` + + USE NS test DB test; + + LET var = NULL; + + SELECT * FROM "test" WHERE VOID = ""; + SELECT * FROM "test" WHERE VOID = []; + SELECT * FROM "test" WHERE VOID = {}; + SELECT * FROM "test" WHERE VOID = $var; + SELECT * FROM "test" WHERE VOID = NULL; + SELECT * FROM "test" WHERE VOID = VOID; + SELECT * FROM "test" WHERE VOID = EMPTY; + SELECT * FROM "test" WHERE VOID = something; + + SELECT * FROM "test" WHERE "" = VOID; + SELECT * FROM "test" WHERE [] = VOID; + SELECT * FROM "test" WHERE {} = VOID; + SELECT * FROM "test" WHERE $var = VOID; + SELECT * FROM "test" WHERE NULL = VOID; + SELECT * FROM "test" WHERE VOID = VOID; + SELECT * FROM "test" WHERE EMPTY = VOID; + SELECT * FROM "test" WHERE something = VOID; + + SELECT * FROM "test" WHERE VOID != ""; + SELECT * FROM "test" WHERE VOID != []; + SELECT * FROM "test" WHERE VOID != {}; + SELECT * FROM "test" WHERE VOID != $var; + SELECT * FROM "test" WHERE VOID != NULL; + SELECT * FROM "test" WHERE VOID != VOID; + SELECT * FROM "test" WHERE VOID != EMPTY; + SELECT * FROM "test" WHERE VOID != something; + + SELECT * FROM "test" WHERE "" != VOID; + SELECT * FROM "test" WHERE [] != VOID; + SELECT * FROM "test" WHERE {} != VOID; + SELECT * FROM "test" WHERE $var != VOID; + SELECT * FROM "test" WHERE NULL != VOID; + SELECT * FROM "test" WHERE VOID != VOID; + SELECT * FROM "test" WHERE EMPTY != VOID; + SELECT * FROM "test" WHERE something != VOID; + + SELECT * FROM "test" WHERE VOID ∈ []; + SELECT * FROM "test" WHERE VOID ∉ []; + SELECT * FROM "test" WHERE VOID ∋ []; + SELECT * FROM "test" WHERE VOID ∌ []; + + SELECT * FROM "test" WHERE [] ∈ VOID; + SELECT * FROM "test" WHERE [] ∉ VOID; + SELECT * FROM "test" WHERE [] ∋ VOID; + SELECT * FROM "test" WHERE [] ∌ VOID; + + SELECT * FROM "test" WHERE VOID ∈ [null]; + SELECT * FROM "test" WHERE VOID ∉ [null]; + SELECT * FROM "test" WHERE [null] ∋ VOID; + SELECT * FROM "test" WHERE [null] ∌ VOID; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 46) + + So(res[2].Result, ShouldHaveLength, 0) + So(res[3].Result, ShouldHaveLength, 0) + So(res[4].Result, ShouldHaveLength, 0) + So(res[5].Result, ShouldHaveLength, 0) + So(res[6].Result, ShouldHaveLength, 0) + So(res[7].Result, ShouldHaveLength, 1) + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 1) + + So(res[10].Result, ShouldHaveLength, 0) + So(res[11].Result, ShouldHaveLength, 0) + So(res[12].Result, ShouldHaveLength, 0) + So(res[13].Result, ShouldHaveLength, 0) + So(res[14].Result, ShouldHaveLength, 0) + So(res[15].Result, ShouldHaveLength, 1) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 1) + + So(res[18].Result, ShouldHaveLength, 1) + So(res[19].Result, ShouldHaveLength, 1) + So(res[20].Result, ShouldHaveLength, 1) + So(res[21].Result, ShouldHaveLength, 1) + So(res[22].Result, ShouldHaveLength, 1) + So(res[23].Result, ShouldHaveLength, 0) + So(res[24].Result, ShouldHaveLength, 0) + So(res[25].Result, ShouldHaveLength, 0) + + So(res[26].Result, ShouldHaveLength, 1) + So(res[27].Result, ShouldHaveLength, 1) + So(res[28].Result, ShouldHaveLength, 1) + So(res[29].Result, ShouldHaveLength, 1) + So(res[30].Result, ShouldHaveLength, 1) + So(res[31].Result, ShouldHaveLength, 0) + So(res[32].Result, ShouldHaveLength, 0) + So(res[33].Result, ShouldHaveLength, 0) + + So(res[34].Result, ShouldHaveLength, 0) + So(res[35].Result, ShouldHaveLength, 1) + So(res[36].Result, ShouldHaveLength, 0) + So(res[37].Result, ShouldHaveLength, 1) + + So(res[38].Result, ShouldHaveLength, 0) + So(res[39].Result, ShouldHaveLength, 1) + So(res[40].Result, ShouldHaveLength, 0) + So(res[41].Result, ShouldHaveLength, 1) + + So(res[42].Result, ShouldHaveLength, 0) + So(res[43].Result, ShouldHaveLength, 1) + So(res[44].Result, ShouldHaveLength, 0) + So(res[45].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary EMPTY comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET var = NULL; + + SELECT * FROM "test" WHERE EMPTY = ""; + SELECT * FROM "test" WHERE EMPTY = []; + SELECT * FROM "test" WHERE EMPTY = {}; + SELECT * FROM "test" WHERE EMPTY = $var; + SELECT * FROM "test" WHERE EMPTY = NULL; + SELECT * FROM "test" WHERE EMPTY = VOID; + SELECT * FROM "test" WHERE EMPTY = EMPTY; + SELECT * FROM "test" WHERE EMPTY = something; + + SELECT * FROM "test" WHERE "" = EMPTY; + SELECT * FROM "test" WHERE [] = EMPTY; + SELECT * FROM "test" WHERE {} = EMPTY; + SELECT * FROM "test" WHERE $var = EMPTY; + SELECT * FROM "test" WHERE NULL = EMPTY; + SELECT * FROM "test" WHERE VOID = EMPTY; + SELECT * FROM "test" WHERE EMPTY = EMPTY; + SELECT * FROM "test" WHERE something = EMPTY; + + SELECT * FROM "test" WHERE EMPTY != ""; + SELECT * FROM "test" WHERE EMPTY != []; + SELECT * FROM "test" WHERE EMPTY != {}; + SELECT * FROM "test" WHERE EMPTY != $var; + SELECT * FROM "test" WHERE EMPTY != NULL; + SELECT * FROM "test" WHERE EMPTY != VOID; + SELECT * FROM "test" WHERE EMPTY != EMPTY; + SELECT * FROM "test" WHERE EMPTY != something; + + SELECT * FROM "test" WHERE "" != EMPTY; + SELECT * FROM "test" WHERE [] != EMPTY; + SELECT * FROM "test" WHERE {} != EMPTY; + SELECT * FROM "test" WHERE $var != EMPTY; + SELECT * FROM "test" WHERE NULL != EMPTY; + SELECT * FROM "test" WHERE VOID != EMPTY; + SELECT * FROM "test" WHERE EMPTY != EMPTY; + SELECT * FROM "test" WHERE something != EMPTY; + + SELECT * FROM "test" WHERE EMPTY ∈ []; + SELECT * FROM "test" WHERE EMPTY ∉ []; + SELECT * FROM "test" WHERE EMPTY ∋ []; + SELECT * FROM "test" WHERE EMPTY ∌ []; + + SELECT * FROM "test" WHERE [] ∈ EMPTY; + SELECT * FROM "test" WHERE [] ∉ EMPTY; + SELECT * FROM "test" WHERE [] ∋ EMPTY; + SELECT * FROM "test" WHERE [] ∌ EMPTY; + + SELECT * FROM "test" WHERE EMPTY ∈ [null]; + SELECT * FROM "test" WHERE EMPTY ∉ [null]; + SELECT * FROM "test" WHERE [null] ∋ EMPTY; + SELECT * FROM "test" WHERE [null] ∌ EMPTY; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 46) + + So(res[2].Result, ShouldHaveLength, 0) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 1) + So(res[7].Result, ShouldHaveLength, 1) + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 1) + + So(res[10].Result, ShouldHaveLength, 0) + So(res[11].Result, ShouldHaveLength, 1) + So(res[12].Result, ShouldHaveLength, 1) + So(res[13].Result, ShouldHaveLength, 1) + So(res[14].Result, ShouldHaveLength, 1) + So(res[15].Result, ShouldHaveLength, 1) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 1) + + So(res[18].Result, ShouldHaveLength, 1) + So(res[19].Result, ShouldHaveLength, 0) + So(res[20].Result, ShouldHaveLength, 0) + So(res[21].Result, ShouldHaveLength, 0) + So(res[22].Result, ShouldHaveLength, 0) + So(res[23].Result, ShouldHaveLength, 0) + So(res[24].Result, ShouldHaveLength, 0) + So(res[25].Result, ShouldHaveLength, 0) + + So(res[26].Result, ShouldHaveLength, 1) + So(res[27].Result, ShouldHaveLength, 0) + So(res[28].Result, ShouldHaveLength, 0) + So(res[29].Result, ShouldHaveLength, 0) + So(res[30].Result, ShouldHaveLength, 0) + So(res[31].Result, ShouldHaveLength, 0) + So(res[32].Result, ShouldHaveLength, 0) + So(res[33].Result, ShouldHaveLength, 0) + + So(res[34].Result, ShouldHaveLength, 0) + So(res[35].Result, ShouldHaveLength, 1) + So(res[36].Result, ShouldHaveLength, 0) + So(res[37].Result, ShouldHaveLength, 1) + + So(res[38].Result, ShouldHaveLength, 0) + So(res[39].Result, ShouldHaveLength, 1) + So(res[40].Result, ShouldHaveLength, 0) + So(res[41].Result, ShouldHaveLength, 1) + + So(res[42].Result, ShouldHaveLength, 0) + So(res[43].Result, ShouldHaveLength, 1) + So(res[44].Result, ShouldHaveLength, 0) + So(res[45].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary thing comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + -- ------------------------------ + + SELECT * FROM "test" WHERE person:test = person:test; + SELECT * FROM "test" WHERE person:test = "person:test"; + SELECT * FROM "test" WHERE person:test ∈ array(person:test); + + -- ------------------------------ + + SELECT * FROM "test" WHERE person:test = person:test; + SELECT * FROM "test" WHERE person:test != person:test; + SELECT * FROM "test" WHERE person:test = user:test; + SELECT * FROM "test" WHERE person:test != user:test; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 8) + + So(res[1].Result, ShouldHaveLength, 1) + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 0) + So(res[6].Result, ShouldHaveLength, 0) + So(res[7].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary bool comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + -- ------------------------------ + + SELECT * FROM "test" WHERE true = true; + SELECT * FROM "test" WHERE true = "true"; + SELECT * FROM "test" WHERE true = /\w/; + SELECT * FROM "test" WHERE true ∈ [true,false]; + + -- ------------------------------ + + SELECT * FROM "test" WHERE true = true; + SELECT * FROM "test" WHERE true != true; + SELECT * FROM "test" WHERE false = false; + SELECT * FROM "test" WHERE false != false; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 9) + + So(res[1].Result, ShouldHaveLength, 1) + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 0) + So(res[7].Result, ShouldHaveLength, 1) + So(res[8].Result, ShouldHaveLength, 0) + + }) + + Convey("Check binary float comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET timer = "1987-06-22T08:30:30.511Z"; + + -- ------------------------------ + + SELECT * FROM "test" WHERE 1 = "1"; + SELECT * FROM "test" WHERE 1 = /\d/; + SELECT * FROM "test" WHERE 1 ∈ [1,2,3]; + SELECT * FROM "test" WHERE 551349030511000000 = $timer; + + -- ------------------------------ + + SELECT * FROM "test" WHERE 1 = 1; + SELECT * FROM "test" WHERE 1.1 != 1.1; + + SELECT * FROM "test" WHERE 1 < 2; + SELECT * FROM "test" WHERE 1 > 2; + SELECT * FROM "test" WHERE 1 <= 2; + SELECT * FROM "test" WHERE 1 >= 2; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 12) + + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 1) + + So(res[6].Result, ShouldHaveLength, 1) + So(res[7].Result, ShouldHaveLength, 0) + + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 0) + So(res[10].Result, ShouldHaveLength, 1) + So(res[11].Result, ShouldHaveLength, 0) + + }) + + Convey("Check binary string comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET timer = "1987-06-22T08:30:30.511Z"; + + -- ------------------------------ + + SELECT * FROM "test" WHERE "true" = true; + SELECT * FROM "test" WHERE "1.1" = 1.1; + SELECT * FROM "test" WHERE "person:test" = person:test; + SELECT * FROM "test" WHERE "test" = /\w/; + SELECT * FROM "test" WHERE "test" ∈ ["test","some"]; + SELECT * FROM "test" WHERE "1987-06-22 08:30:30.511 +0000 UTC" = $timer; + + -- ------------------------------ + + SELECT * FROM "test" WHERE "test" = "test"; + SELECT * FROM "test" WHERE "test" != "test"; + + SELECT * FROM "test" WHERE "abc" < "def"; + SELECT * FROM "test" WHERE "abc" > "def"; + SELECT * FROM "test" WHERE "abc" <= "def"; + SELECT * FROM "test" WHERE "abc" >= "def"; + + SELECT * FROM "test" WHERE "a true test string" ∋ "test"; + SELECT * FROM "test" WHERE "a true test string" ∌ "test"; + SELECT * FROM "test" WHERE "test" ∈ "a true test string"; + SELECT * FROM "test" WHERE "test" ∉ "a true test string"; + + SELECT * FROM "test" WHERE "a true test string" = /test/; + SELECT * FROM "test" WHERE "a true test string" != /test/; + SELECT * FROM "test" WHERE "a true test string" ?= /test/; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 21) + + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 1) + So(res[7].Result, ShouldHaveLength, 1) + + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 0) + + So(res[10].Result, ShouldHaveLength, 1) + So(res[11].Result, ShouldHaveLength, 0) + So(res[12].Result, ShouldHaveLength, 1) + So(res[13].Result, ShouldHaveLength, 0) + + So(res[14].Result, ShouldHaveLength, 1) + So(res[15].Result, ShouldHaveLength, 0) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 0) + + So(res[18].Result, ShouldHaveLength, 1) + So(res[19].Result, ShouldHaveLength, 0) + So(res[20].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary time.Time comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET timer = "1987-06-22T08:30:30.511Z"; + + -- ------------------------------ + + SELECT * FROM "test" WHERE $timer = "1987-06-22 08:30:30.511 +0000 UTC"; + SELECT * FROM "test" WHERE $timer = 551349030511000000; + SELECT * FROM "test" WHERE $timer = $timer; + SELECT * FROM "test" WHERE $timer = /\d/; + SELECT * FROM "test" WHERE $timer ∈ array($timer); + + -- ------------------------------ + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 7) + + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 1) + + }) + + Convey("Check binary array comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + LET timer = "1987-06-22T08:30:30.511Z"; + + -- ------------------------------ + + SELECT * FROM "test" WHERE [true] ∋ true; + SELECT * FROM "test" WHERE ["test"] ∋ "test"; + SELECT * FROM "test" WHERE [1,2,3] ∋ 1; + SELECT * FROM "test" WHERE array($timer) ∋ $timer; + SELECT * FROM "test" WHERE [1,2,3] = /\d/; + SELECT * FROM "test" WHERE [{test:true}] ∋ {test:true}; + + -- ------------------------------ + + SELECT * FROM "test" WHERE [] = []; + SELECT * FROM "test" WHERE [] != []; + + SELECT * FROM "test" WHERE [1,2,3] = [1,2,3]; + SELECT * FROM "test" WHERE [1,2,3] = [4,5,6]; + SELECT * FROM "test" WHERE [1,2,3] != [1,2,3]; + SELECT * FROM "test" WHERE [1,2,3] != [4,5,6]; + + SELECT * FROM "test" WHERE [1,2,3] ∈ [ [1,2,3] ]; + SELECT * FROM "test" WHERE [1,2,3] ∉ [ [1,2,3] ]; + SELECT * FROM "test" WHERE [ [1,2,3] ] ∋ [1,2,3]; + SELECT * FROM "test" WHERE [ [1,2,3] ] ∌ [1,2,3]; + + SELECT * FROM "test" WHERE [1,2,3,4,5] ⊇ [1,3,5]; + SELECT * FROM "test" WHERE [1,2,3,4,5] ⊇ [2,4,6]; + SELECT * FROM "test" WHERE [1,3,5,7,9] ⊃ [1,3,5]; + SELECT * FROM "test" WHERE [1,3,5,7,9] ⊃ [2,4,6]; + SELECT * FROM "test" WHERE [1,3,5,7,9] ⊅ [1,3,5]; + SELECT * FROM "test" WHERE [1,3,5,7,9] ⊅ [2,4,6]; + + SELECT * FROM "test" WHERE [1,3,5] ⊆ [1,2,3,4,5]; + SELECT * FROM "test" WHERE [2,4,6] ⊆ [1,2,3,4,5]; + SELECT * FROM "test" WHERE [1,3,5] ⊂ [1,3,5,7,9]; + SELECT * FROM "test" WHERE [2,4,6] ⊂ [1,3,5,7,9]; + SELECT * FROM "test" WHERE [1,3,5] ⊄ [1,3,5,7,9]; + SELECT * FROM "test" WHERE [2,4,6] ⊄ [1,3,5,7,9]; + + SELECT * FROM "test" WHERE [1,2,3] = /[0-9]/; + SELECT * FROM "test" WHERE [1,"2",true] = /[0-9]/; + SELECT * FROM "test" WHERE ["a","b","c"] = /[0-9]/; + + SELECT * FROM "test" WHERE [1,2,3] != /[0-9]/; + SELECT * FROM "test" WHERE [1,"2",true] != /[0-9]/; + SELECT * FROM "test" WHERE ["a","b","c"] != /[0-9]/; + + SELECT * FROM "test" WHERE [1,2,3] ?= /[0-9]/; + SELECT * FROM "test" WHERE [1,"2",true] ?= /[0-9]/; + SELECT * FROM "test" WHERE ["a","b","c"] ?= /[0-9]/; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 39) + + So(res[2].Result, ShouldHaveLength, 1) + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 1) + So(res[5].Result, ShouldHaveLength, 1) + So(res[6].Result, ShouldHaveLength, 1) + So(res[7].Result, ShouldHaveLength, 1) + + So(res[8].Result, ShouldHaveLength, 1) + So(res[9].Result, ShouldHaveLength, 0) + + So(res[10].Result, ShouldHaveLength, 1) + So(res[11].Result, ShouldHaveLength, 0) + So(res[12].Result, ShouldHaveLength, 0) + So(res[13].Result, ShouldHaveLength, 1) + + So(res[14].Result, ShouldHaveLength, 1) + So(res[15].Result, ShouldHaveLength, 0) + So(res[16].Result, ShouldHaveLength, 1) + So(res[17].Result, ShouldHaveLength, 0) + + So(res[18].Result, ShouldHaveLength, 1) + So(res[19].Result, ShouldHaveLength, 0) + So(res[20].Result, ShouldHaveLength, 1) + So(res[21].Result, ShouldHaveLength, 0) + So(res[22].Result, ShouldHaveLength, 0) + So(res[23].Result, ShouldHaveLength, 1) + + So(res[24].Result, ShouldHaveLength, 1) + So(res[25].Result, ShouldHaveLength, 0) + So(res[26].Result, ShouldHaveLength, 1) + So(res[27].Result, ShouldHaveLength, 0) + So(res[28].Result, ShouldHaveLength, 0) + So(res[29].Result, ShouldHaveLength, 1) + + So(res[30].Result, ShouldHaveLength, 1) + So(res[31].Result, ShouldHaveLength, 0) + So(res[32].Result, ShouldHaveLength, 0) + So(res[33].Result, ShouldHaveLength, 0) + So(res[34].Result, ShouldHaveLength, 0) + So(res[35].Result, ShouldHaveLength, 1) + + So(res[36].Result, ShouldHaveLength, 1) + So(res[37].Result, ShouldHaveLength, 1) + So(res[38].Result, ShouldHaveLength, 0) + + }) + + Convey("Check binary object comparisons", t, func() { + + setupDB() + + txt := ` + + USE NS test DB test; + + -- ------------------------------ + + SELECT * FROM "test" WHERE {test:true} = {test:true}; + SELECT * FROM "test" WHERE {test:true} ∈ [{test:true}]; + + -- ------------------------------ + + SELECT * FROM "test" WHERE {test:true} = {test:true}; + SELECT * FROM "test" WHERE {test:true} != {test:true}; + SELECT * FROM "test" WHERE {test:true} = {other:true}; + SELECT * FROM "test" WHERE {test:true} != {other:true}; + + ` + + res, err := Execute(setupKV(), txt, nil) + So(err, ShouldBeNil) + So(res, ShouldHaveLength, 7) + + So(res[1].Result, ShouldHaveLength, 1) + So(res[2].Result, ShouldHaveLength, 1) + + So(res[3].Result, ShouldHaveLength, 1) + So(res[4].Result, ShouldHaveLength, 0) + So(res[5].Result, ShouldHaveLength, 0) + So(res[6].Result, ShouldHaveLength, 1) + + }) + +} diff --git a/db/select_test.go b/db/select_test.go index 2d011c9b..2301820c 100644 --- a/db/select_test.go +++ b/db/select_test.go @@ -24,96 +24,6 @@ import ( func TestSelect(t *testing.T) { - Convey("Select temps", t, func() { - - setupDB() - - txt := ` - - USE NS test DB test; - - LET var = NULL; - - SELECT * FROM "test" WHERE NULL = ""; - SELECT * FROM "test" WHERE NULL = $var; - SELECT * FROM "test" WHERE NULL = VOID; - SELECT * FROM "test" WHERE NULL = NULL; - SELECT * FROM "test" WHERE NULL = EMPTY; - - SELECT * FROM "test" WHERE "" = NULL; - SELECT * FROM "test" WHERE $var = NULL; - SELECT * FROM "test" WHERE VOID = NULL; - SELECT * FROM "test" WHERE NULL = NULL; - SELECT * FROM "test" WHERE EMPTY = NULL; - - SELECT * FROM "test" WHERE VOID = ""; - SELECT * FROM "test" WHERE VOID = $var; - SELECT * FROM "test" WHERE VOID = NULL; - SELECT * FROM "test" WHERE VOID = VOID; - SELECT * FROM "test" WHERE VOID = EMPTY; - - SELECT * FROM "test" WHERE "" = VOID; - SELECT * FROM "test" WHERE $var = VOID; - SELECT * FROM "test" WHERE NULL = VOID; - SELECT * FROM "test" WHERE VOID = VOID; - SELECT * FROM "test" WHERE EMPTY = VOID; - - SELECT * FROM "test" WHERE EMPTY = ""; - SELECT * FROM "test" WHERE EMPTY = $var; - SELECT * FROM "test" WHERE EMPTY = NULL; - SELECT * FROM "test" WHERE EMPTY = VOID; - SELECT * FROM "test" WHERE EMPTY = EMPTY; - - SELECT * FROM "test" WHERE "" = EMPTY; - SELECT * FROM "test" WHERE $var = EMPTY; - SELECT * FROM "test" WHERE NULL = EMPTY; - SELECT * FROM "test" WHERE VOID = EMPTY; - SELECT * FROM "test" WHERE EMPTY = EMPTY; - - ` - - res, err := Execute(setupKV(), txt, nil) - So(err, ShouldBeNil) - So(res, ShouldHaveLength, 32) - - So(res[2].Result, ShouldHaveLength, 0) - So(res[3].Result, ShouldHaveLength, 1) - So(res[4].Result, ShouldHaveLength, 0) - So(res[5].Result, ShouldHaveLength, 1) - So(res[6].Result, ShouldHaveLength, 1) - - So(res[7].Result, ShouldHaveLength, 0) - So(res[8].Result, ShouldHaveLength, 1) - So(res[9].Result, ShouldHaveLength, 0) - So(res[10].Result, ShouldHaveLength, 1) - So(res[11].Result, ShouldHaveLength, 1) - - So(res[12].Result, ShouldHaveLength, 0) - So(res[13].Result, ShouldHaveLength, 0) - So(res[14].Result, ShouldHaveLength, 0) - So(res[15].Result, ShouldHaveLength, 1) - So(res[16].Result, ShouldHaveLength, 1) - - So(res[17].Result, ShouldHaveLength, 0) - So(res[18].Result, ShouldHaveLength, 0) - So(res[19].Result, ShouldHaveLength, 0) - So(res[20].Result, ShouldHaveLength, 1) - So(res[21].Result, ShouldHaveLength, 1) - - So(res[22].Result, ShouldHaveLength, 0) - So(res[23].Result, ShouldHaveLength, 1) - So(res[24].Result, ShouldHaveLength, 1) - So(res[25].Result, ShouldHaveLength, 1) - So(res[26].Result, ShouldHaveLength, 1) - - So(res[27].Result, ShouldHaveLength, 0) - So(res[28].Result, ShouldHaveLength, 1) - So(res[29].Result, ShouldHaveLength, 1) - So(res[30].Result, ShouldHaveLength, 1) - So(res[31].Result, ShouldHaveLength, 1) - - }) - Convey("Select records from one thing", t, func() { setupDB()