Ensure NULL/VOID/EMPTY values are compared correctly
This commit is contained in:
parent
327bdd05cd
commit
d367726709
2 changed files with 207 additions and 61 deletions
178
db/fetch.go
178
db/fetch.go
|
@ -409,94 +409,150 @@ func binaryMath(op sql.Token, l, r interface{}) interface{} {
|
|||
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
if d != nil {
|
||||
|
||||
switch l := lo.(type) {
|
||||
|
||||
switch lo.(type) {
|
||||
case *sql.Void:
|
||||
|
||||
switch r.(type) {
|
||||
case nil:
|
||||
return op == sql.NEQ
|
||||
}
|
||||
|
||||
case *sql.Ident:
|
||||
|
||||
switch r.(type) {
|
||||
|
||||
case *sql.Void:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == false
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == true
|
||||
}
|
||||
|
||||
case nil:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == true && d.Get(l.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == false || d.Get(l.ID).Data() != nil
|
||||
}
|
||||
|
||||
case *sql.Empty:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == false || d.Get(l.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == true && d.Get(l.ID).Data() != nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch r := ro.(type) {
|
||||
|
||||
case *sql.Void:
|
||||
|
||||
switch l.(type) {
|
||||
case nil:
|
||||
return op == sql.NEQ
|
||||
}
|
||||
|
||||
case *sql.Ident:
|
||||
|
||||
switch l.(type) {
|
||||
|
||||
case *sql.Void:
|
||||
switch r := ro.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(r.ID) == false
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(r.ID) == true
|
||||
}
|
||||
|
||||
case nil:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(r.ID) == true && d.Get(r.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(r.ID) == false || d.Get(r.ID).Data() != nil
|
||||
}
|
||||
|
||||
case *sql.Empty:
|
||||
}
|
||||
case *sql.Empty:
|
||||
switch r := ro.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(r.ID) == false || d.Get(r.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(r.ID) == true && d.Get(r.ID).Data() != nil
|
||||
}
|
||||
|
||||
}
|
||||
case nil:
|
||||
switch r := ro.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(r.ID) == true && d.Get(r.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(r.ID) == false || d.Get(r.ID).Data() != nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ro.(type) {
|
||||
case *sql.Void:
|
||||
switch l := lo.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == false
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == true
|
||||
}
|
||||
}
|
||||
case *sql.Empty:
|
||||
switch l := lo.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == false || d.Get(l.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == true && d.Get(l.ID).Data() != nil
|
||||
}
|
||||
}
|
||||
case nil:
|
||||
switch l := lo.(type) {
|
||||
case *sql.Ident:
|
||||
if op == sql.EQ {
|
||||
return d.Exists(l.ID) == true && d.Get(l.ID).Data() == nil
|
||||
} else if op == sql.NEQ {
|
||||
return d.Exists(l.ID) == false || d.Get(l.ID).Data() != nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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.Empty:
|
||||
return op == sql.EQ
|
||||
case []interface{}:
|
||||
return chkArrayR(op, l, r)
|
||||
case map[string]interface{}:
|
||||
|
|
|
@ -24,6 +24,96 @@ 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()
|
||||
|
|
Loading…
Reference in a new issue