syncbase: syncQL: switch from operating on interface{} values to *vdl.Value values.

Change-Id: Ib4373e9efc38e849c696561ce00238feac571369
diff --git a/v23/syncbase/nosql/internal/query/demo/db_objects.vdl b/v23/syncbase/nosql/internal/query/demo/db_objects.vdl
new file mode 100644
index 0000000..a6338c0
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/demo/db_objects.vdl
@@ -0,0 +1,93 @@
+// 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 main
+
+type AddressInfo struct {
+	Street string
+	City   string
+	State  string
+	Zip    string
+}
+
+type CreditAgency enum {
+	Equifax
+	Experian
+	TransUnion
+}
+
+type ExperianRating enum {
+        Good
+        Bad
+}
+
+type EquifaxCreditReport struct {
+	Rating byte
+}
+
+type ExperianCreditReport struct {
+	Rating ExperianRating
+}
+
+type TransUnionCreditReport struct {
+	Rating	int16
+}
+
+type AgencyReport union {
+	EquifaxReport    EquifaxCreditReport
+	ExperianReport   ExperianCreditReport
+	TransUnionReport TransUnionCreditReport
+}
+
+type CreditReport struct {
+	Agency	CreditAgency
+	Report	AgencyReport
+}
+
+type Customer struct {
+	Name    string
+	Id      int64
+	Active  bool
+	Address AddressInfo
+	Credit  CreditReport
+}
+
+type Invoice struct {
+	CustId     int64
+	InvoiceNum int64
+	Amount     int64
+	ShipTo     AddressInfo
+}
+
+type Numbers struct {
+	B    byte
+	Ui16 uint16
+	Ui32 uint32
+	Ui64 uint64
+	I16  int16
+	I32  int32
+	I64  int64
+	F32  float32
+	F64  float64
+	C64  complex64
+	C128 complex128
+}
+
+type FooType struct {
+	Bar BarType
+}
+
+type BarType struct {
+	Baz BazType
+}
+
+type TitleOrValueType union {
+	Title string
+	Value int64
+}
+
+type BazType struct {
+	Name         string
+	TitleOrValue TitleOrValueType
+}
diff --git a/v23/syncbase/nosql/internal/query/demo/db_objects.vdl.go b/v23/syncbase/nosql/internal/query/demo/db_objects.vdl.go
new file mode 100644
index 0000000..dd96a5c
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/demo/db_objects.vdl.go
@@ -0,0 +1,335 @@
+// 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.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: db_objects.vdl
+
+package main
+
+import (
+	// VDL system imports
+	"fmt"
+	"v.io/v23/vdl"
+)
+
+type AddressInfo struct {
+	Street string
+	City   string
+	State  string
+	Zip    string
+}
+
+func (AddressInfo) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.AddressInfo"`
+}) {
+}
+
+type CreditAgency int
+
+const (
+	CreditAgencyEquifax CreditAgency = iota
+	CreditAgencyExperian
+	CreditAgencyTransUnion
+)
+
+// CreditAgencyAll holds all labels for CreditAgency.
+var CreditAgencyAll = [...]CreditAgency{CreditAgencyEquifax, CreditAgencyExperian, CreditAgencyTransUnion}
+
+// CreditAgencyFromString creates a CreditAgency from a string label.
+func CreditAgencyFromString(label string) (x CreditAgency, err error) {
+	err = x.Set(label)
+	return
+}
+
+// Set assigns label to x.
+func (x *CreditAgency) Set(label string) error {
+	switch label {
+	case "Equifax", "equifax":
+		*x = CreditAgencyEquifax
+		return nil
+	case "Experian", "experian":
+		*x = CreditAgencyExperian
+		return nil
+	case "TransUnion", "transunion":
+		*x = CreditAgencyTransUnion
+		return nil
+	}
+	*x = -1
+	return fmt.Errorf("unknown label %q in main.CreditAgency", label)
+}
+
+// String returns the string label of x.
+func (x CreditAgency) String() string {
+	switch x {
+	case CreditAgencyEquifax:
+		return "Equifax"
+	case CreditAgencyExperian:
+		return "Experian"
+	case CreditAgencyTransUnion:
+		return "TransUnion"
+	}
+	return ""
+}
+
+func (CreditAgency) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.CreditAgency"`
+	Enum struct{ Equifax, Experian, TransUnion string }
+}) {
+}
+
+type ExperianRating int
+
+const (
+	ExperianRatingGood ExperianRating = iota
+	ExperianRatingBad
+)
+
+// ExperianRatingAll holds all labels for ExperianRating.
+var ExperianRatingAll = [...]ExperianRating{ExperianRatingGood, ExperianRatingBad}
+
+// ExperianRatingFromString creates a ExperianRating from a string label.
+func ExperianRatingFromString(label string) (x ExperianRating, err error) {
+	err = x.Set(label)
+	return
+}
+
+// Set assigns label to x.
+func (x *ExperianRating) Set(label string) error {
+	switch label {
+	case "Good", "good":
+		*x = ExperianRatingGood
+		return nil
+	case "Bad", "bad":
+		*x = ExperianRatingBad
+		return nil
+	}
+	*x = -1
+	return fmt.Errorf("unknown label %q in main.ExperianRating", label)
+}
+
+// String returns the string label of x.
+func (x ExperianRating) String() string {
+	switch x {
+	case ExperianRatingGood:
+		return "Good"
+	case ExperianRatingBad:
+		return "Bad"
+	}
+	return ""
+}
+
+func (ExperianRating) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.ExperianRating"`
+	Enum struct{ Good, Bad string }
+}) {
+}
+
+type EquifaxCreditReport struct {
+	Rating byte
+}
+
+func (EquifaxCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.EquifaxCreditReport"`
+}) {
+}
+
+type ExperianCreditReport struct {
+	Rating ExperianRating
+}
+
+func (ExperianCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.ExperianCreditReport"`
+}) {
+}
+
+type TransUnionCreditReport struct {
+	Rating int16
+}
+
+func (TransUnionCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.TransUnionCreditReport"`
+}) {
+}
+
+type (
+	// AgencyReport represents any single field of the AgencyReport union type.
+	AgencyReport interface {
+		// Index returns the field index.
+		Index() int
+		// Interface returns the field value as an interface.
+		Interface() interface{}
+		// Name returns the field name.
+		Name() string
+		// __VDLReflect describes the AgencyReport union type.
+		__VDLReflect(__AgencyReportReflect)
+	}
+	// AgencyReportEquifaxReport represents field EquifaxReport of the AgencyReport union type.
+	AgencyReportEquifaxReport struct{ Value EquifaxCreditReport }
+	// AgencyReportExperianReport represents field ExperianReport of the AgencyReport union type.
+	AgencyReportExperianReport struct{ Value ExperianCreditReport }
+	// AgencyReportTransUnionReport represents field TransUnionReport of the AgencyReport union type.
+	AgencyReportTransUnionReport struct{ Value TransUnionCreditReport }
+	// __AgencyReportReflect describes the AgencyReport union type.
+	__AgencyReportReflect struct {
+		Name  string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.AgencyReport"`
+		Type  AgencyReport
+		Union struct {
+			EquifaxReport    AgencyReportEquifaxReport
+			ExperianReport   AgencyReportExperianReport
+			TransUnionReport AgencyReportTransUnionReport
+		}
+	}
+)
+
+func (x AgencyReportEquifaxReport) Index() int                         { return 0 }
+func (x AgencyReportEquifaxReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportEquifaxReport) Name() string                       { return "EquifaxReport" }
+func (x AgencyReportEquifaxReport) __VDLReflect(__AgencyReportReflect) {}
+
+func (x AgencyReportExperianReport) Index() int                         { return 1 }
+func (x AgencyReportExperianReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportExperianReport) Name() string                       { return "ExperianReport" }
+func (x AgencyReportExperianReport) __VDLReflect(__AgencyReportReflect) {}
+
+func (x AgencyReportTransUnionReport) Index() int                         { return 2 }
+func (x AgencyReportTransUnionReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportTransUnionReport) Name() string                       { return "TransUnionReport" }
+func (x AgencyReportTransUnionReport) __VDLReflect(__AgencyReportReflect) {}
+
+type CreditReport struct {
+	Agency CreditAgency
+	Report AgencyReport
+}
+
+func (CreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.CreditReport"`
+}) {
+}
+
+type Customer struct {
+	Name    string
+	Id      int64
+	Active  bool
+	Address AddressInfo
+	Credit  CreditReport
+}
+
+func (Customer) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.Customer"`
+}) {
+}
+
+type Invoice struct {
+	CustId     int64
+	InvoiceNum int64
+	Amount     int64
+	ShipTo     AddressInfo
+}
+
+func (Invoice) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.Invoice"`
+}) {
+}
+
+type Numbers struct {
+	B    byte
+	Ui16 uint16
+	Ui32 uint32
+	Ui64 uint64
+	I16  int16
+	I32  int32
+	I64  int64
+	F32  float32
+	F64  float64
+	C64  complex64
+	C128 complex128
+}
+
+func (Numbers) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.Numbers"`
+}) {
+}
+
+type FooType struct {
+	Bar BarType
+}
+
+func (FooType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.FooType"`
+}) {
+}
+
+type BarType struct {
+	Baz BazType
+}
+
+func (BarType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.BarType"`
+}) {
+}
+
+type (
+	// TitleOrValueType represents any single field of the TitleOrValueType union type.
+	TitleOrValueType interface {
+		// Index returns the field index.
+		Index() int
+		// Interface returns the field value as an interface.
+		Interface() interface{}
+		// Name returns the field name.
+		Name() string
+		// __VDLReflect describes the TitleOrValueType union type.
+		__VDLReflect(__TitleOrValueTypeReflect)
+	}
+	// TitleOrValueTypeTitle represents field Title of the TitleOrValueType union type.
+	TitleOrValueTypeTitle struct{ Value string }
+	// TitleOrValueTypeValue represents field Value of the TitleOrValueType union type.
+	TitleOrValueTypeValue struct{ Value int64 }
+	// __TitleOrValueTypeReflect describes the TitleOrValueType union type.
+	__TitleOrValueTypeReflect struct {
+		Name  string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.TitleOrValueType"`
+		Type  TitleOrValueType
+		Union struct {
+			Title TitleOrValueTypeTitle
+			Value TitleOrValueTypeValue
+		}
+	}
+)
+
+func (x TitleOrValueTypeTitle) Index() int                             { return 0 }
+func (x TitleOrValueTypeTitle) Interface() interface{}                 { return x.Value }
+func (x TitleOrValueTypeTitle) Name() string                           { return "Title" }
+func (x TitleOrValueTypeTitle) __VDLReflect(__TitleOrValueTypeReflect) {}
+
+func (x TitleOrValueTypeValue) Index() int                             { return 1 }
+func (x TitleOrValueTypeValue) Interface() interface{}                 { return x.Value }
+func (x TitleOrValueTypeValue) Name() string                           { return "Value" }
+func (x TitleOrValueTypeValue) __VDLReflect(__TitleOrValueTypeReflect) {}
+
+type BazType struct {
+	Name         string
+	TitleOrValue TitleOrValueType
+}
+
+func (BazType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/demo.BazType"`
+}) {
+}
+
+func init() {
+	vdl.Register((*AddressInfo)(nil))
+	vdl.Register((*CreditAgency)(nil))
+	vdl.Register((*ExperianRating)(nil))
+	vdl.Register((*EquifaxCreditReport)(nil))
+	vdl.Register((*ExperianCreditReport)(nil))
+	vdl.Register((*TransUnionCreditReport)(nil))
+	vdl.Register((*AgencyReport)(nil))
+	vdl.Register((*CreditReport)(nil))
+	vdl.Register((*Customer)(nil))
+	vdl.Register((*Invoice)(nil))
+	vdl.Register((*Numbers)(nil))
+	vdl.Register((*FooType)(nil))
+	vdl.Register((*BarType)(nil))
+	vdl.Register((*TitleOrValueType)(nil))
+	vdl.Register((*BazType)(nil))
+}
diff --git a/v23/syncbase/nosql/internal/query/demo/demo.go b/v23/syncbase/nosql/internal/query/demo/demo.go
index 963a00d..81274e0 100644
--- a/v23/syncbase/nosql/internal/query/demo/demo.go
+++ b/v23/syncbase/nosql/internal/query/demo/demo.go
@@ -8,18 +8,23 @@
 	"bufio"
 	"errors"
 	"fmt"
