blob: 61c320a05d0d8b09299b597206e3e68579adc173 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package test
import (
"errors"
"fmt"
"reflect"
"testing"
"time"
"v.io/syncbase/v23/syncbase/nosql/internal/query"
"v.io/syncbase/v23/syncbase/nosql/internal/query/query_checker"
"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
"v.io/syncbase/v23/syncbase/nosql/query_db"
"v.io/syncbase/v23/syncbase/nosql/syncql"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/vdl"
"v.io/v23/verror"
_ "v.io/x/ref/runtime/factories/generic"
"v.io/x/ref/test"
)
type mockDB struct {
ctx *context.T
tables []table
}
type table struct {
name string
rows []kv
}
type keyValueStreamImpl struct {
table table
cursor int
keyRanges query_db.KeyRanges
keyRangesCursor int
}
func compareKeyToLimit(key, limit string) int {
if limit == "" || key < limit {
return -1
} else if key == limit {
return 0
} else {
return 1
}
}
func (kvs *keyValueStreamImpl) Advance() bool {
for true {
kvs.cursor++ // initialized to -1
if kvs.cursor >= len(kvs.table.rows) {
return false
}
// does it match any keyRange
for kvs.keyRangesCursor < len(kvs.keyRanges) {
if kvs.table.rows[kvs.cursor].key >= kvs.keyRanges[kvs.keyRangesCursor].Start && compareKeyToLimit(kvs.table.rows[kvs.cursor].key, kvs.keyRanges[kvs.keyRangesCursor].Limit) < 0 {
return true
}
// Keys and keyRanges are both sorted low to high, so we can increment
// keyRangesCursor if the keyRange.Limit is < the key.
if compareKeyToLimit(kvs.table.rows[kvs.cursor].key, kvs.keyRanges[kvs.keyRangesCursor].Limit) > 0 {
kvs.keyRangesCursor++
if kvs.keyRangesCursor >= len(kvs.keyRanges) {
return false
}
} else {
break
}
}
}
return false
}
func (kvs *keyValueStreamImpl) KeyValue() (string, *vdl.Value) {
return kvs.table.rows[kvs.cursor].key, kvs.table.rows[kvs.cursor].value
}
func (kvs *keyValueStreamImpl) Err() error {
return nil
}
func (kvs *keyValueStreamImpl) Cancel() {
}
func (t table) Scan(keyRanges query_db.KeyRanges) (query_db.KeyValueStream, error) {
var keyValueStreamImpl keyValueStreamImpl
keyValueStreamImpl.table = t
keyValueStreamImpl.cursor = -1
keyValueStreamImpl.keyRanges = keyRanges
return &keyValueStreamImpl, nil
}
func (db mockDB) GetContext() *context.T {
return db.ctx
}
func (db mockDB) GetTable(table string) (query_db.Table, error) {
for _, t := range db.tables {
if t.name == table {
return t, nil
}
}
return nil, errors.New(fmt.Sprintf("No such table: %s.", table))
}
var db mockDB
var custTable table
var numTable table
var fooTable table
var funWithMapsTable table
var ratingsArrayTable table
var tdhApprovalsTable table
var previousRatingsTable table
var previousAddressesTable table
var manyMapsTable table
var manySetsTable table
var bigTable table
type kv struct {
key string
value *vdl.Value
}
var t2015 time.Time
var t2015_04 time.Time
var t2015_04_12 time.Time
var t2015_04_12_22 time.Time
var t2015_04_12_22_16 time.Time
var t2015_04_12_22_16_06 time.Time
var t2015_07 time.Time
var t2015_07_01 time.Time
var t2015_07_01_01_23_45 time.Time
func init() {
var shutdown v23.Shutdown
db.ctx, shutdown = test.V23Init()
defer shutdown()
t20150122131101, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Jan 22 2015 13:11:01 -0800 PST")
t20150210161202, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Feb 10 2015 16:12:02 -0800 PST")
t20150311101303, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Mar 11 2015 10:13:03 -0700 PDT")
t20150317111404, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Mar 17 2015 11:14:04 -0700 PDT")
t20150317131505, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Mar 17 2015 13:15:05 -0700 PDT")
t20150412221606, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Apr 12 2015 22:16:06 -0700 PDT")
t20150413141707, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Apr 13 2015 14:17:07 -0700 PDT")
t2015, _ = time.Parse("2006 MST", "2015 PST")
t2015_04, _ = time.Parse("Jan 2006 MST", "Apr 2015 PDT")
t2015_07, _ = time.Parse("Jan 2006 MST", "Jul 2015 PDT")
t2015_04_12, _ = time.Parse("Jan 2 2006 MST", "Apr 12 2015 PDT")
t2015_07_01, _ = time.Parse("Jan 2 2006 MST", "Jul 01 2015 PDT")
t2015_04_12_22, _ = time.Parse("Jan 2 2006 15 MST", "Apr 12 2015 22 PDT")
t2015_04_12_22_16, _ = time.Parse("Jan 2 2006 15:04 MST", "Apr 12 2015 22:16 PDT")
t2015_04_12_22_16_06, _ = time.Parse("Jan 2 2006 15:04:05 MST", "Apr 12 2015 22:16:06 PDT")
t2015_07_01_01_23_45, _ = time.Parse("Jan 2 2006 15:04:05 MST", "Jul 01 2015 01:23:45 PDT")
custTable.name = "Customer"
custTable.rows = []kv{
kv{
"001",
vdl.ValueOf(Customer{"John Smith", 1, true, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}, []AddressInfo{AddressInfo{"10 Brown St.", "Mountain View", "CA", "94043"}}, CreditReport{Agency: CreditAgencyEquifax, Report: AgencyReportEquifaxReport{EquifaxCreditReport{'A', [4]int16{87, 81, 42, 2}}}}}),
},
kv{
"001001",
vdl.ValueOf(Invoice{1, 1000, t20150122131101, 42, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}}),
},
kv{
"001002",
vdl.ValueOf(Invoice{1, 1003, t20150210161202, 7, AddressInfo{"2 Main St.", "Palo Alto", "CA", "94303"}}),
},
kv{
"001003",
vdl.ValueOf(Invoice{1, 1005, t20150311101303, 88, AddressInfo{"3 Main St.", "Palo Alto", "CA", "94303"}}),
},
kv{
"002",
vdl.ValueOf(Customer{"Bat Masterson", 2, true, AddressInfo{"777 Any St.", "Collins", "IA", "50055"}, []AddressInfo{AddressInfo{"19 Green St.", "Boulder", "CO", "80301"}, AddressInfo{"558 W. Orange St.", "Lancaster", "PA", "17603"}}, CreditReport{Agency: CreditAgencyTransUnion, Report: AgencyReportTransUnionReport{TransUnionCreditReport{80, map[string]int16{"2015Q2": 40, "2015Q1": 60}}}}}),
},
kv{
"002001",
vdl.ValueOf(Invoice{2, 1001, t20150317111404, 166, AddressInfo{"777 Any St.", "collins", "IA", "50055"}}),
},
kv{
"002002",
vdl.ValueOf(Invoice{2, 1002, t20150317131505, 243, AddressInfo{"888 Any St.", "collins", "IA", "50055"}}),
},
kv{
"002003",
vdl.ValueOf(Invoice{2, 1004, t20150412221606, 787, AddressInfo{"999 Any St.", "collins", "IA", "50055"}}),
},
kv{
"002004",
vdl.ValueOf(Invoice{2, 1006, t20150413141707, 88, AddressInfo{"101010 Any St.", "collins", "IA", "50055"}}),
},
kv{
"003",
vdl.ValueOf(Customer{"John Steed", 3, true, AddressInfo{"100 Queen St.", "New London", "CT", "06320"}, []AddressInfo{}, CreditReport{Agency: CreditAgencyExperian, Report: AgencyReportExperianReport{ExperianCreditReport{ExperianRatingGood, map[Tdh]struct{}{TdhTom: {}, TdhHarry: {}}, TdhTom}}}}),
},
}
db.tables = append(db.tables, custTable)
numTable.name = "Numbers"
numTable.rows = []kv{
kv{
"001",
vdl.ValueOf(Numbers{byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), int64(128), float32(3.14159), float64(2.71828182846), complex64(123.0 + 7.0i), complex128(456.789 + 10.1112i)}),
},
kv{
"002",
vdl.ValueOf(Numbers{byte(9), uint16(99), uint32(999), uint64(9999999), int16(9), int32(99), int64(88), float32(1.41421356237), float64(1.73205080757), complex64(9.87 + 7.65i), complex128(4.32 + 1.0i)}),
},
kv{
"003",
vdl.ValueOf(Numbers{byte(210), uint16(210), uint32(210), uint64(210), int16(210), int32(210), int64(210), float32(210.0), float64(210.0), complex64(210.0 + 0.0i), complex128(210.0 + 0.0i)}),
},
}
db.tables = append(db.tables, numTable)
fooTable.name = "Foo"
fooTable.rows = []kv{
kv{
"001",
vdl.ValueOf(FooType{BarType{BazType{"FooBarBaz", TitleOrValueTypeTitle{"Vice President"}}}}),
},
kv{
"002",
vdl.ValueOf(FooType{BarType{BazType{"BazBarFoo", TitleOrValueTypeValue{42}}}}),
},
}
db.tables = append(db.tables, fooTable)
funWithMapsTable.name = "FunWithMaps"
funWithMapsTable.rows = []kv{
kv{
"AAA",
vdl.ValueOf(FunWithMaps{K{'a', "bbb"}, map[K]V{K{'a', "aaa"}: V{"bbb", 23.0}, K{'a', "bbb"}: V{"ccc", 14.7}},
map[int16][]map[string]struct{}{
23: []map[string]struct{}{
map[string]struct{}{"foo": {}, "bar": {}},
},
},
}),
},
kv{
"BBB",
vdl.ValueOf(FunWithMaps{K{'x', "zzz"}, map[K]V{K{'x', "zzz"}: V{"yyy", 17.1}, K{'r', "sss"}: V{"qqq", 7.8}},
map[int16][]map[string]struct{}{
42: []map[string]struct{}{
map[string]struct{}{"great": {}, "dane": {}},
map[string]struct{}{"german": {}, "shepard": {}},
},
},
}),
},
}
db.tables = append(db.tables, funWithMapsTable)
ratingsArrayTable.name = "RatingsArray"
ratingsArrayTable.rows = []kv{
kv{
"000",
vdl.ValueOf(RatingsArray{40, 20, 10, 0}),
},
kv{
"111",
vdl.ValueOf(RatingsArray{17, 18, 19, 20}),
},
}
db.tables = append(db.tables, ratingsArrayTable)
tdhApprovalsTable.name = "TdhApprovals"
tdhApprovalsTable.rows = []kv{
kv{
"yyy",
vdl.ValueOf(map[Tdh]struct{}{TdhTom: {}}),
},
kv{
"zzz",
vdl.ValueOf(map[Tdh]struct{}{TdhDick: {}, TdhHarry: {}}),
},
}
db.tables = append(db.tables, tdhApprovalsTable)
previousRatingsTable.name = "PreviousRatings"
previousRatingsTable.rows = []kv{
kv{
"x1",
vdl.ValueOf(map[string]int16{"1Q2015": 1, "2Q2015": 2}),
},
kv{
"x2",
vdl.ValueOf(map[string]int16{"2Q2015": 3}),
},
}
db.tables = append(db.tables, previousRatingsTable)
previousAddressesTable.name = "PreviousAddresses"
previousAddressesTable.rows = []kv{
kv{
"a1",
vdl.ValueOf([]AddressInfo{
AddressInfo{"100 Main St.", "Anytown", "CA", "94303"},
AddressInfo{"200 Main St.", "Othertown", "IA", "51050"},
}),
},
kv{
"a2",
vdl.ValueOf([]AddressInfo{
AddressInfo{"500 Orange St", "Uptown", "ID", "83209"},
AddressInfo{"200 Fulton St", "Downtown", "MT", "59001"},
}),
},
}
db.tables = append(db.tables, previousAddressesTable)
manyMapsTable.name = "ManyMaps"
manyMapsTable.rows = []kv{
kv{
"0",
vdl.ValueOf(ManyMaps{
map[bool]string{true: "It was the best of times,"},
map[byte]string{10: "it was the worst of times,"},
map[uint16]string{16: "it was the age of wisdom,"},
map[uint32]string{32: "it was the age of foolishness,"},
map[uint64]string{64: "it was the epoch of belief,"},
map[int16]string{17: "it was the epoch of incredulity,"},
map[int32]string{33: "it was the season of Light,"},
map[int64]string{65: "it was the season of Darkness,"},
map[float32]string{32.1: "it was the spring of hope,"},
map[float64]string{64.2: "it was the winter of despair,"},
map[complex64]string{(456.789 + 10.1112i): "we had everything before us,"},
map[complex128]string{(123.456 + 11.2223i): "we had nothing before us,"},
map[string]string{"Dickens": "we are all going direct to Heaven,"},
map[string]map[string]string{
"Charles": map[string]string{"Dickens": "we are all going direct to Heaven,"},
},
map[time.Time]string{t2015_07_01_01_23_45: "we are all going direct the other way"},
}),
},
}
db.tables = append(db.tables, manyMapsTable)
manySetsTable.name = "ManySets"
manySetsTable.rows = []kv{
kv{
"0",
vdl.ValueOf(ManySets{
map[bool]struct{}{true: {}},
map[byte]struct{}{10: {}},
map[uint16]struct{}{16: {}},
map[uint32]struct{}{32: {}},
map[uint64]struct{}{64: {}},
map[int16]struct{}{17: {}},
map[int32]struct{}{33: {}},
map[int64]struct{}{65: {}},
map[float32]struct{}{32.1: {}},
map[float64]struct{}{64.2: {}},
map[complex64]struct{}{(456.789 + 10.1112i): {}},
map[complex128]struct{}{(123.456 + 11.2223i): {}},
map[string]struct{}{"Dickens": {}},
map[time.Time]struct{}{t2015_07_01_01_23_45: {}},
}),
},
}
db.tables = append(db.tables, manySetsTable)
bigTable.name = "BigTable"
for i := 100; i < 301; i++ {
k := fmt.Sprintf("%d", i)
b := vdl.ValueOf(BigData{k})
bigTable.rows = append(bigTable.rows, kv{k, b})
}
db.tables = append(db.tables, bigTable)
}
type keyRangesTest struct {
query string
keyRanges *query_db.KeyRanges
err error
}
type evalWhereUsingOnlyKeyTest struct {
query string
key string
result query.EvalWithKeyResult
}
type evalTest struct {
query string
k string
v *vdl.Value
result bool
}
type projectionTest struct {
query string
k string
v *vdl.Value
result []*vdl.Value
}
type execSelectTest struct {
query string
headers []string
r [][]*vdl.Value
}
type preExecFunctionTest struct {
query string
headers []string
}
type execSelectSingleRowTest struct {
query string
k string
v *vdl.Value
result []*vdl.Value
}
type execSelectErrorTest struct {
query string
err error
}
type execResolveFieldTest struct {
k string
v *vdl.Value
f query_parser.Field
r *vdl.Value
}
func TestQueryExec(t *testing.T) {
basic := []execSelectTest{
{
// Select values for all customer records.
"select v from Customer where Type(v) like \"%.Customer\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select values for all customer records.
"select v from Customer where Type(v) not like \"%.Customer\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
},
},
{
// Select values for all customer records.
"select Type(v) from Customer where Type(v) not like \"%Customer\"",
[]string{"Type"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
},
},
{
// All customers have a v.Credit with type CreditReport.
"select v from Customer where Type(v.Credit) like \"%.CreditReport\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Only customer "001" has an equifax report.
"select v from Customer where Type(v.Credit.Report.EquifaxReport) like \"%.EquifaxCreditReport\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
},
},
{
// Print the types of every record
"select Type(v) from Customer",
[]string{"Type"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
},
},
{
// Print the types of every credit report
"select Type(v.Credit.Report) from Customer",
[]string{"Type"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
},
},
{
// Print the types of every cusomer's v.Credit.Report.EquifaxReport
"select Type(v.Credit.Report.EquifaxReport) from Customer where Type(v) like \"%.Customer\"",
[]string{"Type"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.EquifaxCreditReport")},
[]*vdl.Value{vdl.ValueOf(vdl.ValueOf(nil))},
[]*vdl.Value{vdl.ValueOf(vdl.ValueOf(nil))},
},
},
{
// Select values where v.InvoiceNum is nil
// Since InvoiceNum does not exist for Invoice,
// this will return just customers.
"select v from Customer where v.InvoiceNum is nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select values where v.InvoiceNum is nil
// or v.Name is nil This will select all customers
// with the former and all invoices with the latter.
// Hence, all records are returned.
"select v from Customer where v.InvoiceNum is nil or v.Name is nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select values where v.InvoiceNum is nil
// and v.Name is nil. Expect nothing returned.
"select v from Customer where v.InvoiceNum is nil and v.Name is nil",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select values where v.InvoiceNum is not nil
// This will return just invoices.
"select v from Customer where v.InvoiceNum is not nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
},
},
{
// Select values where v.InvoiceNum is not nil
// or v.Name is not nil. All records are returned.
"select v from Customer where v.InvoiceNum is not nil or v.Name is not nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select values where v.InvoiceNum is nil and v.Name is not nil.
// All customers are returned.
"select v from Customer where v.InvoiceNum is nil and v.Name is not nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select values where v.InvoiceNum is not nil
// and v.Name is not nil. Expect nothing returned.
"select v from Customer where v.InvoiceNum is not nil and v.Name is not nil",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select keys & values for all customer records.
"select k, v from Customer where \"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer\" = Type(v)",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[9].key), custTable.rows[9].value},
},
},
{
// Select keys & names for all customer records.
"select k, v.Name from Customer where Type(v) like \"%.Customer\"",
[]string{"k", "v.Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), vdl.ValueOf("John Smith")},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), vdl.ValueOf("Bat Masterson")},
[]*vdl.Value{vdl.ValueOf(custTable.rows[9].key), vdl.ValueOf("John Steed")},
},
},
{
// Select both customer and invoice records.
// Customer records have Id.
// Invoice records have CustId.
"select v.Id, v.CustId from Customer",
[]string{"v.Id", "v.CustId"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(1)), vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(1))},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(1))},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(1))},
[]*vdl.Value{vdl.ValueOf(int64(2)), vdl.ValueOf(nil)},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(2))},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(2))},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(2))},
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int64(2))},
[]*vdl.Value{vdl.ValueOf(int64(3)), vdl.ValueOf(nil)},
},
},
{
// Select keys & values fo all invoice records.
"select k, v from Customer where Type(v) like \"%.Invoice\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
},
},
{
// Select key, cust id, invoice number and amount for $88 invoices.
"select k, v.CustId as ID, v.InvoiceNum as InvoiceNumber, v.Amount as Amt from Customer where Type(v) like \"%.Invoice\" and v.Amount = 88",
[]string{"k", "ID", "InvoiceNumber", "Amt"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), vdl.ValueOf(int64(1)), vdl.ValueOf(int64(1005)), vdl.ValueOf(int64(88))},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), vdl.ValueOf(int64(2)), vdl.ValueOf(int64(1006)), vdl.ValueOf(int64(88))},
},
},
{
// Select keys & values for all records with a key prefix of "001".
"select k, v from Customer where k like \"001%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
},
},
{
// Select keys & values for all records with a key prefix of "002".
"select k, v from Customer where k like \"002%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
},
},
{
// Select keys & values for all records with a key prefix NOT LIKE "002%".
"select k, v from Customer where k not like \"002%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[9].key), custTable.rows[9].value},
},
},
{
// Select keys & values for all records with a key prefix NOT LIKE "002".
// will be optimized to k <> "002"
"select k, v from Customer where k not like \"002\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[9].key), custTable.rows[9].value},
},
},
{
// Select keys & values for all records with a key prefix of "001".
// or a key prefix of "002".
"select k, v from Customer where k like \"001%\" or k like \"002%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
},
},
{
// Select keys & values for all records with a key prefix of "001".
// or a key prefix of "002".
"select k, v from Customer where k like \"002%\" or k like \"001%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
},
},
{
// Let's play with whitespace and mixed case.
" sElEcT k, v from \n Customer WhErE k lIkE \"002%\" oR k LiKe \"001%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
},
},
{
// Add in a like clause that accepts all strings.
" sElEcT k, v from \n Customer WhErE k lIkE \"002%\" oR k LiKe \"001%\" or k lIkE \"%\"",
[]string{"k", "v"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key), custTable.rows[2].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), custTable.rows[3].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[4].key), custTable.rows[4].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key), custTable.rows[5].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key), custTable.rows[6].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key), custTable.rows[7].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key), custTable.rows[8].value},
[]*vdl.Value{vdl.ValueOf(custTable.rows[9].key), custTable.rows[9].value},
},
},
{
// Select id, name for customers whose last name is Masterson.
"select v.Id as ID, v.Name as Name from Customer where Type(v) like \"%.Customer\" and v.Name like \"%Masterson\"",
[]string{"ID", "Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(2)), vdl.ValueOf("Bat Masterson")},
},
},
{
// Select records where v.Address.City is "Collins" or type is Invoice.
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
},
},
{
"select k from Customer where k >= \"002001\" and k <= \"002002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002001")},
[]*vdl.Value{vdl.ValueOf("002002")},
},
},
{
"select k from Customer where k > \"002001\" and k <= \"002002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002002")},
},
},
{
"select k from Customer where k > \"002001\" and k < \"002002\"",
[]string{"k"},
[][]*vdl.Value{},
},
{
"select k from Customer where k > \"002001\" or k < \"002002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("001")},
[]*vdl.Value{vdl.ValueOf("001001")},
[]*vdl.Value{vdl.ValueOf("001002")},
[]*vdl.Value{vdl.ValueOf("001003")},
[]*vdl.Value{vdl.ValueOf("002")},
[]*vdl.Value{vdl.ValueOf("002001")},
[]*vdl.Value{vdl.ValueOf("002002")},
[]*vdl.Value{vdl.ValueOf("002003")},
[]*vdl.Value{vdl.ValueOf("002004")},
[]*vdl.Value{vdl.ValueOf("003")},
},
},
{
"select k from Customer where k <> \"002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("001")},
[]*vdl.Value{vdl.ValueOf("001001")},
[]*vdl.Value{vdl.ValueOf("001002")},
[]*vdl.Value{vdl.ValueOf("001003")},
[]*vdl.Value{vdl.ValueOf("002001")},
[]*vdl.Value{vdl.ValueOf("002002")},
[]*vdl.Value{vdl.ValueOf("002003")},
[]*vdl.Value{vdl.ValueOf("002004")},
[]*vdl.Value{vdl.ValueOf("003")},
},
},
{
"select k from Customer where k <> \"002\" or k like \"002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("001")},
[]*vdl.Value{vdl.ValueOf("001001")},
[]*vdl.Value{vdl.ValueOf("001002")},
[]*vdl.Value{vdl.ValueOf("001003")},
[]*vdl.Value{vdl.ValueOf("002")},
[]*vdl.Value{vdl.ValueOf("002001")},
[]*vdl.Value{vdl.ValueOf("002002")},
[]*vdl.Value{vdl.ValueOf("002003")},
[]*vdl.Value{vdl.ValueOf("002004")},
[]*vdl.Value{vdl.ValueOf("003")},
},
},
{
"select k from Customer where k <> \"002\" and k like \"002\"",
[]string{"k"},
[][]*vdl.Value{},
},
{
"select k from Customer where k <> \"002\" and k like \"002%\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002001")},
[]*vdl.Value{vdl.ValueOf("002002")},
[]*vdl.Value{vdl.ValueOf("002003")},
[]*vdl.Value{vdl.ValueOf("002004")},
},
},
{
"select k from Customer where k <> \"002\" and k like \"%002\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("001002")},
[]*vdl.Value{vdl.ValueOf("002002")},
},
},
{
// Select records where v.Address.City is "Collins" and v.InvoiceNum is not nil.
"select v from Customer where v.Address.City = \"Collins\" and v.InvoiceNum is not nil",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select records where v.Address.City is "Collins" and v.InvoiceNum is nil.
"select v from Customer where v.Address.City = \"Collins\" and v.InvoiceNum is nil",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[4].value},
},
},
{
// Select customer name for customer Id (i.e., key) "001".
"select v.Name as Name from Customer where Type(v) like \"%.Customer\" and k = \"001\"",
[]string{"Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("John Smith")},
},
},
{
// Select v where v.Credit.Report.EquifaxReport.Rating = 'A'
"select v from Customer where v.Credit.Report.EquifaxReport.Rating = 'A'",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
},
},
{
// Select v where v.AgencyRating = "Bad"
"select v from Customer where v.Credit.Report.EquifaxReport.Rating < 'A' or v.Credit.Report.ExperianReport.Rating = \"Bad\" or v.Credit.Report.TransUnionReport.Rating < 90",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[4].value},
},
},
{
// Select records where v.Bar.Baz.Name = "FooBarBaz"
"select v from Foo where v.Bar.Baz.Name = \"FooBarBaz\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{fooTable.rows[0].value},
},
},
{
// Select records where v.Bar.Baz.TitleOrValue.Value = 42
"select v from Foo where v.Bar.Baz.TitleOrValue.Value = 42",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{fooTable.rows[1].value},
},
},
{
// Select records where v.Bar.Baz.TitleOrValue.Title = "Vice President"
"select v from Foo where v.Bar.Baz.TitleOrValue.Title = \"Vice President\"",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{fooTable.rows[0].value},
},
},
{
// Select records where v.Address.City = "Collins" or type is Invoice.
// Limit 3
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\" limit 3",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
},
},
{
// Select records where v.Address.City = "Collins" or type is Invoice.
// Offset 5
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\" offset 5",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
},
},
{
// Select records where v.Address.City = "Collins" is "Mountain View".
"select v from Customer where v.Address.City = \"Mountain View\"",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select records where v.Address.City = "Collins" or type is Invoice.
// Offset 8
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\" offset 8",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select records where v.Address.City = "Collins" or type is Invoice.
// Offset 23
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\" offset 23",
[]string{"v"},
[][]*vdl.Value{},
},
{
// Select records where v.Address.City = "Collins" is 84 or type is Invoice.
// Limit 3 Offset 2
"select v from Customer where v.Address.City = \"Collins\" or Type(v) like \"%.Invoice\" limit 3 offset 2",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
},
},
{
// Select records where v.Address.City = "Collins" or (type is Invoice and v.InvoiceNum is not nil).
// Limit 3 Offset 2
"select v from Customer where v.Address.City = \"Collins\" or (Type(v) like \"%.Invoice\" and v.InvoiceNum is not nil) limit 3 offset 2",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
},
},
{
// Select records where v.Address.City = "Collins" or (type is Invoice and v.InvoiceNum is nil).
// Limit 3 Offset 2
"select v from Customer where v.Address.City = \"Collins\" or (Type(v) like \"%.Invoice\" and v.InvoiceNum is nil) limit 3 offset 2",
[]string{"v"},
[][]*vdl.Value{},
},
// Test functions.
{
// Select invoice records where date is 2015-03-17
"select v from Customer where Type(v) like \"%.Invoice\" and YMD(v.InvoiceDate, \"America/Los_Angeles\") = Date(\"2015-03-17 PDT\")",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
},
},
{
// Now will always be > 2012, so all customer records will be returned.
"select v from Customer where Now() > Date(\"2012-03-17 PDT\")",
[]string{"v"},
[][]*vdl.Value{
[]*vdl.Value{custTable.rows[0].value},
[]*vdl.Value{custTable.rows[1].value},
[]*vdl.Value{custTable.rows[2].value},
[]*vdl.Value{custTable.rows[3].value},
[]*vdl.Value{custTable.rows[4].value},
[]*vdl.Value{custTable.rows[5].value},
[]*vdl.Value{custTable.rows[6].value},
[]*vdl.Value{custTable.rows[7].value},
[]*vdl.Value{custTable.rows[8].value},
[]*vdl.Value{custTable.rows[9].value},
},
},
{
// Select April 2015 PT invoices.
// Note: this wouldn't work for March as daylight saving occurs March 8
// and causes comparisons for those days to be off 1 hour.
// It would work to use UTC -- see next test.
"select k from Customer where YM(v.InvoiceDate, \"America/Los_Angeles\") = YM(Date(\"2015-04-01 PDT\"), \"America/Los_Angeles\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key)},
},
},
{
// Select March 2015 UTC invoices.
"select k from Customer where YM(v.InvoiceDate, \"UTC\") = YM(Date(\"2015-03-01 UTC\"), \"UTC\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key)},
},
},
{
// Select 2015 UTC invoices.
"select k from Customer where Y(v.InvoiceDate, \"UTC\") = Y(Date(\"2015-01-01 UTC\"), \"UTC\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[2].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key)},
},
},
{
// Select the Mar 17 2015 11:14:04 America/Los_Angeles invoice.
"select k from Customer where v.InvoiceDate = DateTime(\"2015-03-17 11:14:04 PDT\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
},
},
{
// Select invoices in the minute Mar 17 2015 11:14 America/Los_Angeles invoice.
"select k from Customer where YMDHM(v.InvoiceDate, \"America/Los_Angeles\") = YMDHM(DateTime(\"2015-03-17 11:14:00 PDT\"), \"America/Los_Angeles\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
},
},
{
// Select invoices in the hour Mar 17 2015 11 hundred America/Los_Angeles invoice.
"select k from Customer where YMDH(v.InvoiceDate, \"America/Los_Angeles\") = YMDH(DateTime(\"2015-03-17 11:00:00 PDT\"), \"America/Los_Angeles\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
},
},
{
// Select invoices on the day Mar 17 2015 America/Los_Angeles invoice.
"select k from Customer where YMD(v.InvoiceDate, \"America/Los_Angeles\") = YMD(Date(\"2015-03-17 PDT\"), \"America/Los_Angeles\")",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key)},
},
},
// Test string functions in where clause.
{
// Select invoices shipped to Any street -- using Lowercase.
"select k from Customer where Type(v) like \"%.Invoice\" and Lowercase(v.ShipTo.Street) like \"%any%\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key)},
},
},
{
// Select invoices shipped to Any street -- using Uppercase.
"select k from Customer where Type(v) like \"%.Invoice\" and Uppercase(v.ShipTo.Street) like \"%ANY%\"",
[]string{"k"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[6].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[7].key)},
[]*vdl.Value{vdl.ValueOf(custTable.rows[8].key)},
},
},
// Select clause functions.
// Date function
{
"select Date(\"2015-07-01 PDT\") from Customer",
[]string{"Date"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01)},
},
},
// DateTime function
{
"select DateTime(\"2015-07-01 01:23:45 PDT\") from Customer",
[]string{"DateTime"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
[]*vdl.Value{vdl.ValueOf(t2015_07_01_01_23_45)},
},
},
// Lowercase function
{
"select Lowercase(v.Name) as name from Customer where Type(v) like \"%.Customer\"",
[]string{"name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("john smith")},
[]*vdl.Value{vdl.ValueOf("bat masterson")},
[]*vdl.Value{vdl.ValueOf("john steed")},
},
},
// Uppercase function
{
"select Uppercase(v.Name) as NAME from Customer where Type(v) like \"%.Customer\"",
[]string{"NAME"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("JOHN SMITH")},
[]*vdl.Value{vdl.ValueOf("BAT MASTERSON")},
[]*vdl.Value{vdl.ValueOf("JOHN STEED")},
},
},
// YMDHMS function
{
"select k, YMDHMS(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"002003\"",
[]string{
"k",
"YMDHMS",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002003"), vdl.ValueOf(t2015_04_12_22_16_06)},
},
},
// YMDHM function
{
"select k, YMDHM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"002003\"",
[]string{
"k",
"YMDHM",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002003"), vdl.ValueOf(t2015_04_12_22_16)},
},
},
// YMDH function
{
"select k, YMDH(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"002003\"",
[]string{
"k",
"YMDH",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002003"), vdl.ValueOf(t2015_04_12_22)},
},
},
// YMD function
{
"select k, YMD(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"002003\"",
[]string{
"k",
"YMD",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002003"), vdl.ValueOf(t2015_04_12)},
},
},
// YM function
{
"select k, YM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"002003\"",
[]string{
"k",
"YM",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("002003"), vdl.ValueOf(t2015_04)},
},
},
// Y function
{
"select k, Y(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"001001\"",
[]string{
"k",
"Y",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("001001"), vdl.ValueOf(t2015)},
},
},
// Nested functions
{
"select Y(YM(YMD(YMDH(YMDHM(YMDHMS(v.InvoiceDate, \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\") from Customer where Type(v) like \"%.Invoice\" and k = \"001001\"",
[]string{"Y"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(t2015)},
},
},
// Bad arg to function. Expression is false.
{
"select v from Customer where Type(v) like \"%.Invoice\" and YMD(v.InvoiceDate, v.Foo) = v.InvoiceDate",
[]string{"v"},
[][]*vdl.Value{},
},
// Map in selection
{
"select v.Credit.Report.TransUnionReport.PreviousRatings[\"2015Q2\"] from Customer where v.Name = \"Bat Masterson\"",
[]string{"v.Credit.Report.TransUnionReport.PreviousRatings[2015Q2]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int16(40))},
},
},
// Map in selection using function as key.
{
"select v.Credit.Report.TransUnionReport.PreviousRatings[Uppercase(\"2015q2\")] from Customer where v.Name = \"Bat Masterson\"",
[]string{"v.Credit.Report.TransUnionReport.PreviousRatings[Uppercase]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int16(40))},
},
},
// Map in selection using struct as key.
{
"select v.Map[v.Key] from FunWithMaps",
[]string{"v.Map[v.Key]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(V{"ccc", 14.7})},
[]*vdl.Value{vdl.ValueOf(V{"yyy", 17.1})},
},
},
// map of int16 to array of sets of strings
{
"select v.Confusing[23][0][\"foo\"] from FunWithMaps",
[]string{"v.Confusing[23][0][foo]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(true)},
[]*vdl.Value{vdl.ValueOf(nil)},
},
},
// Function using a map lookup as arg
{
"select Uppercase(v.B[true]) from ManyMaps",
[]string{"Uppercase"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("IT WAS THE BEST OF TIMES,")},
},
},
// Set in selection
{
"select v.Credit.Report.ExperianReport.TdhApprovals[\"Tom\"], v.Credit.Report.ExperianReport.TdhApprovals[\"Dick\"], v.Credit.Report.ExperianReport.TdhApprovals[\"Harry\"] from Customer where v.Name = \"John Steed\"",
[]string{
"v.Credit.Report.ExperianReport.TdhApprovals[Tom]",
"v.Credit.Report.ExperianReport.TdhApprovals[Dick]",
"v.Credit.Report.ExperianReport.TdhApprovals[Harry]",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(true), vdl.ValueOf(false), vdl.ValueOf(true)},
},
},
// List in selection
{
"select v.PreviousAddresses[0].Street from Customer where v.Name = \"Bat Masterson\"",
[]string{"v.PreviousAddresses[0].Street"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("19 Green St.")},
},
},
// List in selection (index out of bounds)
{
"select v.PreviousAddresses[2].Street from Customer where v.Name = \"Bat Masterson\"",
[]string{"v.PreviousAddresses[2].Street"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(nil)},
},
},
// Array in selection
{
"select v.Credit.Report.EquifaxReport.FourScoreRatings[2] from Customer where v.Name = \"John Smith\"",
[]string{"v.Credit.Report.EquifaxReport.FourScoreRatings[2]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int16(42))},
},
},
// Array in selection (using an array as the index)
// Note: v.Credit.Report.EquifaxReport.FourScoreRatings[3] is 2
// and v.Credit.Report.EquifaxReport.FourScoreRatings[2] is 42
{
"select v.Credit.Report.EquifaxReport.FourScoreRatings[v.Credit.Report.EquifaxReport.FourScoreRatings[3]] from Customer where v.Name = \"John Smith\"",
[]string{"v.Credit.Report.EquifaxReport.FourScoreRatings[v.Credit.Report.EquifaxReport.FourScoreRatings[3]]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int16(42))},
},
},
// Array in selection (index out of bounds)
{
"select v.Credit.Report.EquifaxReport.FourScoreRatings[4] from Customer where v.Name = \"John Smith\"",
[]string{"v.Credit.Report.EquifaxReport.FourScoreRatings[4]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(nil)},
},
},
// Map in where expression
{
"select v.Name from Customer where v.Credit.Report.TransUnionReport.PreviousRatings[\"2015Q2\"] = 40",
[]string{"v.Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("Bat Masterson")},
},
},
// Set in where expression (convert string to enum to do lookup)
{
"select v.Name from Customer where v.Credit.Report.ExperianReport.TdhApprovals[\"Tom\"] = true",
[]string{
"v.Name",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("John Steed")},
},
},
// Negative case: Set in where expression (convert string to enum to do lookup)
{
"select v.Name from Customer where v.Credit.Report.ExperianReport.TdhApprovals[\"Dick\"] = true",
[]string{
"v.Name",
},
[][]*vdl.Value{},
},
// Set in where expression (use another field as lookup key)
// Find all customers where experian auditor was also an approver.
{
"select v.Name from Customer where v.Credit.Report.ExperianReport.TdhApprovals[v.Credit.Report.ExperianReport.Auditor] = true",
[]string{
"v.Name",
},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("John Steed")},
},
},
// List in where expression
{
"select v.Name from Customer where v.PreviousAddresses[0].Street = \"19 Green St.\"",
[]string{"v.Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("Bat Masterson")},
},
},
// List in where expression (index out of bounds)
{
"select v.Name from Customer where v.PreviousAddresses[10].Street = \"19 Green St.\"",
[]string{"v.Name"},
[][]*vdl.Value{},
},
// Array in where expression
{
"select v.Name from Customer where v.Credit.Report.EquifaxReport.FourScoreRatings[2] = 42",
[]string{"v.Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("John Smith")},
},
},
// Array in where expression (using another field as index)
// Note: v.Credit.Report.EquifaxReport.FourScoreRatings[3] is 2
// and v.Credit.Report.EquifaxReport.FourScoreRatings[2] is 42
{
"select v.Name from Customer where v.Credit.Report.EquifaxReport.FourScoreRatings[v.Credit.Report.EquifaxReport.FourScoreRatings[3]] = 42",
[]string{"v.Name"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf("John Smith")},
},
},
// Array in where expression (index out of bounds, using another field as index)
{
"select v.Name from Customer where v.Credit.Report.EquifaxReport.FourScoreRatings[v.Credit.Report.EquifaxReport.FourScoreRatings[2]] = 42",
[]string{"v.Name"},
[][]*vdl.Value{},
},
// Array in select and where expressions (top level value is the array)
{
"select v[0], v[1], v[2], v[3] from RatingsArray where v[0] = 40",
[]string{"v[0]", "v[1]", "v[2]", "v[3]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int16(40)), vdl.ValueOf(int16(20)), vdl.ValueOf(int16(10)), vdl.ValueOf(int16(0))},
},
},
// List in select and where expressions (top level value is the list)
{
"select v[-1].City, v[0].City, v[1].City, v[2].City from PreviousAddresses where v[1].Street = \"200 Main St.\"",
[]string{"v[-1].City", "v[0].City", "v[1].City", "v[2].City"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf("Anytown"), vdl.ValueOf("Othertown"), vdl.ValueOf(nil)},
},
},
// Set in select and where expressions (top level value is the set)
{
"select v[\"Tom\"], v[\"Dick\"], v[\"Harry\"] from TdhApprovals where v[\"Dick\"] = true",
[]string{"v[Tom]", "v[Dick]", "v[Harry]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(false), vdl.ValueOf(true), vdl.ValueOf(true)},
},
},
// Map in select and where expressions (top level value is the map)
{
"select v[\"1Q2015\"], v[\"2Q2015\"] from PreviousRatings where v[\"2Q2015\"] = 3",
[]string{"v[1Q2015]", "v[2Q2015]"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(nil), vdl.ValueOf(int16(3))},
},
},
// Test lots of types as map keys
{
"select v.B[true], v.By[10], v.U16[16], v.U32[32], v.U64[64], v.I16[17], v.I32[33], v.I64[65], v.F32[32.1], v.F64[64.2], v.C64[Complex(456.789, 10.1112)], v.C128[Complex(123.456, 11.2223)], v.S[\"Dickens\"], v.Ms[\"Charles\"][\"Dickens\"], v.T[DateTime(\"2015-07-01 01:23:45 PDT\")] from ManyMaps",
[]string{"v.B[true]", "v.By[10]", "v.U16[16]", "v.U32[32]", "v.U64[64]", "v.I16[17]", "v.I32[33]", "v.I64[65]", "v.F32[32.1]", "v.F64[64.2]", "v.C64[Complex]", "v.C128[Complex]", "v.S[Dickens]", "v.Ms[Charles][Dickens]", "v.T[DateTime]"},
[][]*vdl.Value{
[]*vdl.Value{
vdl.ValueOf("It was the best of times,"),
vdl.ValueOf("it was the worst of times,"),
vdl.ValueOf("it was the age of wisdom,"),
vdl.ValueOf("it was the age of foolishness,"),
vdl.ValueOf("it was the epoch of belief,"),
vdl.ValueOf("it was the epoch of incredulity,"),
vdl.ValueOf("it was the season of Light,"),
vdl.ValueOf("it was the season of Darkness,"),
vdl.ValueOf("it was the spring of hope,"),
vdl.ValueOf("it was the winter of despair,"),
vdl.ValueOf("we had everything before us,"),
vdl.ValueOf("we had nothing before us,"),
vdl.ValueOf("we are all going direct to Heaven,"),
vdl.ValueOf("we are all going direct to Heaven,"),
vdl.ValueOf("we are all going direct the other way"),
},
},
},
// Test lots of types as set keys
{
"select v.B[true], v.By[10], v.U16[16], v.U32[32], v.U64[64], v.I16[17], v.I32[33], v.I64[65], v.F32[32.1], v.F64[64.2], v.C64[Complex(456.789, 10.1112)], v.C128[Complex(123.456, 11.2223)], v.S[\"Dickens\"], v.T[DateTime(\"2015-07-01 01:23:45 PDT\")] from ManySets",
[]string{"v.B[true]", "v.By[10]", "v.U16[16]", "v.U32[32]", "v.U64[64]", "v.I16[17]", "v.I32[33]", "v.I64[65]", "v.F32[32.1]", "v.F64[64.2]", "v.C64[Complex]", "v.C128[Complex]", "v.S[Dickens]", "v.T[DateTime]"},
[][]*vdl.Value{
[]*vdl.Value{
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
vdl.ValueOf(true),
},
},
},
{
"select k, v.Key from BigTable where k < \"101\" or k = \"200\" or k like \"300%\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{svPair("100"), svPair("200"), svPair("300")},
},
{
"select k, v.Key from BigTable where \"101\" > k or \"200\" = k or k like \"300%\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{svPair("100"), svPair("200"), svPair("300")},
},
{
"select k, v.Key from BigTable where k is nil",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k is not nil and \"103\" = v.Key",
[]string{"k", "v.Key"},
[][]*vdl.Value{svPair("103")},
},
{
"select k, v.Key from BigTable where k like \"10_\" or k like \"20_\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("100"),
svPair("101"),
svPair("102"),
svPair("103"),
svPair("104"),
svPair("105"),
svPair("106"),
svPair("107"),
svPair("108"),
svPair("109"),
svPair("200"),
svPair("201"),
svPair("202"),
svPair("203"),
svPair("204"),
svPair("205"),
svPair("206"),
svPair("207"),
svPair("208"),
svPair("209"),
},
},
{
"select k, v.Key from BigTable where k like \"_%9\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("109"),
svPair("119"),
svPair("129"),
svPair("139"),
svPair("149"),
svPair("159"),
svPair("169"),
svPair("179"),
svPair("189"),
svPair("199"),
svPair("209"),
svPair("219"),
svPair("229"),
svPair("239"),
svPair("249"),
svPair("259"),
svPair("269"),
svPair("279"),
svPair("289"),
svPair("299"),
},
},
{
"select k, v.Key from BigTable where k like \"__0\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("100"),
svPair("110"),
svPair("120"),
svPair("130"),
svPair("140"),
svPair("150"),
svPair("160"),
svPair("170"),
svPair("180"),
svPair("190"),
svPair("200"),
svPair("210"),
svPair("220"),
svPair("230"),
svPair("240"),
svPair("250"),
svPair("260"),
svPair("270"),
svPair("280"),
svPair("290"),
svPair("300"),
},
},
{
"select k, v.Key from BigTable where k like \"10%\" or k like \"20%\" or k like \"30%\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("100"),
svPair("101"),
svPair("102"),
svPair("103"),
svPair("104"),
svPair("105"),
svPair("106"),
svPair("107"),
svPair("108"),
svPair("109"),
svPair("200"),
svPair("201"),
svPair("202"),
svPair("203"),
svPair("204"),
svPair("205"),
svPair("206"),
svPair("207"),
svPair("208"),
svPair("209"),
svPair("300"),
},
},
{
"select k, v.Key from BigTable where k like \"1__\" and k like \"_2_\" and k like \"__3\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{svPair("123")},
},
{
"select k, v.Key from BigTable where (k > \"100\" and k < \"103\") or (k > \"205\" and k < \"208\")",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("101"),
svPair("102"),
svPair("206"),
svPair("207"),
},
},
{
"select k, v.Key from BigTable where ( \"100\" < k and \"103\" > k) or (\"205\" < k and \"208\" > k)",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("101"),
svPair("102"),
svPair("206"),
svPair("207"),
},
},
{
"select k, v.Key from BigTable where k <= \"100\" or k = \"101\" or k >= \"300\" or (k <> \"299\" and k not like \"300\" and k >= \"298\")",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("100"),
svPair("101"),
svPair("298"),
svPair("300"),
},
},
{
"select k, v.Key from BigTable where \"100\" >= k or \"101\" = k or \"300\" <= k or (\"299\" <> k and k not like \"300\" and \"298\" <= k)",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("100"),
svPair("101"),
svPair("298"),
svPair("300"),
},
},
{
"select k, v.Key from BigTable where k like \"1%\" and k like \"%9\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{
svPair("109"),
svPair("119"),
svPair("129"),
svPair("139"),
svPair("149"),
svPair("159"),
svPair("169"),
svPair("179"),
svPair("189"),
svPair("199"),
},
},
{
"select k, v.Key from BigTable where k like \"3%\" and k like \"30%\" and k like \"300%\"",
[]string{"k", "v.Key"},
[][]*vdl.Value{svPair("300")},
},
{
"select k, v.Key from BigTable where \"110\" > k",
[]string{"k", "v.Key"},
svPairs(100, 109),
},
{
"select k, v.Key from BigTable where \"110\" < k and \"205\" > k",
[]string{"k", "v.Key"},
svPairs(111, 204),
},
{
"select k, v.Key from BigTable where \"110\" <= k and \"205\" >= k",
[]string{"k", "v.Key"},
svPairs(110, 205),
},
{
"select k, v.Key from BigTable where k is nil",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k is not nil",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k <> k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k < k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k > k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k = k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k <= k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k >= k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k = v.Key",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where v.Key = k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where v.Key = k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k <> v.key",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where v.key <> k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k < v.key",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where v.key < k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k > v.key",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where v.key > k",
[]string{"k", "v.Key"},
[][]*vdl.Value{},
},
{
"select k, v.Key from BigTable where k >= v.Key",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where v.Key >= k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where k <= v.Key",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
"select k, v.Key from BigTable where v.Key <= k",
[]string{"k", "v.Key"},
svPairs(100, 300),
},
{
// Split on .
"select Split(Type(v), \".\") from Customer where k = \"001\"",
[]string{"Split"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf([]string{"v", "io/syncbase/v23/syncbase/nosql/internal/query/test", "Customer"})},
},
},
{
// Split on /
"select Split(Type(v), \"/\") from Customer where k = \"001\"",
[]string{"Split"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf([]string{"v.io", "syncbase", "v23", "syncbase", "nosql", "internal", "query", "test.Customer"})},
},
},
{
// Split on /, Len of array
"select Len(Split(Type(v), \"/\")) from Customer where k = \"001\"",
[]string{"Len"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(8))},
},
},
{
// Split on empty string, Len of array
// Split with sep == empty string splits on chars.
"select Len(Split(Type(v), \"\")) from Customer where k = \"001\"",
[]string{"Len"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(len("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")))},
},
},
{
// Len of string, list and struct.
// returns len of string, elements in list and nil for struct.
"select Len(v.Name), Len(v.PreviousAddresses), Len(v.Credit) from Customer where k = \"002\"",
[]string{"Len", "Len", "Len"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(13)), vdl.ValueOf(int64(2)), vdl.ValueOf(nil)},
},
},
{
// Len of set
"select Len(v.Credit.Report.ExperianReport.TdhApprovals) from Customer where Type(v) like \"%.Customer\" and k = \"003\"",
[]string{"Len"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(2))},
},
},
{
// Len of map
"select Len(v.Map) from FunWithMaps",
[]string{"Len"},
[][]*vdl.Value{
[]*vdl.Value{vdl.ValueOf(int64(2))},
[]*vdl.Value{vdl.ValueOf(int64(2))},
},
},
}
for _, test := range basic {
headers, rs, err := query.Exec(db, test.query)
if err != nil {
t.Errorf("query: %s; got %v, want nil", test.query, err)
} else {
// Collect results.
r := [][]*vdl.Value{}
for rs.Advance() {
r = append(r, rs.Result())
}
if !reflect.DeepEqual(test.r, r) {
t.Errorf("query: %s; got %v, want %v", test.query, r, test.r)
}
if !reflect.DeepEqual(test.headers, headers) {
t.Errorf("query: %s; got %v, want %v", test.query, headers, test.headers)
}
}
}
}
func svPair(s string) []*vdl.Value {
v := vdl.ValueOf(s)
return []*vdl.Value{v, v}
}
// Genearate k,v pairs for start to finish (*INCLUSIVE*)
func svPairs(start, finish int64) [][]*vdl.Value {
retVal := [][]*vdl.Value{}
for i := start; i <= finish; i++ {
v := vdl.ValueOf(fmt.Sprintf("%d", i))
retVal = append(retVal, []*vdl.Value{v, v})
}
return retVal
}
// Use Now to verify it is "pre" executed such that all the rows
// have the same time.
func TestPreExecFunctions(t *testing.T) {
basic := []preExecFunctionTest{
{
"select Now() from Customer",
[]string{
"Now",
},
},
}
for _, test := range basic {
headers, rs, err := query.Exec(db, test.query)
if err != nil {
t.Errorf("query: %s; got %v, want nil", test.query, err)
} else {
// Check that all results are identical.
// Collect results.
var last []*vdl.Value
for rs.Advance() {
result := rs.Result()
if last != nil && !reflect.DeepEqual(last, result) {
t.Errorf("query: %s; got %v, want %v", test.query, result, last)
}
last = result
}
if !reflect.DeepEqual(test.headers, headers) {
t.Errorf("query: %s; got %v, want %v", test.query, headers, test.headers)
}
}
}
}
func appendZeroByte(start string) string {
limit := []byte(start)
limit = append(limit, 0)
return string(limit)
}
func plusOne(start string) string {
limit := []byte(start)
for len(limit) > 0 {
if limit[len(limit)-1] == 255 {
limit = limit[:len(limit)-1] // chop off trailing \x00
} else {
limit[len(limit)-1] += 1 // add 1
break // no carry
}
}
return string(limit)
}
func TestKeyRanges(t *testing.T) {
basic := []keyRangesTest{
{
// Need all keys
"select k, v from Customer",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// Keys 001 or 003
" select k, v from Customer where k = \"001\" or k = \"003\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "001", Limit: appendZeroByte("001")},
query_db.KeyRange{Start: "003", Limit: appendZeroByte("003")},
},
nil,
},
{
// Keys 001 and 003 (resulting in no keys)
" select k, v from Customer where k = \"001\" and k = \"003\"",
&query_db.KeyRanges{},
nil,
},
{
// Need all keys
"select k, v from Customer where k like \"%\" or k like \"001%\" or k like \"002%\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// Need all keys, likes in where clause in different order
"select k, v from Customer where k like \"002%\" or k like \"001%\" or k like \"%\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// All selected rows will have key prefix of "abc".
"select k, v from Customer where Type(v) like \"%.Foo.Bar\" and k like \"abc%\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "abc", Limit: plusOne("abc")},
},
nil,
},
{
// Need all keys
"select k, v from Customer where Type(v) like \"%.Foo.Bar\" or k like \"abc%\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// Need all keys
"select k, v from Customer where k like \"abc%\" or v.zip = \"94303\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// All selected rows will have key prefix of "foo".
"select k, v from Customer where Type(v) like \"%.Foo.Bar\" and k like \"foo_bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo", Limit: plusOne("foo")},
},
nil,
},
{
// All selected rows will have key == "baz" or prefix of "foo".
"select k, v from Customer where k like \"foo_bar\" or k = \"baz\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "baz", Limit: appendZeroByte("baz")},
query_db.KeyRange{Start: "foo", Limit: plusOne("foo")},
},
nil,
},
{
// All selected rows will have key == "fo" or prefix of "foo".
"select k, v from Customer where k like \"foo_bar\" or k = \"fo\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "fo", Limit: appendZeroByte("fo")},
query_db.KeyRange{Start: "foo", Limit: plusOne("foo")},
},
nil,
},
{
// All selected rows will have prefix of "fo".
// k == foo is a subset of above prefix
"select k, v from Customer where k like \"fo_bar\" or k = \"foo\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "fo", Limit: plusOne("fo")},
},
nil,
},
{
// All selected rows will have key prefix of "foo".
"select k, v from Customer where k like \"foo%bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo", Limit: plusOne("foo")},
},
nil,
},
{
// Select "foo\bar" row.
"select k, v from Customer where k like \"foo\\\\bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo\\bar", Limit: appendZeroByte("foo\\bar")},
},
nil,
},
{
// Select "foo%bar" row.
"select k, v from Customer where k like \"foo\\%bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo%bar", Limit: appendZeroByte("foo%bar")},
},
nil,
},
{
// Select "foo\%bar" row.
"select k, v from Customer where k like \"foo\\\\\\%bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo\\%bar", Limit: appendZeroByte("foo\\%bar")},
},
nil,
},
{
// Need all keys
"select k, v from Customer where k like \"%foo\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// Need all keys
"select k, v from Customer where k like \"_foo\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "", Limit: ""},
},
nil,
},
{
// Select "foo_bar" row.
"select k, v from Customer where k like \"foo\\_bar\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foo_bar", Limit: appendZeroByte("foo_bar")},
},
nil,
},
{
// Select "foobar%" row.
"select k, v from Customer where k like \"foobar\\%\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foobar%", Limit: appendZeroByte("foobar%")},
},
nil,
},
{
// Select "foobar_" row.
"select k, v from Customer where k like \"foobar\\_\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "foobar_", Limit: appendZeroByte("foobar_")},
},
nil,
},
{
// Select "\%_" row.
"select k, v from Customer where k like \"\\\\\\%\\_\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "\\%_", Limit: appendZeroByte("\\%_")},
},
nil,
},
{
// Select "%_abc\" row.
"select k, v from Customer where k = \"%_abc\\\"",
&query_db.KeyRanges{
query_db.KeyRange{Start: "%_abc\\", Limit: appendZeroByte("%_abc\\")},
},
nil,
},
}
for _, test := range basic {
s, synErr := query_parser.Parse(db, test.query)
if synErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, synErr)
}
if synErr == nil {
semErr := query_checker.Check(db, s)
if semErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, semErr)
}
if semErr == nil {
switch sel := (*s).(type) {
case query_parser.SelectStatement:
keyRanges := query_checker.CompileKeyRanges(sel.Where)
if !reflect.DeepEqual(test.keyRanges, keyRanges) {
t.Errorf("query: %s;\nGOT %v\nWANT %v", test.query, keyRanges, test.keyRanges)
}
default:
t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
}
}
}
}
}
func TestEvalWhereUsingOnlyKey(t *testing.T) {
basic := []evalWhereUsingOnlyKeyTest{
{
// Row will be selected using only the key.
"select k, v from Customer where k like \"abc%\"",
"abcdef",
query.INCLUDE,
},
{
// Row will be rejected using only the key.
"select k, v from Customer where k like \"abc\"",
"abcd",
query.EXCLUDE,
},
{
// Need value to determine if row should be selected.
"select k, v from Customer where k = \"abc\" or v.zip = \"94303\"",
"abcd",
query.FETCH_VALUE,
},
{
// Need value (i.e., its type) to determine if row should be selected.
"select k, v from Customer where k = \"xyz\" or Type(v) like \"%.foo.Bar\"",
"wxyz",
query.FETCH_VALUE,
},
{
// Although value is in where clause, it is not needed to reject row.
"select k, v from Customer where k = \"abcd\" and v.zip = \"94303\"",
"abcde",
query.EXCLUDE,
},
}
for _, test := range basic {
s, synErr := query_parser.Parse(db, test.query)
if synErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, synErr)
}
if synErr == nil {
semErr := query_checker.Check(db, s)
if semErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, semErr)
}
if semErr == nil {
switch sel := (*s).(type) {
case query_parser.SelectStatement:
result := query.EvalWhereUsingOnlyKey(db, &sel, test.key)
if result != test.result {
t.Errorf("query: %s; got %v, want %v", test.query, result, test.result)
}
default:
t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
}
}
}
}
}
func TestEval(t *testing.T) {
basic := []evalTest{
{
"select k, v from Customer where Type(v) = \"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer\"",
custTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where Type(v) like \"%.Customer\"",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v.Name = \"John Smith\"",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v.Name = v.Name",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v = v",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v > v",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v < v",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v >= v",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v <= v",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v.Credit.Report.EquifaxReport.Rating = 'A'",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v.Credit.Report.EquifaxReport.Rating <> 'A'",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v.Credit.Report.EquifaxReport.Rating >= 'B'",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v.Credit.Report.EquifaxReport.Rating <= 'B'",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v.Credit.Report.TransUnionReport.Rating = 80",
numTable.rows[0].key, custTable.rows[4].value, true,
},
{
"select k, v from Customer where v.Credit.Report.TransUnionReport.Rating <> 80",
numTable.rows[0].key, custTable.rows[4].value, false,
},
{
"select k, v from Customer where v.Cr4dit.Report.TransUnionReport.Rating <= 70",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Customer where v.Credit.Report.TransUnionReport.Rating >= 70",
numTable.rows[0].key, custTable.rows[4].value, true,
},
{
"select k, v from Customer where v.Active = true",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
"select k, v from Customer where v.Active = false",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
"select k, v from Numbers where 12 = v.B",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where 11 < v.B",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.B > 10",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.B >= 14",
numTable.rows[0].key, numTable.rows[0].value, false,
},
{
"select k, v from Numbers where v.B >= 11.0",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.Ui64 = 999888777666",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.Ui64 < 999888777666",
numTable.rows[0].key, numTable.rows[0].value, false,
},
{
"select k, v from Numbers where v.B < v.Ui64",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.C64 = \"(123+7i)\"",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.C64 = Complex(123, 7)",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.C128 = \"(456.789+10.1112i)\"",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.C128 = Complex(456.789, 10.1112)",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.Ui16 = 1234",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.Ui32 = 5678",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.I16 = 9876",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
"select k, v from Numbers where v.I32 = 876543",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
// Deeply nested.
"select v from Foo where v.Bar.Baz.Name = \"FooBarBaz\"",
numTable.rows[0].key, fooTable.rows[0].value, true,
},
{
// Convert int64 to string
"select v from Customer where v.CustId = \"1\"",
numTable.rows[0].key, custTable.rows[1].value, true,
},
{
// Convert bool to string
"select v from Customer where v.Active = \"true\"",
numTable.rows[0].key, custTable.rows[0].value, true,
},
{
// Bool can't convert to other types.
"select v from Customer where v.Active = 1",
numTable.rows[0].key, custTable.rows[0].value, false,
},
{
// Test that numeric types can compare to a float64
"select v from Numbers where v.F64 = v.B and v.F64 = v.Ui16 and v.F64 = v.Ui32 and v.F64 = v.Ui64 and v.F64 = v.I16 and v.F64 = v.I32 and v.F64 = v.I64 and v.F64 = v.F32 and v.F64 = v.C64 and v.F64 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test that all numeric types can compare to an int32
"select v from Numbers where v.I32 = v.B and v.I32 = v.Ui16 and v.I32 = v.Ui32 and v.I32 = v.Ui64 and v.I32 = v.I16 and v.I32 = v.F64 and v.I32 = v.I64 and v.I32 = v.F32 and v.I32 = v.C64 and v.I32 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test that all numeric types can compare to an int16
"select v from Numbers where v.I16 = v.B and v.I16 = v.Ui16 and v.I16 = v.Ui32 and v.I16 = v.Ui64 and v.I16 = v.F64 and v.I16 = v.I32 and v.I16 = v.I64 and v.I16 = v.F32 and v.I16 = v.C64 and v.I16 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test that all numeric types can compare to an uint64
"select v from Numbers where v.Ui64 = v.B and v.Ui64 = v.Ui16 and v.Ui64 = v.Ui32 and v.Ui64 = v.F64 and v.Ui64 = v.I16 and v.Ui64 = v.I32 and v.Ui64 = v.I64 and v.Ui64 = v.F32 and v.Ui64 = v.C64 and v.Ui64 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test that all numeric types can compare to an uint32
"select v from Numbers where v.Ui32 = v.B and v.Ui32 = v.Ui16 and v.Ui32 = v.F64 and v.Ui32 = v.Ui64 and v.Ui32 = v.I16 and v.Ui32 = v.I32 and v.Ui32 = v.I64 and v.Ui32 = v.F32 and v.Ui32 = v.C64 and v.Ui32 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test that all numeric types can compare to an uint16
"select v from Numbers where v.Ui16 = v.B and v.Ui16 = v.F64 and v.Ui16 = v.Ui32 and v.Ui16 = v.Ui64 and v.Ui16 = v.I16 and v.Ui16 = v.I32 and v.Ui16 = v.I64 and v.Ui16 = v.F32 and v.Ui16 = v.C64 and v.Ui16 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test C64 = C128
"select v from Numbers where v.C64 = v.C128",
numTable.rows[2].key, numTable.rows[2].value, true,
},
{
// Test C64 <> C128
"select v from Numbers where v.C64 <> v.C128",
numTable.rows[0].key, numTable.rows[0].value, true,
},
{
// Complex integers can only compare to themselves and other numerics.
// Compare to integer
"select v from Numbers where v.C128 <> false",
numTable.rows[0].key, numTable.rows[0].value, false,
},
{
"select v from Numbers where v.C128 = \"(456.789+10.1112i)\"",
numTable.rows[0].key, numTable.rows[0].value, true,
},
}
for _, test := range basic {
s, synErr := query_parser.Parse(db, test.query)
if synErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, synErr)
}
if synErr == nil {
semErr := query_checker.Check(db, s)
if semErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, semErr)
}
if semErr == nil {
switch sel := (*s).(type) {
case query_parser.SelectStatement:
result := query.Eval(db, test.k, test.v, sel.Where.Expr)
if result != test.result {
t.Errorf("query: %s; got %v, want %v", test.query, result, test.result)
}
default:
t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
}
}
}
}
}
func TestProjection(t *testing.T) {
basic := []projectionTest{
{
"select k, v from Customer where Type(v) like \"%.Customer\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{
vdl.ValueOf("123456"),
custTable.rows[0].value,
},
},
{
"select k, v, v.Name, v.Id, v.Active, v.Credit.Agency, v.Credit.Report.EquifaxReport.Rating, v.Address.Street, v.Address.City, v.Address.State, v.Address.Zip from Customer where Type(v) like \"%.Customer\"",
custTable.rows[0].key, custTable.rows[0].value,
[]*vdl.Value{
vdl.ValueOf(custTable.rows[0].key),
custTable.rows[0].value,
vdl.ValueOf("John Smith"),
vdl.ValueOf(int64(1)),
vdl.ValueOf(true),
vdl.ValueOf(CreditAgencyEquifax),
vdl.ValueOf(byte('A')),
vdl.ValueOf("1 Main St."),
vdl.ValueOf("Palo Alto"),
vdl.ValueOf("CA"),
vdl.ValueOf("94303"),
},
},
}
for _, test := range basic {
s, synErr := query_parser.Parse(db, test.query)
if synErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, synErr)
}
if synErr == nil {
semErr := query_checker.Check(db, s)
if semErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, semErr)
}
if semErr == nil {
switch sel := (*s).(type) {
case query_parser.SelectStatement:
result := query.ComposeProjection(db, test.k, test.v, sel.Select)
if !reflect.DeepEqual(result, test.result) {
t.Errorf("query: %s; got %v, want %v", test.query, result, test.result)
}
default:
t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
}
}
}
}
}
func TestExecSelectSingleRow(t *testing.T) {
basic := []execSelectSingleRowTest{
{
"select k, v from Customer where Type(v) like \"%.Customer\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{
vdl.ValueOf("123456"),
custTable.rows[0].value,
},
},
{
"select k, v from Customer where Type(v) like \"%.Customer\" and k like \"123%\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{
vdl.ValueOf("123456"),
custTable.rows[0].value,
},
},
{
"select k, v from Customer where Type(v) like \"%.Invoice\" and k like \"123%\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{},
},
{
"select k, v from Customer where Type(v) like \"%.Customer\" and k like \"456%\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{},
},
{
"select v from Customer where v.Name = \"John Smith\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{
custTable.rows[0].value,
},
},
{
"select v from Customer where v.Name = \"John Doe\"",
"123456", custTable.rows[0].value,
[]*vdl.Value{},
},
{
"select k, v, v.Name, v.Id, v.Active, v.Credit.Report.EquifaxReport.Rating, v.Credit.Report.ExperianReport.Rating, v.Credit.Report.TransUnionReport.Rating, v.Address.Street, v.Address.City, v.Address.State, v.Address.Zip from Customer where Type(v) like \"%.Customer\"",
custTable.rows[0].key, custTable.rows[0].value,
[]*vdl.Value{
vdl.ValueOf(custTable.rows[0].key),
custTable.rows[0].value,
vdl.ValueOf("John Smith"),
vdl.ValueOf(int64(1)),
vdl.ValueOf(true),
vdl.ValueOf(byte('A')),
vdl.ValueOf(nil),
vdl.ValueOf(nil),
vdl.ValueOf("1 Main St."),
vdl.ValueOf("Palo Alto"),
vdl.ValueOf("CA"),
vdl.ValueOf("94303"),
},
},
}
for _, test := range basic {
s, synErr := query_parser.Parse(db, test.query)
if synErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, synErr)
}
if synErr == nil {
semErr := query_checker.Check(db, s)
if semErr != nil {
t.Errorf("query: %s; got %v, want nil", test.query, semErr)
}
if semErr == nil {
switch sel := (*s).(type) {
case query_parser.SelectStatement:
result := query.ExecSelectSingleRow(db, test.k, test.v, &sel)
if !reflect.DeepEqual(result, test.result) {
t.Errorf("query: %s; got %v, want %v", test.query, result, test.result)
}
default:
t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
}
}
}
}
}
// TODO(jkline): More negative tests here (even though they are tested elsewhere)?
func TestExecErrors(t *testing.T) {
basic := []execSelectErrorTest{
{
"select a from Customer",
syncql.NewErrInvalidSelectField(db.GetContext(), 7),
},
{
"select v from Unknown",
// The following error text is dependent on implementation of Database.
syncql.NewErrTableCantAccess(db.GetContext(), 14, "Unknown", errors.New("No such table: Unknown.")),
},
{
"select v from Customer offset -1",
// The following error text is dependent on implementation of Database.
syncql.NewErrExpected(db.GetContext(), 30, "positive integer literal"),
},
{
"select k, v.Key from BigTable where 110 <= k and 205 >= k",
syncql.NewErrKeyExpressionLiteral(db.GetContext(), 36),
},
{
"select k, v.Key from BigTable where Type(k) = \"BigData\"",
syncql.NewErrArgMustBeField(db.GetContext(), 41),
},
{
"select v from Customer where Len(10) = 3",
syncql.NewErrFunctionLenInvalidArg(db.GetContext(), 33),
},
{
"select K from Customer where Type(v) = \"Invoice\"",
syncql.NewErrDidYouMeanLowercaseK(db.GetContext(), 7),
},
{
"select V from Customer where Type(v) = \"Invoice\"",
syncql.NewErrDidYouMeanLowercaseV(db.GetContext(), 7),
},
{
"select k from Customer where K = \"001\"",
syncql.NewErrDidYouMeanLowercaseK(db.GetContext(), 29),
},
{
"select v from Customer where Type(V) = \"Invoice\"",
syncql.NewErrDidYouMeanLowercaseV(db.GetContext(), 34),
},
{
"select K, V from Customer where Type(V) = \"Invoice\" and K = \"001\"",
syncql.NewErrDidYouMeanLowercaseK(db.GetContext(), 7),
},
{
"select type(v) from Customer where Type(v) = \"Invoice\"",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Type"),
},
{
"select Type(v) from Customer where type(v) = \"Invoice\"",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 35, "Type"),
},
{
"select type(v) from Customer where type(v) = \"Invoice\"",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Type"),
},
{
"select date(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Date"),
},
{
"select Datetime(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "DateTime"),
},
{
"select y(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Y"),
},
{
"select ym(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "YM"),
},
{
"select ymd(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "YMD"),
},
{
"select ymdh(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "YMDH"),
},
{
"select ymdhm(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "YMDHM"),
},
{
"select ymdhms(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "YMDHMS"),
},
{
"select now() from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Now"),
},
{
"select LowerCase(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Lowercase"),
},
{
"select UPPERCASE(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Uppercase"),
},
{
"select spliT(\"foo:bar\", \":\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Split"),
},
{
"select comPLex(1.0, 2.0) from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Complex"),
},
{
"select len(\"foo\") from Customer",
syncql.NewErrDidYouMeanFunction(db.GetContext(), 7, "Len"),
},
}
for _, test := range basic {
_, _, err := query.Exec(db, test.query)
// Test both that the IDs compare and the text compares (since the offset needs to match).
if verror.ErrorID(err) != verror.ErrorID(test.err) || err.Error() != test.err.Error() {
t.Errorf("query: %s; got %v, want %v", test.query, err, test.err)
}
}
}
func TestResolveField(t *testing.T) {
basic := []execResolveFieldTest{
{
custTable.rows[0].key,
custTable.rows[0].value,
query_parser.Field{
Segments: []query_parser.Segment{
query_parser.Segment{
Value: "k",
Node: query_parser.Node{Off: 7},
},
},
Node: query_parser.Node{Off: 7},
},
vdl.ValueOf("001"),
},
{
custTable.rows[0].key,
custTable.rows[0].value,
query_parser.Field{
Segments: []query_parser.Segment{
query_parser.Segment{
Value: "v",
Node: query_parser.Node{Off: 7},
},
query_parser.Segment{
Value: "Address",
Node: query_parser.Node{Off: 7},
},
query_parser.Segment{
Value: "City",
Node: query_parser.Node{Off: 7},
},
},
Node: query_parser.Node{Off: 7},
},
vdl.ValueOf("Palo Alto"),
},
}
for _, test := range basic {
r := query.ResolveField(db, test.k, test.v, &test.f)
if !reflect.DeepEqual(r, test.r) {
t.Errorf("got %v(%s), want %v(%s)", r, r.Type(), test.r, test.r.Type())
}
}
}