-	"math/big"
 	"os"
 	"strings"
 
 	"v.io/syncbase/v23/syncbase/nosql/internal/query"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_db"
+	"v.io/v23/vdl"
 )
 
 type demoDB struct {
 	tables []table
 }
 
+type kv struct {
+	key   string
+	value *vdl.Value
+}
+
 type table struct {
 	name string
 	rows []kv
@@ -58,7 +63,7 @@
 	return false
 }
 
-func (kvs *keyValueStreamImpl) KeyValue() (string, interface{}) {
+func (kvs *keyValueStreamImpl) KeyValue() (string, *vdl.Value) {
 	return kvs.table.rows[kvs.cursor].key, kvs.table.rows[kvs.cursor].value
 }
 
@@ -87,47 +92,6 @@
 
 }
 
-type AddressInfo struct {
-	Street string
-	City   string
-	State  string
-	Zip    string
-}
-
-type Customer struct {
-	Name    string
-	ID      int64
-	Active  bool
-	Rating  rune
-	Address AddressInfo
-}
-
-type Invoice struct {
-	CustID     int64
-	InvoiceNum int64
-	Amount     int64
-	ShipTo     AddressInfo
-}
-
-type Numbers struct {
-	B    byte
-	UI16 uint16
-	UI32 uint32
-	UI64 uint64
-	I16  int16
-	I32  int32
-	I64  int64
-	BI   big.Int
-	F32  float32
-	F64  float64
-	BR   big.Rat
-}
-
-type kv struct {
-	key   string
-	value interface{}
-}
-
 func createDB() query_db.Database {
 	var db demoDB
 	var custTable table
@@ -135,39 +99,39 @@
 	custTable.rows = []kv{
 		kv{
 			"001",
-			Customer{"John Smith", 1, true, 'A', AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}},
+			vdl.ValueOf(Customer{"John Smith", 1, true, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}, CreditReport{Agency: CreditAgencyEquifax, Report: AgencyReportEquifaxReport{EquifaxCreditReport{'A'}}}}),
 		},
 		kv{
 			"001001",
-			Invoice{1, 1000, 42, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}},
+			vdl.ValueOf(Invoice{1, 1000, 42, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}}),
 		},
 		kv{
 			"001002",
-			Invoice{1, 1003, 7, AddressInfo{"2 Main St.", "Palo Alto", "CA", "94303"}},
+			vdl.ValueOf(Invoice{1, 1003, 7, AddressInfo{"2 Main St.", "Palo Alto", "CA", "94303"}}),
 		},
 		kv{
 			"001003",
-			Invoice{1, 1005, 88, AddressInfo{"3 Main St.", "Palo Alto", "CA", "94303"}},
+			vdl.ValueOf(Invoice{1, 1005, 88, AddressInfo{"3 Main St.", "Palo Alto", "CA", "94303"}}),
 		},
 		kv{
 			"002",
-			Customer{"Bat Masterson", 2, true, 'B', AddressInfo{"777 Any St.", "Collins", "IA", "50055"}},
+			vdl.ValueOf(Customer{"Bat Masterson", 2, true, AddressInfo{"777 Any St.", "Collins", "IA", "50055"}, CreditReport{Agency: CreditAgencyTransUnion, Report: AgencyReportTransUnionReport{TransUnionCreditReport{80}}}}),
 		},
 		kv{
 			"002001",
-			Invoice{2, 1001, 166, AddressInfo{"777 Any St.", "collins", "IA", "50055"}},
+			vdl.ValueOf(Invoice{2, 1001, 166, AddressInfo{"777 Any St.", "collins", "IA", "50055"}}),
 		},
 		kv{
 			"002002",
-			Invoice{2, 1002, 243, AddressInfo{"888 Any St.", "collins", "IA", "50055"}},
+			vdl.ValueOf(Invoice{2, 1002, 243, AddressInfo{"888 Any St.", "collins", "IA", "50055"}}),
 		},
 		kv{
 			"002003",
-			Invoice{2, 1004, 787, AddressInfo{"999 Any St.", "collins", "IA", "50055"}},
+			vdl.ValueOf(Invoice{2, 1004, 787, AddressInfo{"999 Any St.", "collins", "IA", "50055"}}),
 		},
 		kv{
 			"002004",
-			Invoice{2, 1006, 88, AddressInfo{"101010 Any St.", "collins", "IA", "50055"}},
+			vdl.ValueOf(Invoice{2, 1006, 88, AddressInfo{"101010 Any St.", "collins", "IA", "50055"}}),
 		},
 	}
 	db.tables = append(db.tables, custTable)
@@ -177,14 +141,19 @@
 	numTable.rows = []kv{
 		kv{
 			"001",
-			Numbers{byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), int64(128), *big.NewInt(1234567890), float32(3.14159), float64(2.71828182846), *big.NewRat(123, 1)},
+			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",
-			Numbers{byte(9), uint16(99), uint32(999), uint64(9999999), int16(9), int32(99), int64(88), *big.NewInt(9999), float32(1.41421356237), float64(1.73205080757), *big.NewRat(999999, 1)},
+			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)
+
 	return db
 }
 
@@ -194,17 +163,7 @@
 		for _, t := range db.tables {
 			fmt.Printf("table: %s\n", t.name)
 			for _, row := range t.rows {
-				fmt.Printf("key: %s, value: ", row.key)
-				switch v := row.value.(type) {
-				case Customer:
-					fmt.Printf("type:Customer Name:%v,ID:%v,Active:%v,Rating:%v,Address{%v}\n", v.Name, v.ID, v.Active, v.Rating, dumpAddress(&v.Address))
-				case Invoice:
-					fmt.Printf("type:Invoice CustID:%v,InvoiceNum:%v,Amount:%v,ShipTo:{%v}\n", v.CustID, v.InvoiceNum, v.Amount, dumpAddress(&v.ShipTo))
-				case Numbers:
-					fmt.Printf("type:Numbers B:%v,UI16:%v,UI32:%v,UI64:%v,I16:%v,I32:%v,I64:%v,BI:%v,F32:%v,F64:%v,BR:%v\n", v.B, v.UI16, v.UI32, v.UI64, v.I16, v.I32, v.I64, v.BI, v.F32, v.F64, v.BR)
-				default:
-					fmt.Printf("%v\n", row.value)
-				}
+				fmt.Printf("key: %s, value: %v", row.key, row.value)
 			}
 		}
 	}
diff --git a/v23/syncbase/nosql/internal/query/eval.go b/v23/syncbase/nosql/internal/query/eval.go
index e923c60..ce9d7f0 100644
--- a/v23/syncbase/nosql/internal/query/eval.go
+++ b/v23/syncbase/nosql/internal/query/eval.go
@@ -13,9 +13,10 @@
 
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_checker"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/v23/vdl"
 )
 
-func Eval(k string, v interface{}, e *query_parser.Expression) bool {
+func Eval(k string, v *vdl.Value, e *query_parser.Expression) bool {
 	if query_checker.IsLogicalOperator(e.Operator) {
 		return evalLogicalOperators(k, v, e)
 	} else {
@@ -23,7 +24,7 @@
 	}
 }
 
-func evalLogicalOperators(k string, v interface{}, e *query_parser.Expression) bool {
+func evalLogicalOperators(k string, v *vdl.Value, e *query_parser.Expression) bool {
 	switch e.Operator.Type {
 	case query_parser.And:
 		return Eval(k, v, e.Operand1.Expr) && Eval(k, v, e.Operand2.Expr)
@@ -35,7 +36,7 @@
 	}
 }
 
-func evalComparisonOperators(k string, v interface{}, e *query_parser.Expression) bool {
+func evalComparisonOperators(k string, v *vdl.Value, e *query_parser.Expression) bool {
 	lhsValue := resolveOperand(k, v, e.Operand1)
 	// Check for an is nil epression (i.e., v[.<field>...] is nil).
 	// These expressions evaluate to true if the field cannot be resolved.
@@ -68,6 +69,8 @@
 		return compareBigRats(lhsValue, rhsValue, e.Operator)
 	case query_parser.TypBool:
 		return compareBools(lhsValue, rhsValue, e.Operator)
+	case query_parser.TypComplex:
+		return compareComplex(lhsValue, rhsValue, e.Operator)
 	case query_parser.TypFloat:
 		return compareFloats(lhsValue, rhsValue, e.Operator)
 	case query_parser.TypInt:
@@ -83,6 +86,7 @@
 }
 
 func coerceValues(lhsValue, rhsValue *query_parser.Operand) (*query_parser.Operand, *query_parser.Operand, error) {
+	// TODO(jkline): explore using vdl for coercions ( https://v.io/designdocs/vdl-spec.html#conversions ).
 	var err error
 	// If either operand is a string, convert the other to a string.
 	if lhsValue.Type == query_parser.TypStr || rhsValue.Type == query_parser.TypStr {
@@ -92,6 +96,23 @@
 		if rhsValue, err = convertValueToString(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
+	}
+	// If either operand is Complex, promote numerics to Complex.
+	// Comparing complex to string is handled above.
+	if lhsValue.Type == query_parser.TypComplex || rhsValue.Type == query_parser.TypComplex {
+		// If both complex, just return them.
+		if lhsValue.Type == query_parser.TypComplex && rhsValue.Type == query_parser.TypComplex {
+			return lhsValue, rhsValue, nil
+		}
+		var err error
+		if lhsValue, err = convertValueToComplex(lhsValue); err != nil {
+			return nil, nil, err
+		}
+		if rhsValue, err = convertValueToComplex(rhsValue); err != nil {
+			return nil, nil, err
+		}
+		return lhsValue, rhsValue, nil
 	}
 	// If either operand is a big rat, convert both to a big rat.
 	// Also, if one operand is a float and the other is a big int,
@@ -103,6 +124,7 @@
 		if rhsValue, err = convertValueToBigRat(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
 	}
 	// If either operand is a float, convert the other to a float.
 	if lhsValue.Type == query_parser.TypFloat || rhsValue.Type == query_parser.TypFloat {
@@ -112,6 +134,7 @@
 		if rhsValue, err = convertValueToFloat(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
 	}
 	// If either operand is a big int, convert both to a big int.
 	// Also, if one operand is a uint64 and the other is an int64, convert both to big ints.
@@ -122,6 +145,7 @@
 		if rhsValue, err = convertValueToBigInt(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
 	}
 	// If either operand is an int64, convert the other to int64.
 	if lhsValue.Type == query_parser.TypInt || rhsValue.Type == query_parser.TypInt {
@@ -131,6 +155,7 @@
 		if rhsValue, err = convertValueToInt(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
 	}
 	// If either operand is an uint64, convert the other to uint64.
 	if lhsValue.Type == query_parser.TypUint || rhsValue.Type == query_parser.TypUint {
@@ -140,6 +165,7 @@
 		if rhsValue, err = convertValueToUint(rhsValue); err != nil {
 			return nil, nil, err
 		}
+		return lhsValue, rhsValue, nil
 	}
 	// Must be the same at this point.
 	if lhsValue.Type != rhsValue.Type {
@@ -160,6 +186,8 @@
 		c.Str = o.BigRat.String()
 	case query_parser.TypBool:
 		c.Str = strconv.FormatBool(o.Bool)
+	case query_parser.TypComplex:
+		c.Str = fmt.Sprintf("%g", o.Complex)
 	case query_parser.TypFloat:
 		c.Str = strconv.FormatFloat(o.Float, 'f', -1, 64)
 	case query_parser.TypInt:
@@ -181,6 +209,24 @@
 	return &c, nil
 }
 
+func convertValueToComplex(o *query_parser.Operand) (*query_parser.Operand, error) {
+	var c query_parser.Operand
+	c.Type = query_parser.TypComplex
+	switch o.Type {
+	case query_parser.TypComplex:
+		return o, nil
+	case query_parser.TypFloat:
+		c.Complex = complex(o.Float, 0.0i)
+	case query_parser.TypInt:
+		c.Complex = complex(float64(o.Int), 0.0i)
+	case query_parser.TypUint:
+		c.Complex = complex(float64(o.Uint), 0.0i)
+	default:
+		return nil, errors.New("Cannot convert operand to Complex for comparison.")
+	}
+	return &c, nil
+}
+
 func convertValueToBigRat(o *query_parser.Operand) (*query_parser.Operand, error) {
 	// operand cannot be string literal.
 	var c query_parser.Operand
@@ -346,6 +392,18 @@
 	}
 }
 
+func compareComplex(lhsValue, rhsValue *query_parser.Operand, oper *query_parser.BinaryOperator) bool {
+	switch oper.Type {
+	case query_parser.Equal:
+		return lhsValue.Complex == rhsValue.Complex
+	case query_parser.NotEqual:
+		return lhsValue.Complex != rhsValue.Complex
+	default:
+		// Complex values are not ordered.  All other operands return false.
+		return false
+	}
+}
+
 func compareFloats(lhsValue, rhsValue *query_parser.Operand, oper *query_parser.BinaryOperator) bool {
 	switch oper.Type {
 	case query_parser.Equal:
@@ -447,12 +505,12 @@
 	}
 }
 
-func resolveOperand(k string, v interface{}, o *query_parser.Operand) *query_parser.Operand {
+func resolveOperand(k string, v *vdl.Value, o *query_parser.Operand) *query_parser.Operand {
 	if o.Type != query_parser.TypField {
 		return o
 	}
 	value, hasAltStr, altStr := ResolveField(k, v, o.Column)
-	if value == nil {
+	if value.IsNil() {
 		return nil
 	}
 
@@ -460,61 +518,34 @@
 	var newOp query_parser.Operand
 	newOp.Off = o.Off
 
-	switch value := value.(type) {
-	case bool:
+	switch value.Kind() {
+	case vdl.Bool:
 		newOp.Type = query_parser.TypBool
-		newOp.Bool = value
-	case int:
+		newOp.Bool = value.Bool()
+	case vdl.Byte:
 		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case int8:
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case int16:
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case int32: // rune
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case int64:
-		newOp.Type = query_parser.TypInt
-		newOp.Int = value
-	case uint:
-		newOp.Type = query_parser.TypBigInt
-		var b big.Int
-		b.SetUint64(uint64(value))
-		newOp.BigInt = &b
-	case uint8: // byte
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case uint16:
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case uint32:
-		newOp.Type = query_parser.TypInt
-		newOp.Int = int64(value)
-	case uint64:
-		newOp.Type = query_parser.TypBigInt
-		var b big.Int
-		b.SetUint64(value)
-		newOp.BigInt = &b
-	case float32:
-		newOp.Type = query_parser.TypFloat
-		newOp.Float = float64(value)
-	case float64:
-		newOp.Type = query_parser.TypFloat
-		newOp.Float = value
-	case string:
+		newOp.Int = int64(value.Byte())
+	case vdl.Enum:
 		newOp.Type = query_parser.TypStr
-		newOp.Str = value
+		newOp.Str = value.EnumLabel()
+		newOp.HasAltStr = false
+	case vdl.Int16, vdl.Int32, vdl.Int64:
+		newOp.Type = query_parser.TypInt
+		newOp.Int = value.Int()
+	case vdl.Uint16, vdl.Uint32, vdl.Uint64:
+		newOp.Type = query_parser.TypInt
+		newOp.Int = int64(value.Uint())
+	case vdl.Float32, vdl.Float64:
+		newOp.Type = query_parser.TypFloat
+		newOp.Float = value.Float()
+	case vdl.String:
+		newOp.Type = query_parser.TypStr
+		newOp.Str = value.RawString()
 		newOp.HasAltStr = hasAltStr
 		newOp.AltStr = altStr
-	case *big.Int:
-		newOp.Type = query_parser.TypBigInt
-		newOp.BigInt = value
-	case *big.Rat:
-		newOp.Type = query_parser.TypBigRat
-		newOp.BigRat = value
+	case vdl.Complex64, vdl.Complex128:
+		newOp.Type = query_parser.TypComplex
+		newOp.Complex = value.Complex()
 	default: // OpObject for structs, arrays, maps, ...
 		newOp.Type = query_parser.TypObject
 		newOp.Object = value
@@ -526,37 +557,38 @@
 // to a string being returned, and alternate string is returned.  In this case,
 // <string-value>, true, <alt-string> is returned.  In all other cases,
 // <value>,false,"" is returned.
-func ResolveField(k string, v interface{}, f *query_parser.Field) (interface{}, bool, string) {
+func ResolveField(k string, v *vdl.Value, f *query_parser.Field) (*vdl.Value, bool, string) {
 	if query_checker.IsKeyField(f) {
-		return k, false, ""
+		return vdl.StringValue(k), false, ""
 	}
+	t := v.Type()
 	if query_checker.IsTypeField(f) {
-		if v == nil {
-			return nil, false, ""
-		} else {
-			// Types evaluate to two strings, Str and AltStr.
-			// This is because types match on full path or just the name.
-			name := reflect.ValueOf(v).Type().Name()
-			return reflect.ValueOf(v).Type().PkgPath() + "." + name, true, name
-		}
+		// Types evaluate to two strings, Str and AltStr.
+		// This is because types match on full path or just the name.
+		pkg, name := vdl.SplitIdent(t.Name())
+		return vdl.StringValue(pkg + "." + name), true, name
 	}
+
 	object := v
 	segments := f.Segments
-	// The first segment will always be v itself, skip it.
+	// The first segment will always be v (itself), skip it.
 	for i := 1; i < len(segments); i++ {
 		// object must be a struct in order to look for the next segment.
-		if reflect.ValueOf(object).Kind() != reflect.Struct {
-			return nil, false, "" // field does not exist
+		if object.Kind() == vdl.Struct {
+			if object = object.StructFieldByName(segments[i].Value); object == nil {
+				return vdl.ValueOf(nil), false, "" // field does not exist
+			}
+		} else if object.Kind() == vdl.Union {
+			unionType := object.Type()
+			idx, tempValue := object.UnionField()
+			if segments[i].Value == unionType.Field(idx).Name {
+				object = tempValue
+			} else {
+				return vdl.ValueOf(nil), false, "" // union field does not exist or is not set
+			}
+		} else {
+			return vdl.ValueOf(nil), false, "" // can only traverse into structs and unions
 		}
-		// Look up the segment in object.
-		_, ok := reflect.ValueOf(object).Type().FieldByName(segments[i].Value)
-		if !ok {
-			return nil, false, "" // field does not exist
-		}
-		if !reflect.ValueOf(object).FieldByName(segments[i].Value).CanInterface() {
-			return nil, false, ""
-		}
-		object = reflect.ValueOf(object).FieldByName(segments[i].Value).Interface()
 	}
 	return object, false, ""
 }
diff --git a/v23/syncbase/nosql/internal/query/query.go b/v23/syncbase/nosql/internal/query/query.go
index a6c1c99..5c76cd2 100644
--- a/v23/syncbase/nosql/internal/query/query.go
+++ b/v23/syncbase/nosql/internal/query/query.go
@@ -11,6 +11,7 @@
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_checker"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_db"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/v23/vdl"
 )
 
 type QueryError struct {
@@ -20,7 +21,7 @@
 
 type ResultStream interface {
 	Advance() bool
-	Result() []interface{}
+	Result() []*vdl.Value
 	Err() *QueryError
 	Cancel()
 }
@@ -59,8 +60,8 @@
 
 // Given a key, a value and a SelectClause, return the projection.
 // This function is only called if Eval returned true on the WhereClause expression.
-func ComposeProjection(k string, v interface{}, s *query_parser.SelectClause) []interface{} {
-	var projection []interface{}
+func ComposeProjection(k string, v *vdl.Value, s *query_parser.SelectClause) []*vdl.Value {
+	var projection []*vdl.Value
 	for _, f := range s.Columns {
 		// If field not found, nil is returned (as per specification).
 		c, _, _ := ResolveField(k, v, &f)
@@ -85,12 +86,13 @@
 }
 
 // For testing purposes, given a SelectStatement, k and v;
-// return nil if row not selected, else return the projection (type []interface{}).
+// return nil if row not selected, else return the projection (type []*vdl.Value).
 // Note: limit and offset clauses are ignored for this function as they make no sense
 // for a single row.
-func ExecSelectSingleRow(k string, v interface{}, s *query_parser.SelectStatement) interface{} {
+func ExecSelectSingleRow(k string, v *vdl.Value, s *query_parser.SelectStatement) []*vdl.Value {
 	if !Eval(k, v, s.Where.Expr) {
-		return nil
+		rs := []*vdl.Value{}
+		return rs
 	}
 	return ComposeProjection(k, v, s.Select)
 }
@@ -101,7 +103,7 @@
 	skippedCount    int64 // skipped so far (needed for offset clause)
 	keyValueStream  query_db.KeyValueStream
 	k               string
-	v               interface{}
+	v               *vdl.Value
 	err             *QueryError
 }
 
@@ -142,7 +144,7 @@
 	return false
 }
 
-func (rs *resultStreamImpl) Result() []interface{} {
+func (rs *resultStreamImpl) Result() []*vdl.Value {
 	return ComposeProjection(rs.k, rs.v, rs.selectStatement.Select)
 }
 
diff --git a/v23/syncbase/nosql/internal/query/query_db/query_db.go b/v23/syncbase/nosql/internal/query/query_db/query_db.go
index 10e5ec0..8724fd2 100644
--- a/v23/syncbase/nosql/internal/query/query_db/query_db.go
+++ b/v23/syncbase/nosql/internal/query/query_db/query_db.go
@@ -4,6 +4,10 @@
 
 package query_db
 
+import (
+	"v.io/v23/vdl"
+)
+
 type Database interface {
 	GetTable(name string) (Table, error)
 }
@@ -29,7 +33,7 @@
 	// KeyValue returns the element that was staged by Advance.
 	// KeyValue may panic if Advance returned false or was not
 	// called at all.  KeyValue does not block.
-	KeyValue() (string, interface{})
+	KeyValue() (string, *vdl.Value)
 
 	// Err returns a non-nil error iff the stream encountered
 	// any errors.  Err does not block.
diff --git a/v23/syncbase/nosql/internal/query/query_parser/query_parser.go b/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
index 502fe43..2e45daf 100644
--- a/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
+++ b/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
@@ -14,6 +14,7 @@
 	"unicode/utf8"
 
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_db"
+	"v.io/v23/vdl"
 )
 
 type TokenType int
@@ -101,6 +102,7 @@
 	TypBigInt OperandType = 1 + iota // Only as a result of Resolve/Coerce Operand
 	TypBigRat                        // Only as a result of Resolve/Coerce Operand
 	TypBool
+	TypComplex
 	TypExpr
 	TypField
 	TypFloat
@@ -117,6 +119,7 @@
 	BigInt    *big.Int
 	BigRat    *big.Rat
 	Bool      bool
+	Complex   complex128
 	Column    *Field
 	Float     float64
 	Function  *Function
@@ -129,7 +132,7 @@
 	Uint      uint64
 	CompRegex *regexp.Regexp
 	Expr      *Expression
-	Object    interface{}
+	Object    *vdl.Value
 	Node
 }
 
@@ -903,6 +906,9 @@
 	case TypBigRat:
 		val += "(BigRat)"
 		val += o.BigRat.String()
+	case TypComplex:
+		val += "(Complex)"
+		val += fmt.Sprintf("%g", o.Complex)
 	case TypField:
 		val += "(field)"
 		val += o.Column.String()
diff --git a/v23/syncbase/nosql/internal/query/query_test.go b/v23/syncbase/nosql/internal/query/query_test.go
deleted file mode 100644
index a703e17..0000000
--- a/v23/syncbase/nosql/internal/query/query_test.go
+++ /dev/null
@@ -1,1179 +0,0 @@
-// 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 query_test
-
-import (
-	"errors"
-	"fmt"
-	"math/big"
-	"reflect"
-	"strings"
-	"testing"
-
-	"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_db"
-	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
-)
-
-type mockDB struct {
-}
-
-type customerTable struct {
-}
-
-type keyValueStreamImpl struct {
-	cursor       int
-	prefixes     []string
-	prefixCursor int
-	customerRows []customerKV
-}
-
-func (kvs *keyValueStreamImpl) Advance() bool {
-	for true {
-		kvs.cursor++ // initialized to -1
-		if kvs.cursor >= len(kvs.customerRows) {
-			return false
-		}
-		for kvs.prefixCursor < len(kvs.prefixes) {
-			// does it match any prefix
-			if kvs.prefixes[kvs.prefixCursor] == "" || strings.HasPrefix(kvs.customerRows[kvs.cursor].key, kvs.prefixes[kvs.prefixCursor]) {
-				return true
-			}
-			// Keys and prefixes are both sorted low to high, so we can increment
-			// prefixCursor if the prefix is < the key.
-			if kvs.prefixes[kvs.prefixCursor] < kvs.customerRows[kvs.cursor].key {
-				kvs.prefixCursor++
-				if kvs.prefixCursor >= len(kvs.prefixes) {
-					return false
-				}
-			} else {
-				break
-			}
-		}
-	}
-	return false
-}
-
-func (kvs *keyValueStreamImpl) KeyValue() (string, interface{}) {
-	return kvs.customerRows[kvs.cursor].key, kvs.customerRows[kvs.cursor].value
-}
-
-func (kvs *keyValueStreamImpl) Err() error {
-	return nil
-}
-
-func (kvs *keyValueStreamImpl) Cancel() {
-}
-
-func (customerTable customerTable) Scan(prefixes []string) (query_db.KeyValueStream, error) {
-	var keyValueStreamImpl keyValueStreamImpl
-	keyValueStreamImpl.cursor = -1
-	keyValueStreamImpl.prefixes = prefixes
-	keyValueStreamImpl.customerRows = customerRows
-	return &keyValueStreamImpl, nil
-}
-
-func (db mockDB) GetTable(table string) (query_db.Table, error) {
-	if table == "Customer" {
-		var customerTable customerTable
-		return customerTable, nil
-	}
-	return nil, errors.New(fmt.Sprintf("No such table: %s.", table))
-
-}
-
-type Nest2 struct {
-	Foo string
-	Bar bool
-	Baz int64
-}
-
-type Nest1 struct {
-	FooBarBaz Nest2
-}
-
-type Customer struct {
-	Name              string
-	ID                int64
-	Active            bool
-	Rating            rune
-	Street            string
-	City              string
-	State             string
-	Zip               string
-	GratuituousBigInt *big.Int
-	GratuituousBigRat *big.Rat
-	GratuituousByte   byte
-	GratuituousUint16 uint16
-	GratuituousUint32 uint32
-	GratuituousUint64 uint64
-	GratuituousInt16  int16
-	GratuituousInt32  int32
-	Foo               Nest1
-}
-
-type Invoice struct {
-	CustID     int64
-	InvoiceNum int64
-	Amount     int64
-}
-
-var db mockDB
-var sampleRow Customer
-var sampleRow123 Customer
-
-type customerKV struct {
-	key   string
-	value interface{}
-}
-
-var customerRows []customerKV
-
-func init() {
-	sampleRow = Customer{"John Smith", 123456, true, 'A', "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(1234567890), big.NewRat(123, 1), byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), Nest1{Nest2{"foo", true, 42}}}
-	sampleRow123 = Customer{"John Smith", 123, true, 123, "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(123), big.NewRat(123, 1), byte(123), uint16(123), uint32(123), uint64(123), int16(123), int32(123), Nest1{Nest2{"foo", true, 123}}}
-	sampleRow = Customer{"John Smith", 123456, true, 'A', "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(1234567890), big.NewRat(123, 1), byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), Nest1{Nest2{"foo", true, 42}}}
-
-	customerRows = []customerKV{
-		customerKV{
-			"001",
-			Customer{"John Smith", 1, true, 'A', "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(1234567890), big.NewRat(123, 1), byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), Nest1{Nest2{"foo", true, 42}}},
-		},
-		customerKV{
-			"001001",
-			Invoice{1, 1000, 42},
-		},
-		customerKV{
-			"001002",
-			Invoice{1, 1003, 7},
-		},
-		customerKV{
-			"001003",
-			Invoice{1, 1005, 88},
-		},
-		customerKV{
-			"002",
-			Customer{"Bat Masterson", 2, true, 'B', "777 Any St.", "collins", "IA", "50055", big.NewInt(9999), big.NewRat(999999, 1), byte(9), uint16(99), uint32(999), uint64(9999999), int16(9), int32(99), Nest1{Nest2{"bar", false, 84}}},
-		},
-		customerKV{
-			"002001",
-			Invoice{2, 1001, 166},
-		},
-		customerKV{
-			"002002",
-			Invoice{2, 1002, 243},
-		},
-		customerKV{
-			"002003",
-			Invoice{2, 1004, 787},
-		},
-		customerKV{
-			"002004",
-			Invoice{2, 1006, 88},
-		},
-	}
-}
-
-type keyPrefixesTest struct {
-	query       string
-	keyPrefixes []string
-	err         *query.QueryError
-}
-
-type evalWhereUsingOnlyKeyTest struct {
-	query  string
-	key    string
-	result query.EvalWithKeyResult
-}
-
-type evalTest struct {
-	query  string
-	k      string
-	v      interface{}
-	result bool
-}
-
-type projectionTest struct {
-	query  string
-	k      string
-	v      interface{}
-	result []interface{}
-}
-
-type execSelectTest struct {
-	query string
-	r     []interface{}
-}
-
-type execSelectSingleRowTest struct {
-	query  string
-	k      string
-	v      interface{}
-	result interface{}
-}
-
-type execSelectErrorTest struct {
-	query string
-	err   *query.QueryError
-}
-
-func TestQueryExec(t *testing.T) {
-	basic := []execSelectTest{
-		{
-			// Select values for all customer records.
-			"select v from Customer where t = \"Customer\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-				[]interface{}{customerRows[4].value},
-			},
-		},
-		{
-			// 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",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-				[]interface{}{customerRows[4].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",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-				[]interface{}{customerRows[1].value},
-				[]interface{}{customerRows[2].value},
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[4].value},
-				[]interface{}{customerRows[5].value},
-				[]interface{}{customerRows[6].value},
-				[]interface{}{customerRows[7].value},
-				[]interface{}{customerRows[8].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",
-			[]interface{}{},
-		},
-		{
-			// Select values where v.InvoiceNum is not nil
-			// This will return just invoices.
-			"select v from Customer where v.InvoiceNum is not nil",
-			[]interface{}{
-				[]interface{}{customerRows[1].value},
-				[]interface{}{customerRows[2].value},
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[5].value},
-				[]interface{}{customerRows[6].value},
-				[]interface{}{customerRows[7].value},
-				[]interface{}{customerRows[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",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-				[]interface{}{customerRows[1].value},
-				[]interface{}{customerRows[2].value},
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[4].value},
-				[]interface{}{customerRows[5].value},
-				[]interface{}{customerRows[6].value},
-				[]interface{}{customerRows[7].value},
-				[]interface{}{customerRows[8].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",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-				[]interface{}{customerRows[4].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",
-			[]interface{}{},
-		},
-		{
-			// Select keys & values for all customer records.
-			"select k, v from Customer where t = \"Customer\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-			},
-		},
-		{
-			// Select keys & names for all customer records.
-			"select k, v.Name from Customer where t = \"Customer\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, "John Smith"},
-				[]interface{}{customerRows[4].key, "Bat Masterson"},
-			},
-		},
-		{
-			// Select both customer and invoice records.
-			// Customer records have ID.
-			// Invoice records have CustID.
-			"select v.ID, v.CustID from Customer",
-			[]interface{}{
-				[]interface{}{int64(1), nil},
-				[]interface{}{nil, int64(1)},
-				[]interface{}{nil, int64(1)},
-				[]interface{}{nil, int64(1)},
-				[]interface{}{int64(2), nil},
-				[]interface{}{nil, int64(2)},
-				[]interface{}{nil, int64(2)},
-				[]interface{}{nil, int64(2)},
-				[]interface{}{nil, int64(2)},
-			},
-		},
-		{
-			// Select keys & values fo all invoice records.
-			"select k, v from Customer where t = \"Invoice\"",
-			[]interface{}{
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[8].value},
-			},
-		},
-		{
-			// Select key, cust id, invoice number and amount for $88 invoices.
-			"select k, v.CustID, v.InvoiceNum, v.Amount from Customer where t = \"Invoice\" and v.Amount = 88",
-			[]interface{}{
-				[]interface{}{customerRows[3].key, int64(1), int64(1005), int64(88)},
-				[]interface{}{customerRows[8].key, int64(2), int64(1006), int64(88)},
-			},
-		},
-		{
-			// Select keys & values for all records with a key prefix of "001".
-			"select k, v from Customer where k like \"001%\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-			},
-		},
-		{
-			// Select keys & values for all records with a key prefix of "001".
-			"select k, v from Customer where k like \"002%\"",
-			[]interface{}{
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[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 \"001%\" or k like \"002%\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[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%\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[8].value},
-			},
-		},
-		{
-			// Let's play with whitespace and mixed case.
-			"   sElEcT  k,  v from \n  Customer WhErE k lIkE \"002%\" oR k LiKe \"001%\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[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 \"%\"",
-			[]interface{}{
-				[]interface{}{customerRows[0].key, customerRows[0].value},
-				[]interface{}{customerRows[1].key, customerRows[1].value},
-				[]interface{}{customerRows[2].key, customerRows[2].value},
-				[]interface{}{customerRows[3].key, customerRows[3].value},
-				[]interface{}{customerRows[4].key, customerRows[4].value},
-				[]interface{}{customerRows[5].key, customerRows[5].value},
-				[]interface{}{customerRows[6].key, customerRows[6].value},
-				[]interface{}{customerRows[7].key, customerRows[7].value},
-				[]interface{}{customerRows[8].key, customerRows[8].value},
-			},
-		},
-		{
-			// Select id, name for customers whose last name is Masterson.
-			"select v.ID, v.Name from Customer where t = \"Customer\" and v.Name like \"%Masterson\"",
-			[]interface{}{
-				[]interface{}{int64(2), "Bat Masterson"},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\"",
-			[]interface{}{
-				[]interface{}{customerRows[1].value},
-				[]interface{}{customerRows[2].value},
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[4].value},
-				[]interface{}{customerRows[5].value},
-				[]interface{}{customerRows[6].value},
-				[]interface{}{customerRows[7].value},
-				[]interface{}{customerRows[8].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 and v.InvoiceNum is not nil.
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 and v.InvoiceNum is not nil",
-			[]interface{}{},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 and v.InvoiceNum is nil.
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 and v.InvoiceNum is nil",
-			[]interface{}{
-				[]interface{}{customerRows[4].value},
-			},
-		},
-		{
-			// Select customer name for customer ID (i.e., key) "001".
-			"select v.Name from Customer where t = \"Customer\" and k = \"001\"",
-			[]interface{}{
-				[]interface{}{"John Smith"},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Bar is true.
-			"select v from Customer where v.Foo.FooBarBaz.Bar = true",
-			[]interface{}{
-				[]interface{}{customerRows[0].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			// Limit 3
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\" limit 3",
-			[]interface{}{
-				[]interface{}{customerRows[1].value},
-				[]interface{}{customerRows[2].value},
-				[]interface{}{customerRows[3].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			// Offset 5
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\" offset 5",
-			[]interface{}{
-				[]interface{}{customerRows[6].value},
-				[]interface{}{customerRows[7].value},
-				[]interface{}{customerRows[8].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 199.
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 199",
-			[]interface{}{},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			// Offset 8
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\" offset 8",
-			[]interface{}{},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			// Offset 23
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\" offset 23",
-			[]interface{}{},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or type is Invoice.
-			// Limit 3 Offset 2
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or t = \"Invoice\" limit 3 offset 2",
-			[]interface{}{
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[4].value},
-				[]interface{}{customerRows[5].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or (type is Invoice and v.InvoiceNum is not nil).
-			// Limit 3 Offset 2
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or (t = \"Invoice\" and v.InvoiceNum is not nil) limit 3 offset 2",
-			[]interface{}{
-				[]interface{}{customerRows[3].value},
-				[]interface{}{customerRows[4].value},
-				[]interface{}{customerRows[5].value},
-			},
-		},
-		{
-			// Select records where v.Foo.FooBarBaz.Baz is 84 or (type is Invoice and v.InvoiceNum is nil).
-			// Limit 3 Offset 2
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 84 or (t = \"Invoice\" and v.InvoiceNum is nil) limit 3 offset 2",
-			[]interface{}{},
-		},
-	}
-
-	for _, test := range basic {
-		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 := []interface{}{}
-			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)
-			}
-		}
-	}
-}
-
-func TestKeyPrefixes(t *testing.T) {
-	basic := []keyPrefixesTest{
-		{
-			// Need all keys (single prefix of "").
-			"select k, v from Customer",
-			[]string{""},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "abc".
-			"select k, v from Customer where t = \"Foo.Bar\" and k like \"abc%\"",
-			[]string{"abc"},
-			nil,
-		},
-		{
-			// Need all keys (single prefix of "").
-			"select k, v from Customer where t = \"Foo.Bar\" or k like \"abc%\"",
-			[]string{""},
-			nil,
-		},
-		{
-			// Need all keys (single prefix of "").
-			"select k, v from Customer where k like \"abc%\" or v.zip = \"94303\"",
-			[]string{""},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo".
-			"select k, v from Customer where t = \"Foo.Bar\" and k like \"foo_bar\"",
-			[]string{"foo"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "baz" or "foo".
-			"select k, v from Customer where k like \"foo_bar\" or k = \"baz\"",
-			[]string{"baz", "foo"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "fo".
-			"select k, v from Customer where k like \"foo_bar\" or k = \"fo\"",
-			[]string{"fo"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo".
-			"select k, v from Customer where k like \"foo%bar\"",
-			[]string{"foo"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo\bar".
-			"select k, v from Customer where k like \"foo\\\\bar\"",
-			[]string{"foo\\bar"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo%bar".
-			"select k, v from Customer where k like \"foo\\%bar\"",
-			[]string{"foo%bar"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo\%bar".
-			"select k, v from Customer where k like \"foo\\\\\\%bar\"",
-			[]string{"foo\\%bar"},
-			nil,
-		},
-		{
-			// Need all keys (single prefix of "").
-			"select k, v from Customer where k like \"%foo\"",
-			[]string{""},
-			nil,
-		},
-		{
-			// Need all keys (single prefix of "").
-			"select k, v from Customer where k like \"_foo\"",
-			[]string{""},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foo_bar".
-			"select k, v from Customer where k like \"foo\\_bar\"",
-			[]string{"foo_bar"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foobar%".
-			"select k, v from Customer where k like \"foobar\\%\"",
-			[]string{"foobar%"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "foobar_".
-			"select k, v from Customer where k like \"foobar\\_\"",
-			[]string{"foobar_"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "\%_".
-			"select k, v from Customer where k like \"\\\\\\%\\_\"",
-			[]string{"\\%_"},
-			nil,
-		},
-		{
-			// All selected rows will have key prefix of "%_abc\".
-			"select k, v from Customer where k = \"%_abc\\\"",
-			[]string{"%_abc\\"},
-			nil,
-		},
-	}
-
-	for _, test := range basic {
-		s, synErr := query_parser.Parse(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:
-					keyPrefixes := query.CompileKeyPrefixes(sel.Where)
-					if !reflect.DeepEqual(test.keyPrefixes, keyPrefixes) {
-						t.Errorf("query: %s;\nGOT  %v\nWANT %v", test.query, keyPrefixes, test.keyPrefixes)
-					}
-				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 t = \"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(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(&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 t = \"v.io/syncbase/v23/syncbase/nosql/internal/query_test.Customer\"",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where t = \"Customer\"",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.Name = \"John Smith\"",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.Name = v.Name",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v = v",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v > v",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v < v",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v >= v",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v <= v",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.Rating = 'A'",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.Rating <> 'A'",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.Rating >= 'B'",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.Rating <= 'B'",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.Active = true",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.Active = false",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.GratuituousBigInt > 100",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousBigInt = 1234567890",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where 9876543210 < v.GratuituousBigInt",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where 12 = v.GratuituousByte",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where 11 < v.GratuituousByte",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousByte > 10",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousByte >= 14",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.GratuituousByte >= 11.0",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousUint64 = 999888777666",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousUint64 < 999888777666",
-			"123456", sampleRow, false,
-		},
-		{
-			"select k, v from Customer where v.GratuituousByte < v.GratuituousUint64",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousBigRat = 123",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousUint16 = 1234",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousUint32 = 5678",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousInt16 = 9876",
-			"123456", sampleRow, true,
-		},
-		{
-			"select k, v from Customer where v.GratuituousInt32 = 876543",
-			"123456", sampleRow, true,
-		},
-		{
-			// Deeply nested string.
-			"select v from Customer where v.Foo.FooBarBaz.Foo = \"foo\"",
-			"123456", sampleRow, true,
-		},
-		{
-			// Deeply nested bool.
-			"select v from Customer where v.Foo.FooBarBaz.Bar = true",
-			"123456", sampleRow, true,
-		},
-		{
-			// Deeply nested int64.
-			"select v from Customer where v.Foo.FooBarBaz.Baz = 42",
-			"123456", sampleRow, true,
-		},
-		{
-			// Convert int64 to string
-			"select v from Customer where v.Foo.FooBarBaz.Baz = \"42\"",
-			"123456", sampleRow, true,
-		},
-		{
-			// Convert bool to string
-			"select v from Customer where v.Foo.FooBarBaz.Bar = \"true\"",
-			"123456", sampleRow, true,
-		},
-		{
-			// Bool can't convert to other types.
-			"select v from Customer where v.Foo.FooBarBaz.Bar = 1",
-			"123456", sampleRow, false,
-		},
-		{
-			// Test that all numeric types can compare to a big.Rat
-			"select v from Customer where v.GratuituousBigRat = v.Foo.FooBarBaz.Baz and v.GratuituousBigRat = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousBigRat = v.GratuituousBigInt and v.GratuituousBigRat = v.GratuituousByte and v.GratuituousBigRat = v.GratuituousUint16 and v.GratuituousBigRat = v.GratuituousUint32 and v.GratuituousBigRat = v.GratuituousUint64 and v.GratuituousBigRat = v.GratuituousInt16 and v.GratuituousBigRat = v.GratuituousInt32",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to a big.Int
-			"select v from Customer where v.GratuituousBigInt = v.Foo.FooBarBaz.Baz and v.GratuituousBigInt = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousBigInt = v.GratuituousBigInt and v.GratuituousBigInt = v.GratuituousByte and v.GratuituousBigInt = v.GratuituousUint16 and v.GratuituousBigInt = v.GratuituousUint32 and v.GratuituousBigInt = v.GratuituousUint64 and v.GratuituousBigInt = v.GratuituousInt16 and v.GratuituousBigInt = v.GratuituousInt32",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to an int32
-			"select v from Customer where v.GratuituousInt32 = v.Foo.FooBarBaz.Baz and v.GratuituousInt32 = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousInt32 = v.GratuituousInt32 and v.GratuituousInt32 = v.GratuituousByte and v.GratuituousInt32 = v.GratuituousUint16 and v.GratuituousInt32 = v.GratuituousUint32 and v.GratuituousInt32 = v.GratuituousUint64 and v.GratuituousInt32 = v.GratuituousInt16 and v.GratuituousInt32 = v.GratuituousBigInt",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to an int16
-			"select v from Customer where v.GratuituousInt16 = v.Foo.FooBarBaz.Baz and v.GratuituousInt16 = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousInt16 = v.GratuituousInt16 and v.GratuituousInt16 = v.GratuituousByte and v.GratuituousInt16 = v.GratuituousUint16 and v.GratuituousInt16 = v.GratuituousUint32 and v.GratuituousInt16 = v.GratuituousUint64 and v.GratuituousInt16 = v.GratuituousInt32 and v.GratuituousInt16 = v.GratuituousBigInt",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to an uint64
-			"select v from Customer where v.GratuituousUint64 = v.Foo.FooBarBaz.Baz and v.GratuituousUint64 = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousUint64 = v.GratuituousUint64 and v.GratuituousUint64 = v.GratuituousByte and v.GratuituousUint64 = v.GratuituousUint16 and v.GratuituousUint64 = v.GratuituousUint32 and v.GratuituousUint64 = v.GratuituousUint16 and v.GratuituousUint64 = v.GratuituousInt32 and v.GratuituousUint64 = v.GratuituousBigInt",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to an uint32
-			"select v from Customer where v.GratuituousUint32 = v.Foo.FooBarBaz.Baz and v.GratuituousUint32 = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousUint32 = v.GratuituousUint32 and v.GratuituousUint32 = v.GratuituousByte and v.GratuituousUint32 = v.GratuituousUint16 and v.GratuituousUint32 = v.GratuituousUint64 and v.GratuituousUint32 = v.GratuituousUint16 and v.GratuituousUint32 = v.GratuituousInt32 and v.GratuituousUint32 = v.GratuituousBigInt",
-			"123", sampleRow123, true,
-		},
-		{
-			// Test that all numeric types can compare to an uint16
-			"select v from Customer where v.GratuituousUint16 = v.Foo.FooBarBaz.Baz and v.GratuituousUint16 = v.ID and v.GratuituousBigRat = v.Rating and v.GratuituousUint16 = v.GratuituousUint16 and v.GratuituousUint16 = v.GratuituousByte and v.GratuituousUint32 = v.GratuituousUint16 and v.GratuituousUint16 = v.GratuituousUint64 and v.GratuituousUint16 = v.GratuituousUint16 and v.GratuituousUint16 = v.GratuituousInt32 and v.GratuituousUint16 = v.GratuituousBigInt",
-			"123", sampleRow123, true,
-		},
-	}
-
-	for _, test := range basic {
-		s, synErr := query_parser.Parse(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(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 t = \"Customer\"",
-			"123456", sampleRow,
-			[]interface{}{
-				"123456",
-				sampleRow,
-			},
-		},
-		{
-			"select k, v, v.Name, v.ID, v.Active, v.Rating, v.Street, v.City, v.State, v.Zip, v.GratuituousBigInt, v.GratuituousBigRat, v.GratuituousByte, v.GratuituousUint16, v.GratuituousUint32, v.GratuituousUint64, v.GratuituousInt16, v.GratuituousInt32, v.Foo, v.Foo.FooBarBaz, v.Foo.FooBarBaz.Foo, v.Foo.FooBarBaz.Bar, v.Foo.FooBarBaz.Baz from Customer where t = \"Customer\"",
-			"123456", sampleRow,
-			[]interface{}{
-				"123456",
-				sampleRow,
-				"John Smith",
-				int64(123456),
-				true,
-				'A',
-				"1 Main St.",
-				"Palo Alto",
-				"CA",
-				"94303",
-				big.NewInt(1234567890),
-				big.NewRat(123, 1),
-				byte(12),
-				uint16(1234),
-				uint32(5678),
-				uint64(999888777666),
-				int16(9876),
-				int32(876543),
-				Nest1{Nest2{"foo", true, int64(42)}},
-				Nest2{"foo", true, int64(42)},
-				"foo",
-				true,
-				int64(42),
-			},
-		},
-	}
-
-	for _, test := range basic {
-		s, synErr := query_parser.Parse(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(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 t = \"Customer\"",
-			"123456", sampleRow,
-			[]interface{}{
-				"123456",
-				sampleRow,
-			},
-		},
-		{
-			"select k, v from Customer where t = \"Customer\" and k like \"123%\"",
-			"123456", sampleRow,
-			[]interface{}{
-				"123456",
-				sampleRow,
-			},
-		},
-		{
-			"select k, v from Customer where t = \"Invoice\" and k like \"123%\"",
-			"123456", sampleRow,
-			nil,
-		},
-		{
-			"select k, v from Customer where t = \"Customer\" and k like \"456%\"",
-			"123456", sampleRow,
-			nil,
-		},
-		{
-			"select v from Customer where v.Name = \"John Smith\"",
-			"123456", sampleRow,
-			[]interface{}{
-				sampleRow,
-			},
-		},
-		{
-			"select v from Customer where v.Name = \"John Doe\"",
-			"123456", sampleRow,
-			nil,
-		},
-		{
-			"select k, v, v.Name, v.ID, v.Active, v.Rating, v.Street, v.City, v.State, v.Zip, v.GratuituousBigInt, v.GratuituousBigRat, v.GratuituousByte, v.GratuituousUint16, v.GratuituousUint32, v.GratuituousUint64, v.GratuituousInt16, v.GratuituousInt32, v.Foo, v.Foo.FooBarBaz, v.Foo.FooBarBaz.Foo, v.Foo.FooBarBaz.Bar, v.Foo.FooBarBaz.Baz from Customer where t = \"Customer\"",
-			"123456", sampleRow,
-			[]interface{}{
-				"123456",
-				sampleRow,
-				"John Smith",
-				int64(123456),
-				true,
-				'A',
-				"1 Main St.",
-				"Palo Alto",
-				"CA",
-				"94303",
-				big.NewInt(1234567890),
-				big.NewRat(123, 1),
-				byte(12),
-				uint16(1234),
-				uint32(5678),
-				uint64(999888777666),
-				int16(9876),
-				int32(876543),
-				Nest1{Nest2{"foo", true, int64(42)}},
-				Nest2{"foo", true, int64(42)},
-				"foo",
-				true,
-				int64(42),
-			},
-		},
-	}
-
-	for _, test := range basic {
-		s, synErr := query_parser.Parse(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(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",
-			query.Error(7, "Select field must be 'k' or 'v[{.<ident>}...]'."),
-		},
-		{
-			"select v from Unknown",
-			// The following error text is dependent on implementation of Database.
-			query.Error(14, "No such table: Unknown."),
-		},
-		{
-			"select v from Customer offset -1",
-			// The following error text is dependent on implementation of Database.
-			query.Error(30, "Expected positive integer literal., found '-'."),
-		},
-	}
-
-	for _, test := range basic {
-		_, err := query.Exec(db, test.query)
-		if !reflect.DeepEqual(err, test.err) {
-			t.Errorf("query: %s; got %v, want %v", test.query, err, test.err)
-		}
-	}
-}
diff --git a/v23/syncbase/nosql/internal/query/test/db_objects.vdl b/v23/syncbase/nosql/internal/query/test/db_objects.vdl
new file mode 100644
index 0000000..a444f0d
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/test/db_objects.vdl
@@ -0,0 +1,93 @@
+// 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
+
+type AddressInfo struct {
+	Street string
+	City   string
+	State  string
+	Zip    string
+}
+
+type CreditAgency enum {
+	Equifax
+	Experian
+	TransUnion
+}
+
+type ExperianRating enum {
+        Good
+        Bad
+}
+
+type EquifaxCreditReport struct {
+	Rating byte
+}
+
+type ExperianCreditReport struct {
+	Rating ExperianRating
+}
+
+type TransUnionCreditReport struct {
+	Rating	int16
+}
+
+type AgencyReport union {
+	EquifaxReport    EquifaxCreditReport
+	ExperianReport   ExperianCreditReport
+	TransUnionReport TransUnionCreditReport
+}
+
+type CreditReport struct {
+	Agency	CreditAgency
+	Report	AgencyReport
+}
+
+type Customer struct {
+	Name    string
+	Id      int64
+	Active  bool
+	Address AddressInfo
+	Credit  CreditReport
+}
+
+type Invoice struct {
+	CustId     int64
+	InvoiceNum int64
+	Amount     int64
+	ShipTo     AddressInfo
+}
+
+type Numbers struct {
+	B    byte
+	Ui16 uint16
+	Ui32 uint32
+	Ui64 uint64
+	I16  int16
+	I32  int32
+	I64  int64
+	F32  float32
+	F64  float64
+	C64  complex64
+	C128 complex128
+}
+
+type FooType struct {
+	Bar BarType
+}
+
+type BarType struct {
+	Baz BazType
+}
+
+type TitleOrValueType union {
+	Title string
+	Value int64
+}
+
+type BazType struct {
+	Name         string
+	TitleOrValue TitleOrValueType
+}
diff --git a/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go b/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go
new file mode 100644
index 0000000..e05dedf
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go
@@ -0,0 +1,335 @@
+// 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.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: db_objects.vdl
+
+package test
+
+import (
+	// VDL system imports
+	"fmt"
+	"v.io/v23/vdl"
+)
+
+type AddressInfo struct {
+	Street string
+	City   string
+	State  string
+	Zip    string
+}
+
+func (AddressInfo) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.AddressInfo"`
+}) {
+}
+
+type CreditAgency int
+
+const (
+	CreditAgencyEquifax CreditAgency = iota
+	CreditAgencyExperian
+	CreditAgencyTransUnion
+)
+
+// CreditAgencyAll holds all labels for CreditAgency.
+var CreditAgencyAll = [...]CreditAgency{CreditAgencyEquifax, CreditAgencyExperian, CreditAgencyTransUnion}
+
+// CreditAgencyFromString creates a CreditAgency from a string label.
+func CreditAgencyFromString(label string) (x CreditAgency, err error) {
+	err = x.Set(label)
+	return
+}
+
+// Set assigns label to x.
+func (x *CreditAgency) Set(label string) error {
+	switch label {
+	case "Equifax", "equifax":
+		*x = CreditAgencyEquifax
+		return nil
+	case "Experian", "experian":
+		*x = CreditAgencyExperian
+		return nil
+	case "TransUnion", "transunion":
+		*x = CreditAgencyTransUnion
+		return nil
+	}
+	*x = -1
+	return fmt.Errorf("unknown label %q in test.CreditAgency", label)
+}
+
+// String returns the string label of x.
+func (x CreditAgency) String() string {
+	switch x {
+	case CreditAgencyEquifax:
+		return "Equifax"
+	case CreditAgencyExperian:
+		return "Experian"
+	case CreditAgencyTransUnion:
+		return "TransUnion"
+	}
+	return ""
+}
+
+func (CreditAgency) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.CreditAgency"`
+	Enum struct{ Equifax, Experian, TransUnion string }
+}) {
+}
+
+type ExperianRating int
+
+const (
+	ExperianRatingGood ExperianRating = iota
+	ExperianRatingBad
+)
+
+// ExperianRatingAll holds all labels for ExperianRating.
+var ExperianRatingAll = [...]ExperianRating{ExperianRatingGood, ExperianRatingBad}
+
+// ExperianRatingFromString creates a ExperianRating from a string label.
+func ExperianRatingFromString(label string) (x ExperianRating, err error) {
+	err = x.Set(label)
+	return
+}
+
+// Set assigns label to x.
+func (x *ExperianRating) Set(label string) error {
+	switch label {
+	case "Good", "good":
+		*x = ExperianRatingGood
+		return nil
+	case "Bad", "bad":
+		*x = ExperianRatingBad
+		return nil
+	}
+	*x = -1
+	return fmt.Errorf("unknown label %q in test.ExperianRating", label)
+}
+
+// String returns the string label of x.
+func (x ExperianRating) String() string {
+	switch x {
+	case ExperianRatingGood:
+		return "Good"
+	case ExperianRatingBad:
+		return "Bad"
+	}
+	return ""
+}
+
+func (ExperianRating) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.ExperianRating"`
+	Enum struct{ Good, Bad string }
+}) {
+}
+
+type EquifaxCreditReport struct {
+	Rating byte
+}
+
+func (EquifaxCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.EquifaxCreditReport"`
+}) {
+}
+
+type ExperianCreditReport struct {
+	Rating ExperianRating
+}
+
+func (ExperianCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.ExperianCreditReport"`
+}) {
+}
+
+type TransUnionCreditReport struct {
+	Rating int16
+}
+
+func (TransUnionCreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.TransUnionCreditReport"`
+}) {
+}
+
+type (
+	// AgencyReport represents any single field of the AgencyReport union type.
+	AgencyReport interface {
+		// Index returns the field index.
+		Index() int
+		// Interface returns the field value as an interface.
+		Interface() interface{}
+		// Name returns the field name.
+		Name() string
+		// __VDLReflect describes the AgencyReport union type.
+		__VDLReflect(__AgencyReportReflect)
+	}
+	// AgencyReportEquifaxReport represents field EquifaxReport of the AgencyReport union type.
+	AgencyReportEquifaxReport struct{ Value EquifaxCreditReport }
+	// AgencyReportExperianReport represents field ExperianReport of the AgencyReport union type.
+	AgencyReportExperianReport struct{ Value ExperianCreditReport }
+	// AgencyReportTransUnionReport represents field TransUnionReport of the AgencyReport union type.
+	AgencyReportTransUnionReport struct{ Value TransUnionCreditReport }
+	// __AgencyReportReflect describes the AgencyReport union type.
+	__AgencyReportReflect struct {
+		Name  string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport"`
+		Type  AgencyReport
+		Union struct {
+			EquifaxReport    AgencyReportEquifaxReport
+			ExperianReport   AgencyReportExperianReport
+			TransUnionReport AgencyReportTransUnionReport
+		}
+	}
+)
+
+func (x AgencyReportEquifaxReport) Index() int                         { return 0 }
+func (x AgencyReportEquifaxReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportEquifaxReport) Name() string                       { return "EquifaxReport" }
+func (x AgencyReportEquifaxReport) __VDLReflect(__AgencyReportReflect) {}
+
+func (x AgencyReportExperianReport) Index() int                         { return 1 }
+func (x AgencyReportExperianReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportExperianReport) Name() string                       { return "ExperianReport" }
+func (x AgencyReportExperianReport) __VDLReflect(__AgencyReportReflect) {}
+
+func (x AgencyReportTransUnionReport) Index() int                         { return 2 }
+func (x AgencyReportTransUnionReport) Interface() interface{}             { return x.Value }
+func (x AgencyReportTransUnionReport) Name() string                       { return "TransUnionReport" }
+func (x AgencyReportTransUnionReport) __VDLReflect(__AgencyReportReflect) {}
+
+type CreditReport struct {
+	Agency CreditAgency
+	Report AgencyReport
+}
+
+func (CreditReport) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.CreditReport"`
+}) {
+}
+
+type Customer struct {
+	Name    string
+	Id      int64
+	Active  bool
+	Address AddressInfo
+	Credit  CreditReport
+}
+
+func (Customer) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer"`
+}) {
+}
+
+type Invoice struct {
+	CustId     int64
+	InvoiceNum int64
+	Amount     int64
+	ShipTo     AddressInfo
+}
+
+func (Invoice) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice"`
+}) {
+}
+
+type Numbers struct {
+	B    byte
+	Ui16 uint16
+	Ui32 uint32
+	Ui64 uint64
+	I16  int16
+	I32  int32
+	I64  int64
+	F32  float32
+	F64  float64
+	C64  complex64
+	C128 complex128
+}
+
+func (Numbers) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Numbers"`
+}) {
+}
+
+type FooType struct {
+	Bar BarType
+}
+
+func (FooType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.FooType"`
+}) {
+}
+
+type BarType struct {
+	Baz BazType
+}
+
+func (BarType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.BarType"`
+}) {
+}
+
+type (
+	// TitleOrValueType represents any single field of the TitleOrValueType union type.
+	TitleOrValueType interface {
+		// Index returns the field index.
+		Index() int
+		// Interface returns the field value as an interface.
+		Interface() interface{}
+		// Name returns the field name.
+		Name() string
+		// __VDLReflect describes the TitleOrValueType union type.
+		__VDLReflect(__TitleOrValueTypeReflect)
+	}
+	// TitleOrValueTypeTitle represents field Title of the TitleOrValueType union type.
+	TitleOrValueTypeTitle struct{ Value string }
+	// TitleOrValueTypeValue represents field Value of the TitleOrValueType union type.
+	TitleOrValueTypeValue struct{ Value int64 }
+	// __TitleOrValueTypeReflect describes the TitleOrValueType union type.
+	__TitleOrValueTypeReflect struct {
+		Name  string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.TitleOrValueType"`
+		Type  TitleOrValueType
+		Union struct {
+			Title TitleOrValueTypeTitle
+			Value TitleOrValueTypeValue
+		}
+	}
+)
+
+func (x TitleOrValueTypeTitle) Index() int                             { return 0 }
+func (x TitleOrValueTypeTitle) Interface() interface{}                 { return x.Value }
+func (x TitleOrValueTypeTitle) Name() string                           { return "Title" }
+func (x TitleOrValueTypeTitle) __VDLReflect(__TitleOrValueTypeReflect) {}
+
+func (x TitleOrValueTypeValue) Index() int                             { return 1 }
+func (x TitleOrValueTypeValue) Interface() interface{}                 { return x.Value }
+func (x TitleOrValueTypeValue) Name() string                           { return "Value" }
+func (x TitleOrValueTypeValue) __VDLReflect(__TitleOrValueTypeReflect) {}
+
+type BazType struct {
+	Name         string
+	TitleOrValue TitleOrValueType
+}
+
+func (BazType) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.BazType"`
+}) {
+}
+
+func init() {
+	vdl.Register((*AddressInfo)(nil))
+	vdl.Register((*CreditAgency)(nil))
+	vdl.Register((*ExperianRating)(nil))
+	vdl.Register((*EquifaxCreditReport)(nil))
+	vdl.Register((*ExperianCreditReport)(nil))
+	vdl.Register((*TransUnionCreditReport)(nil))
+	vdl.Register((*AgencyReport)(nil))
+	vdl.Register((*CreditReport)(nil))
+	vdl.Register((*Customer)(nil))
+	vdl.Register((*Invoice)(nil))
+	vdl.Register((*Numbers)(nil))
+	vdl.Register((*FooType)(nil))
+	vdl.Register((*BarType)(nil))
+	vdl.Register((*TitleOrValueType)(nil))
+	vdl.Register((*BazType)(nil))
+}
diff --git a/v23/syncbase/nosql/internal/query/test/doc.go b/v23/syncbase/nosql/internal/query/test/doc.go
new file mode 100644
index 0000000..89b03b0
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/test/doc.go
@@ -0,0 +1,6 @@
+// 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 contains tests for the query package.
+package test
diff --git a/v23/syncbase/nosql/internal/query/test/query_test.go b/v23/syncbase/nosql/internal/query/test/query_test.go
new file mode 100644
index 0000000..f61b8b1
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/test/query_test.go
@@ -0,0 +1,1261 @@
+// 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"
+	"strings"
+	"testing"
+
+	"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_db"
+	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/v23/vdl"
+)
+
+type mockDB struct {
+	tables []table
+}
+
+type table struct {
+	name string
+	rows []kv
+}
+
+type keyValueStreamImpl struct {
+	table        table
+	cursor       int
+	prefixes     []string
+	prefixCursor int
+}
+
+func (kvs *keyValueStreamImpl) Advance() bool {
+	for true {
+		kvs.cursor++ // initialized to -1
+		if kvs.cursor >= len(kvs.table.rows) {
+			return false
+		}
+		for kvs.prefixCursor < len(kvs.prefixes) {
+			// does it match any prefix
+			if kvs.prefixes[kvs.prefixCursor] == "" || strings.HasPrefix(kvs.table.rows[kvs.cursor].key, kvs.prefixes[kvs.prefixCursor]) {
+				return true
+			}
+			// Keys and prefixes are both sorted low to high, so we can increment
+			// prefixCursor if the prefix is < the key.
+			if kvs.prefixes[kvs.prefixCursor] < kvs.table.rows[kvs.cursor].key {
+				kvs.prefixCursor++
+				if kvs.prefixCursor >= len(kvs.prefixes) {
+					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(prefixes []string) (query_db.KeyValueStream, error) {
+	var keyValueStreamImpl keyValueStreamImpl
+	keyValueStreamImpl.table = t
+	keyValueStreamImpl.cursor = -1
+	keyValueStreamImpl.prefixes = prefixes
+	return &keyValueStreamImpl, nil
+}
+
+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
+
+type kv struct {
+	key   string
+	value *vdl.Value
+}
+
+func init() {
+	custTable.name = "Customer"
+	custTable.rows = []kv{
+		kv{
+			"001",
+			vdl.ValueOf(Customer{"John Smith", 1, true, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}, CreditReport{Agency: CreditAgencyEquifax, Report: AgencyReportEquifaxReport{EquifaxCreditReport{'A'}}}}),
+		},
+		kv{
+			"001001",
+			vdl.ValueOf(Invoice{1, 1000, 42, AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}}),
+		},
+		kv{
+			"001002",
+			vdl.ValueOf(Invoice{1, 1003, 7, AddressInfo{"2 Main St.", "Palo Alto", "CA", "94303"}}),
+		},
+		kv{
+			"001003",
+			vdl.ValueOf(Invoice{1, 1005, 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"}, CreditReport{Agency: CreditAgencyTransUnion, Report: AgencyReportTransUnionReport{TransUnionCreditReport{80}}}}),
+		},
+		kv{
+			"002001",
+			vdl.ValueOf(Invoice{2, 1001, 166, AddressInfo{"777 Any St.", "collins", "IA", "50055"}}),
+		},
+		kv{
+			"002002",
+			vdl.ValueOf(Invoice{2, 1002, 243, AddressInfo{"888 Any St.", "collins", "IA", "50055"}}),
+		},
+		kv{
+			"002003",
+			vdl.ValueOf(Invoice{2, 1004, 787, AddressInfo{"999 Any St.", "collins", "IA", "50055"}}),
+		},
+		kv{
+			"002004",
+			vdl.ValueOf(Invoice{2, 1006, 88, AddressInfo{"101010 Any St.", "collins", "IA", "50055"}}),
+		},
+	}
+	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)
+}
+
+type keyPrefixesTest struct {
+	query       string
+	keyPrefixes []string
+	err         *query.QueryError
+}
+
+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
+	r     [][]*vdl.Value
+}
+
+type execSelectSingleRowTest struct {
+	query  string
+	k      string
+	v      *vdl.Value
+	result []*vdl.Value
+}
+
+type execSelectErrorTest struct {
+	query string
+	err   *query.QueryError
+}
+
+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 t = \"Customer\"",
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[0].value},
+				[]*vdl.Value{custTable.rows[4].value},
+			},
+		},
+		{
+			// 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",
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[0].value},
+				[]*vdl.Value{custTable.rows[4].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",
+			[][]*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},
+			},
+		},
+		{
+			// 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",
+			[][]*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",
+			[][]*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",
+			[][]*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},
+			},
+		},
+		{
+			// 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",
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[0].value},
+				[]*vdl.Value{custTable.rows[4].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",
+			[][]*vdl.Value{},
+		},
+		{
+			// Select keys & values for all customer records.
+			"select k, v from Customer where t = \"Customer\"",
+			[][]*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},
+			},
+		},
+		{
+			// Select keys & names for all customer records.
+			"select k, v.Name from Customer where t = \"Customer\"",
+			[][]*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")},
+			},
+		},
+		{
+			// Select both customer and invoice records.
+			// Customer records have Id.
+			// Invoice records have CustId.
+			"select v.Id, v.CustId from Customer",
+			[][]*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))},
+			},
+		},
+		{
+			// Select keys & values fo all invoice records.
+			"select k, v from Customer where t = \"Invoice\"",
+			[][]*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, v.InvoiceNum, v.Amount from Customer where t = \"Invoice\" and v.Amount = 88",
+			[][]*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%\"",
+			[][]*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 "001".
+			"select k, v from Customer where k like \"002%\"",
+			[][]*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 of "001".
+			// or a key prefix of "002".
+			"select k, v from Customer where k like \"001%\" or k like \"002%\"",
+			[][]*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%\"",
+			[][]*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%\"",
+			[][]*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 \"%\"",
+			[][]*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 id, name for customers whose last name is Masterson.
+			"select v.Id, v.Name from Customer where t = \"Customer\" and v.Name like \"%Masterson\"",
+			[][]*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 t = \"Invoice\"",
+			[][]*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 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",
+			[][]*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",
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[4].value},
+			},
+		},
+		{
+			// Select customer name for customer Id (i.e., key) "001".
+			"select v.Name from Customer where t = \"Customer\" and k = \"001\"",
+			[][]*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'",
+			[][]*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",
+			[][]*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\"",
+			[][]*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",
+			[][]*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\"",
+			[][]*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 t = \"Invoice\" limit 3",
+			[][]*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 t = \"Invoice\" offset 5",
+			[][]*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\"",
+			[][]*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 t = \"Invoice\" offset 8",
+			[][]*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 t = \"Invoice\" offset 23",
+			[][]*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 t = \"Invoice\" limit 3 offset 2",
+			[][]*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 (t = \"Invoice\" and v.InvoiceNum is not nil) limit 3 offset 2",
+			[][]*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 (t = \"Invoice\" and v.InvoiceNum is nil) limit 3 offset 2",
+			[][]*vdl.Value{},
+		},
+	}
+
+	for _, test := range basic {
+		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)
+			}
+		}
+	}
+}
+
+func TestKeyPrefixes(t *testing.T) {
+	basic := []keyPrefixesTest{
+		{
+			// Need all keys (single prefix of "").
+			"select k, v from Customer",
+			[]string{""},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "abc".
+			"select k, v from Customer where t = \"Foo.Bar\" and k like \"abc%\"",
+			[]string{"abc"},
+			nil,
+		},
+		{
+			// Need all keys (single prefix of "").
+			"select k, v from Customer where t = \"Foo.Bar\" or k like \"abc%\"",
+			[]string{""},
+			nil,
+		},
+		{
+			// Need all keys (single prefix of "").
+			"select k, v from Customer where k like \"abc%\" or v.zip = \"94303\"",
+			[]string{""},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo".
+			"select k, v from Customer where t = \"Foo.Bar\" and k like \"foo_bar\"",
+			[]string{"foo"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "baz" or "foo".
+			"select k, v from Customer where k like \"foo_bar\" or k = \"baz\"",
+			[]string{"baz", "foo"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "fo".
+			"select k, v from Customer where k like \"foo_bar\" or k = \"fo\"",
+			[]string{"fo"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo".
+			"select k, v from Customer where k like \"foo%bar\"",
+			[]string{"foo"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo\bar".
+			"select k, v from Customer where k like \"foo\\\\bar\"",
+			[]string{"foo\\bar"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo%bar".
+			"select k, v from Customer where k like \"foo\\%bar\"",
+			[]string{"foo%bar"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo\%bar".
+			"select k, v from Customer where k like \"foo\\\\\\%bar\"",
+			[]string{"foo\\%bar"},
+			nil,
+		},
+		{
+			// Need all keys (single prefix of "").
+			"select k, v from Customer where k like \"%foo\"",
+			[]string{""},
+			nil,
+		},
+		{
+			// Need all keys (single prefix of "").
+			"select k, v from Customer where k like \"_foo\"",
+			[]string{""},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foo_bar".
+			"select k, v from Customer where k like \"foo\\_bar\"",
+			[]string{"foo_bar"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foobar%".
+			"select k, v from Customer where k like \"foobar\\%\"",
+			[]string{"foobar%"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "foobar_".
+			"select k, v from Customer where k like \"foobar\\_\"",
+			[]string{"foobar_"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "\%_".
+			"select k, v from Customer where k like \"\\\\\\%\\_\"",
+			[]string{"\\%_"},
+			nil,
+		},
+		{
+			// All selected rows will have key prefix of "%_abc\".
+			"select k, v from Customer where k = \"%_abc\\\"",
+			[]string{"%_abc\\"},
+			nil,
+		},
+	}
+
+	for _, test := range basic {
+		s, synErr := query_parser.Parse(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:
+					keyPrefixes := query.CompileKeyPrefixes(sel.Where)
+					if !reflect.DeepEqual(test.keyPrefixes, keyPrefixes) {
+						t.Errorf("query: %s;\nGOT  %v\nWANT %v", test.query, keyPrefixes, test.keyPrefixes)
+					}
+				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 t = \"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(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(&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 t = \"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 t = \"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.C128 = \"(456.789+10.1112i)\"",
+			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(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(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 t = \"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 t = \"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(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(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 t = \"Customer\"",
+			"123456", custTable.rows[0].value,
+			[]*vdl.Value{
+				vdl.ValueOf("123456"),
+				custTable.rows[0].value,
+			},
+		},
+		{
+			"select k, v from Customer where t = \"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 t = \"Invoice\" and k like \"123%\"",
+			"123456", custTable.rows[0].value,
+			[]*vdl.Value{},
+		},
+		{
+			"select k, v from Customer where t = \"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 t = \"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(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(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",
+			query.Error(7, "Select field must be 'k' or 'v[{.<ident>}...]'."),
+		},
+		{
+			"select v from Unknown",
+			// The following error text is dependent on implementation of Database.
+			query.Error(14, "No such table: Unknown."),
+		},
+		{
+			"select v from Customer offset -1",
+			// The following error text is dependent on implementation of Database.
+			query.Error(30, "Expected positive integer literal., found '-'."),
+		},
+	}
+
+	for _, test := range basic {
+		_, err := query.Exec(db, test.query)
+		if !reflect.DeepEqual(err, test.err) {
+			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: "t",
+						Node:  query_parser.Node{Off: 7},
+					},
+				},
+				Node: query_parser.Node{Off: 7},
+			},
+			vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer"),
+		},
+		{
+			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(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())
+		}
+	}
+}