syncbase: syncQL: replace t with Type(), remove restrictions on k

t is no longer an identifier, it has been replaced by the Typefunction.
  Simply replace t with Type(v) in any existing queries.
  This allows inquiring about types other than the v object itself
  (e.g., Type(v.Foo))

k the somewhat arbitrary restrictions on k have been removed.  Instead
  of insisting on:
    k <operator> <string_literal>
  one can use k on either side of the comparison expression and, in addition to
  string literals, value fields and functions are supported.
  Examples:
    "abc" <> k
    k = v.Key
    k = k // always true
    k <> k // always false
    k is not nil // always true
    k is nil // always false

This CL also cleans up function errors.  Rather than a single verror of FunctionReturnedError
with a text argument that can't be internationalized, separate verrors are now created.

Also fixed is a number of places where K and V (upppercase) could not be used in place
of k and v (lowercase).

Note: A change to test/integration/test-database.js (t -> Type(v)) is being mailed separately.
      It may be that I break an integration test which gets fixed by immediately submitting the
      js change.  Note: I don't see selection by type in the TODOs app.

MultiPart: 1/2

Change-Id: I1ba777b0575a7966b991e74db39b83eeb1d6cd4e
diff --git a/v23/syncbase/nosql/client_test.go b/v23/syncbase/nosql/client_test.go
index bca7a84..bd60315 100644
--- a/v23/syncbase/nosql/client_test.go
+++ b/v23/syncbase/nosql/client_test.go
@@ -84,7 +84,7 @@
 		t.Fatalf("tb.Put() failed: %v", err)
 	}
 
-	tu.CheckExec(t, ctx, d, "select k, v.Name from tb where t = \"Baz\"",
+	tu.CheckExec(t, ctx, d, "select k, v.Name from tb where Type(v) = \"Baz\"",
 		[]string{"k", "v.Name"},
 		[][]*vdl.Value{
 			[]*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz.Name)},
@@ -111,7 +111,7 @@
 			[]*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where t = \"Bar\"",
+	tu.CheckExec(t, ctx, d, "select k, v from tb where Type(v) = \"Bar\"",
 		[]string{"k", "v"},
 		[][]*vdl.Value{
 			[]*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
@@ -123,7 +123,7 @@
 			[]*vdl.Value{vdl.ValueOf("bar"), vdl.ValueOf(bar)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where t = \"Baz\"",
+	tu.CheckExec(t, ctx, d, "select k, v from tb where Type(v) = \"Baz\"",
 		[]string{"k", "v"},
 		[][]*vdl.Value{
 			[]*vdl.Value{vdl.ValueOf("baz"), vdl.ValueOf(baz)},
diff --git a/v23/syncbase/nosql/exec_test/exec_test.go b/v23/syncbase/nosql/exec_test/exec_test.go
index 1909634..645b575 100644
--- a/v23/syncbase/nosql/exec_test/exec_test.go
+++ b/v23/syncbase/nosql/exec_test/exec_test.go
@@ -229,7 +229,7 @@
 	basic := []execSelectTest{
 		{
 			// Select values for all customer records.
-			"select v from Customer where t = \"Customer\"",
+			"select v from Customer where Type(v) = \"Customer\"",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[0].value},
@@ -329,7 +329,7 @@
 		},
 		{
 			// Select keys & values for all customer records.
-			"select k, v from Customer where t = \"Customer\"",
+			"select k, v from Customer where Type(v) = \"Customer\"",
 			[]string{"k", "v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[0].key), customerEntries[0].value},
@@ -339,7 +339,7 @@
 		},
 		{
 			// Select keys & names for all customer records.
-			"select k, v.Name from Customer where t = \"Customer\"",
+			"select k, v.Name from Customer where Type(v) = \"Customer\"",
 			[]string{"k", "v.Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[0].key), vdl.ValueOf("John Smith")},
@@ -368,7 +368,7 @@
 		},
 		{
 			// Select keys & values fo all invoice records.
-			"select k, v from Customer where t = \"Invoice\"",
+			"select k, v from Customer where Type(v) = \"Invoice\"",
 			[]string{"k", "v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[1].key), customerEntries[1].value},
@@ -382,7 +382,7 @@
 		},
 		{
 			// Select key, cust id, invoice number and amount for $88 invoices.
-			"select k, v.CustId as ID, v.InvoiceNum as InvoiceNumber, v.Amount as Amt from Customer where t = \"Invoice\" and v.Amount = 88",
+			"select k, v.CustId as ID, v.InvoiceNum as InvoiceNumber, v.Amount as Amt from Customer where Type(v) = \"Invoice\" and v.Amount = 88",
 			[]string{"k", "ID", "InvoiceNumber", "Amt"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[3].key), vdl.ValueOf(int64(1)), vdl.ValueOf(int64(1005)), vdl.ValueOf(int64(88))},
@@ -510,7 +510,7 @@
 		},
 		{
 			// Select id, name for customers whose last name is Masterson.
-			"select v.Id as ID, v.Name as Name from Customer where t = \"Customer\" and v.Name like \"%Masterson\"",
+			"select v.Id as ID, v.Name as Name from Customer where Type(v) = \"Customer\" and v.Name like \"%Masterson\"",
 			[]string{"ID", "Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(int64(2)), vdl.ValueOf("Bat Masterson")},
@@ -518,7 +518,7 @@
 		},
 		{
 			// Select records where v.Address.City is "Collins" or type is Invoice.
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\"",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\"",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[1].value},
@@ -547,7 +547,7 @@
 		},
 		{
 			// Select customer name for customer Id (i.e., key) "001".
-			"select v.Name as Name from Customer where t = \"Customer\" and k = \"001\"",
+			"select v.Name as Name from Customer where Type(v) = \"Customer\" and k = \"001\"",
 			[]string{"Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("John Smith")},
@@ -596,7 +596,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" limit 3",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[1].value},
@@ -607,7 +607,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 5",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[6].value},
@@ -624,21 +624,21 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 8",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		{
 			// Select records where v.Address.City = "Collins" or type is Invoice.
 			// Offset 23
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\" offset 23",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 23",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		{
 			// Select records where v.Address.City = "Collins" is 84 or type is Invoice.
 			// Limit 3 Offset 2
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\" limit 3 offset 2",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[3].value},
@@ -649,7 +649,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or (Type(v) = \"Invoice\" and v.InvoiceNum is not nil) limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[3].value},
@@ -660,14 +660,14 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or (Type(v) = \"Invoice\" and v.InvoiceNum is nil) limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		// Test functions.
 		{
 			// Select invoice records where date is 2015-03-17
-			"select v from Customer where t = \"Invoice\" and YMD(v.InvoiceDate, \"America/Los_Angeles\") = Date(\"2015-03-17 PDT\")",
+			"select v from Customer where Type(v) = \"Invoice\" and YMD(v.InvoiceDate, \"America/Los_Angeles\") = Date(\"2015-03-17 PDT\")",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{customerEntries[5].value},
@@ -763,7 +763,7 @@
 		// Test string functions in where clause.
 		{
 			// Select invoices shipped to Any street -- using LowerCase.
-			"select k from Customer where t = \"Invoice\" and LowerCase(v.ShipTo.Street) like \"%any%\"",
+			"select k from Customer where Type(v) = \"Invoice\" and LowerCase(v.ShipTo.Street) like \"%any%\"",
 			[]string{"k"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[5].key)},
@@ -774,7 +774,7 @@
 		},
 		{
 			// Select invoices shipped to Any street -- using UpperCase.
-			"select k from Customer where t = \"Invoice\" and UpperCase(v.ShipTo.Street) like \"%ANY%\"",
+			"select k from Customer where Type(v) = \"Invoice\" and UpperCase(v.ShipTo.Street) like \"%ANY%\"",
 			[]string{"k"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(customerEntries[5].key)},
@@ -820,7 +820,7 @@
 		},
 		// LowerCase function
 		{
-			"select LowerCase(v.Name) as name from Customer where t = \"Customer\"",
+			"select LowerCase(v.Name) as name from Customer where Type(v) = \"Customer\"",
 			[]string{"name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("john smith")},
@@ -830,7 +830,7 @@
 		},
 		// UpperCase function
 		{
-			"select UpperCase(v.Name) as NAME from Customer where t = \"Customer\"",
+			"select UpperCase(v.Name) as NAME from Customer where Type(v) = \"Customer\"",
 			[]string{"NAME"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("JOHN SMITH")},
@@ -840,7 +840,7 @@
 		},
 		// YMDHMS function
 		{
-			"select k, YMDHMS(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDHMS(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDHMS",
@@ -851,7 +851,7 @@
 		},
 		// YMDHM function
 		{
-			"select k, YMDHM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDHM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDHM",
@@ -862,7 +862,7 @@
 		},
 		// YMDH function
 		{
-			"select k, YMDH(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDH(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDH",
@@ -873,7 +873,7 @@
 		},
 		// YMD function
 		{
-			"select k, YMD(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMD(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMD",
@@ -884,7 +884,7 @@
 		},
 		// YM function
 		{
-			"select k, YM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YM",
@@ -895,7 +895,7 @@
 		},
 		// Y function
 		{
-			"select k, Y(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"001001\"",
+			"select k, Y(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"001001\"",
 			[]string{
 				"k",
 				"Y",
@@ -906,7 +906,7 @@
 		},
 		// Nested functions
 		{
-			"select Y(YM(YMD(YMDH(YMDHM(YMDHMS(v.InvoiceDate, \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\")  from Customer where t = \"Invoice\" and k = \"001001\"",
+			"select Y(YM(YMD(YMDH(YMDHM(YMDHMS(v.InvoiceDate, \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\")  from Customer where Type(v) = \"Invoice\" and k = \"001001\"",
 			[]string{"Y"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(t2015)},
@@ -914,7 +914,7 @@
 		},
 		// Bad arg to function.  Expression is false.
 		{
-			"select v from Customer where t = \"Invoice\" and YMD(v.InvoiceDate, v.Foo) = v.InvoiceDate",
+			"select v from Customer where Type(v) = \"Invoice\" and YMD(v.InvoiceDate, v.Foo) = v.InvoiceDate",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
diff --git a/v23/syncbase/nosql/internal/query/eval.go b/v23/syncbase/nosql/internal/query/eval.go
index b33e975..1ab48c0 100644
--- a/v23/syncbase/nosql/internal/query/eval.go
+++ b/v23/syncbase/nosql/internal/query/eval.go
@@ -303,14 +303,24 @@
 	}
 }
 
+// Return AltStr if available, else Str.
+// Must be called with an operand of type TypStr.
+func favorAltStr(strOp *query_parser.Operand) string {
+	if !strOp.HasAltStr {
+		return strOp.Str
+	}
+	return strOp.AltStr
+}
+
 func compareStrings(lhsValue, rhsValue *query_parser.Operand, oper *query_parser.BinaryOperator) bool {
 	switch oper.Type {
 	case query_parser.Equal:
 		r := lhsValue.Str == rhsValue.Str
-		// Handle special case for type equal clauses.
-		// Only the lhs can have the AltStr field set.
-		if !r && lhsValue.HasAltStr {
-			r = lhsValue.AltStr == rhsValue.Str
+		// If either side has an AltStr, compare AltStr.
+		// If both have AltStr, compare altStr to AltStr.
+		if !r && lhsValue.HasAltStr || rhsValue.HasAltStr {
+			// Handle special case for Type functions (which have AltStr)
+			r = favorAltStr(lhsValue) == favorAltStr(rhsValue)
 		}
 		return r
 	case query_parser.NotEqual:
@@ -397,7 +407,7 @@
 	if o.Type != query_parser.TypField {
 		return o
 	}
-	value, hasAltStr, altStr := ResolveField(db, k, v, o.Column)
+	value := ResolveField(db, k, v, o.Column)
 	if value.IsNil() {
 		return nil
 	}
@@ -429,8 +439,7 @@
 	case vdl.String:
 		newOp.Type = query_parser.TypStr
 		newOp.Str = value.RawString()
-		newOp.HasAltStr = hasAltStr
-		newOp.AltStr = altStr
+		newOp.HasAltStr = false
 	case vdl.Complex64, vdl.Complex128:
 		newOp.Type = query_parser.TypComplex
 		newOp.Complex = value.Complex()
@@ -551,23 +560,13 @@
 	return nil
 }
 
-// Resolve a field.  In the special case where a type is evaluated, in addition
-// 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(db query_db.Database, k string, v *vdl.Value, f *query_parser.Field) (*vdl.Value, bool, string) {
+// Resolve a field.
+func ResolveField(db query_db.Database, k string, v *vdl.Value, f *query_parser.Field) *vdl.Value {
 	if query_checker.IsKeyField(f) {
-		return vdl.StringValue(k), false, ""
+		return vdl.StringValue(k)
 	}
 	// Auto-dereference Any and Optional values
 	v = autoDereference(v)
-	t := v.Type()
-	if query_checker.IsTypeField(f) {
-		// 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
@@ -581,7 +580,7 @@
 		// object must be a struct in order to look for the next segment.
 		if object.Kind() == vdl.Struct {
 			if object = object.StructFieldByName(segments[i].Value); object == nil {
-				return vdl.ValueOf(nil), false, "" // field does not exist
+				return vdl.ValueOf(nil)
 			}
 			object = resolveWithKey(db, k, v, object, segments[i])
 		} else if object.Kind() == vdl.Union {
@@ -590,14 +589,14 @@
 			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
+				return vdl.ValueOf(nil)
 			}
 			object = resolveWithKey(db, k, v, object, segments[i])
 		} else {
-			return vdl.ValueOf(nil), false, "" // can only traverse into structs and unions
+			return vdl.ValueOf(nil)
 		}
 	}
-	return object, false, ""
+	return object
 }
 
 // EvalWhereUsingOnlyKey return type.  See that function for details.
@@ -614,12 +613,12 @@
 // INCLUDE: the row should included in the results
 // EXCLUDE: the row should NOT be included
 // FETCH_VALUE: the value and/or type of the value are required to determine if row should be included.
-// The above decision is accomplished by evaluating all expressions which reference the key and
-// substituing false for all other expressions.  If the result is true, INCLUDE is returned.
-// If the result is false, but no other expressions (i.e., expressions which refer to the type
-// of the value or the value itself) were encountered, EXCLUDE is returned; else, FETCH_VALUE is
-// returned indicating the value must be fetched in order to determine if the row should be included
-// in the results.
+// The above decision is accomplished by evaluating all expressions which compare the key
+// with a string literal and substituing false for all other expressions.  If the result is true,
+// INCLUDE is returned.
+// If the result is false, but no other expressions were encountered, EXCLUDE is returned; else,
+// FETCH_VALUE is returned indicating the value must be fetched in order to determine if the row
+// should be included in the results.
 func EvalWhereUsingOnlyKey(db query_db.Database, s *query_parser.SelectStatement, k string) EvalWithKeyResult {
 	if s.Where == nil { // all rows will be in result
 		return INCLUDE
@@ -651,11 +650,16 @@
 		} else {
 			return FETCH_VALUE
 		}
-	default: // =, > >=, <, <=, Like, <>, NotLike
-		if !query_checker.IsKey(e.Operand1) {
+	default:
+		if !query_checker.ContainsKeyOperand(e) {
 			return FETCH_VALUE
 		} else {
-			if evalComparisonOperators(db, k, nil, e) {
+			// at least one operand is a key
+			// May still need to fetch the value (if
+			// one of the operands is a value field or a function).
+			if query_checker.ContainsFunctionOperand(e) || query_checker.ContainsValueFieldOperand(e) {
+				return FETCH_VALUE
+			} else if evalComparisonOperators(db, k, nil, e) {
 				return INCLUDE
 			} else {
 				return EXCLUDE
diff --git a/v23/syncbase/nosql/internal/query/query.go b/v23/syncbase/nosql/internal/query/query.go
index ffbd841..bcf525f 100644
--- a/v23/syncbase/nosql/internal/query/query.go
+++ b/v23/syncbase/nosql/internal/query/query.go
@@ -48,7 +48,7 @@
 		switch selector.Type {
 		case query_parser.TypSelField:
 			// If field not found, nil is returned (as per specification).
-			f, _, _ := ResolveField(db, k, v, selector.Field)
+			f := ResolveField(db, k, v, selector.Field)
 			projection = append(projection, f)
 		case query_parser.TypSelFunc:
 			if selector.Function.Computed {
diff --git a/v23/syncbase/nosql/internal/query/query_checker/query_checker.go b/v23/syncbase/nosql/internal/query/query_checker/query_checker.go
index ef112c3..5927845 100644
--- a/v23/syncbase/nosql/internal/query/query_checker/query_checker.go
+++ b/v23/syncbase/nosql/internal/query/query_checker/query_checker.go
@@ -57,7 +57,7 @@
 	for _, selector := range s.Selectors {
 		switch selector.Type {
 		case query_parser.TypSelField:
-			switch selector.Field.Segments[0].Value {
+			switch strings.ToLower(selector.Field.Segments[0].Value) {
 			case "k":
 				if len(selector.Field.Segments) > 1 {
 					return syncql.NewErrDotNotationDisallowedForKey(db.GetContext(), selector.Field.Segments[1].Off)
@@ -135,9 +135,9 @@
 		e.Operand2.CompRegex = compRegex
 	}
 
-	// Is/IsNot expressions require operand1 to be a value and operand2 to be nil.
+	// Is/IsNot expressions require operand1 to be a (value or function) and operand2 to be nil.
 	if e.Operator.Type == query_parser.Is || e.Operator.Type == query_parser.IsNot {
-		if !IsField(e.Operand1) {
+		if !IsField(e.Operand1) && !IsFunction(e.Operand1) {
 			return syncql.NewErrIsIsNotRequireLhsValue(db.GetContext(), e.Operand1.Off)
 		}
 		if e.Operand2.Type != query_parser.TypNil {
@@ -145,24 +145,15 @@
 		}
 	}
 
-	// type as an operand must be the first operand, the operator must be = and the 2nd operand must be string literal.
-	if (IsType(e.Operand1) && (e.Operator.Type != query_parser.Equal || e.Operand2.Type != query_parser.TypStr)) || IsType(e.Operand2) {
-		return syncql.NewErrTypeExpressionForm(db.GetContext(), e.Off)
-	}
-
-	// k as an operand must be the first operand, the operator must be
-	// = | <> | > | >= | < | <= | like | not like and the 2nd operand must be a string literal.
-	if (IsKey(e.Operand1) &&
-		((e.Operator.Type != query_parser.Equal &&
-			e.Operator.Type != query_parser.GreaterThan &&
-			e.Operator.Type != query_parser.GreaterThanOrEqual &&
-			e.Operator.Type != query_parser.LessThan &&
-			e.Operator.Type != query_parser.LessThanOrEqual &&
-			e.Operator.Type != query_parser.Like &&
-			e.Operator.Type != query_parser.NotEqual &&
-			e.Operator.Type != query_parser.NotLike) ||
-			e.Operand2.Type != query_parser.TypStr)) || IsKey(e.Operand2) {
-		return syncql.NewErrKeyExpressionForm(db.GetContext(), e.Off)
+	// if an operand is k and the other operand is a literal, that literal must be a string
+	// literal.
+	if ContainsKeyOperand(e) && ((isLiteral(e.Operand1) && !isStringLiteral(e.Operand1)) ||
+		(isLiteral(e.Operand2) && !isStringLiteral(e.Operand2))) {
+		off := e.Operand1.Off
+		if isLiteral(e.Operand2) {
+			off = e.Operand2.Off
+		}
+		return syncql.NewErrKeyExpressionLiteral(db.GetContext(), off)
 	}
 
 	// If either operand is a bool, only = and <> operators are allowed.
@@ -178,16 +169,12 @@
 	case query_parser.TypExpr:
 		return checkExpression(db, o.Expr)
 	case query_parser.TypField:
-		switch o.Column.Segments[0].Value {
+		switch strings.ToLower(o.Column.Segments[0].Value) {
 		case "k":
 			if len(o.Column.Segments) > 1 {
 				return syncql.NewErrDotNotationDisallowedForKey(db.GetContext(), o.Column.Segments[1].Off)
 			}
 		case "v":
-		case "t":
-			if len(o.Column.Segments) > 1 {
-				return syncql.NewErrDotNotationDisallowedForType(db.GetContext(), o.Column.Segments[1].Off)
-			}
 		default:
 			return syncql.NewErrBadFieldInWhere(db.GetContext(), o.Column.Segments[0].Off)
 		}
@@ -346,12 +333,42 @@
 	return o.Type == query_parser.TypField
 }
 
-func IsKey(o *query_parser.Operand) bool {
-	return IsField(o) && IsKeyField(o.Column)
+func IsFunction(o *query_parser.Operand) bool {
+	return o.Type == query_parser.TypFunction
 }
 
-func IsType(o *query_parser.Operand) bool {
-	return IsField(o) && IsTypeField(o.Column)
+func ContainsKeyOperand(expr *query_parser.Expression) bool {
+	return IsKey(expr.Operand1) || IsKey(expr.Operand2)
+}
+
+func ContainsFunctionOperand(expr *query_parser.Expression) bool {
+	return IsFunction(expr.Operand1) || IsFunction(expr.Operand2)
+}
+
+func ContainsValueFieldOperand(expr *query_parser.Expression) bool {
+	return (expr.Operand1.Type == query_parser.TypField && IsValueField(expr.Operand1.Column)) ||
+		(expr.Operand2.Type == query_parser.TypField && IsValueField(expr.Operand2.Column))
+
+}
+
+func isStringLiteral(o *query_parser.Operand) bool {
+	return o.Type == query_parser.TypStr
+}
+
+func isLiteral(o *query_parser.Operand) bool {
+	return o.Type == query_parser.TypBigInt ||
+		o.Type == query_parser.TypBigRat || // currently, no way to specify as literal
+		o.Type == query_parser.TypBool ||
+		o.Type == query_parser.TypComplex || // currently, no way to specify as literal ||
+		o.Type == query_parser.TypFloat ||
+		o.Type == query_parser.TypInt ||
+		o.Type == query_parser.TypStr ||
+		o.Type == query_parser.TypTime || // currently, no way to specify as literal
+		o.Type == query_parser.TypUint
+}
+
+func IsKey(o *query_parser.Operand) bool {
+	return IsField(o) && IsKeyField(o.Column)
 }
 
 func IsKeyField(f *query_parser.Field) bool {
@@ -362,10 +379,6 @@
 	return strings.ToLower(f.Segments[0].Value) == "v"
 }
 
-func IsTypeField(f *query_parser.Field) bool {
-	return strings.ToLower(f.Segments[0].Value) == "t"
-}
-
 func IsExpr(o *query_parser.Operand) bool {
 	return o.Type == query_parser.TypExpr
 }
@@ -476,27 +489,70 @@
 			}
 			return lhsKeyRanges
 		}
-	} else if IsKey(expr.Operand1) {
-		switch expr.Operator.Type {
-		case query_parser.Equal:
-			return &query_db.KeyRanges{computeKeyRangeForSingleValue(expr.Operand2.Str)}
-		case query_parser.GreaterThan:
-			return &query_db.KeyRanges{query_db.KeyRange{string(append([]byte(expr.Operand2.Str), 0)), MaxRangeLimit}}
-		case query_parser.GreaterThanOrEqual:
-			return &query_db.KeyRanges{query_db.KeyRange{expr.Operand2.Str, MaxRangeLimit}}
-		case query_parser.Like:
-			return &query_db.KeyRanges{computeKeyRangeForLike(expr.Operand2.Prefix)}
-		case query_parser.NotLike:
-			return computeKeyRangesForNotLike(expr.Operand2.Prefix)
-		case query_parser.LessThan:
-			return &query_db.KeyRanges{query_db.KeyRange{"", expr.Operand2.Str}}
-		case query_parser.LessThanOrEqual:
-			return &query_db.KeyRanges{query_db.KeyRange{"", string(append([]byte(expr.Operand2.Str), 0))}}
-		default: // case query_parser.NotEqual:
-			return &query_db.KeyRanges{
-				query_db.KeyRange{"", expr.Operand2.Str},
-				query_db.KeyRange{string(append([]byte(expr.Operand2.Str), 0)), MaxRangeLimit},
+	} else if ContainsKeyOperand(expr) { // true if either operand is 'k'
+		if IsKey(expr.Operand1) && IsKey(expr.Operand2) {
+			//k <op> k
+			switch expr.Operator.Type {
+			case query_parser.Equal, query_parser.GreaterThanOrEqual, query_parser.LessThanOrEqual:
+				// True for all keys
+				return &query_db.KeyRanges{KeyRangeAll}
+			default: // query_parser.NotEqual, query_parser.GreaterThan, query_parser.LessThan:
+				// False for all keys
+				return &query_db.KeyRanges{}
 			}
+		} else if expr.Operator.Type == query_parser.Is {
+			// k is nil
+			// False for all keys
+			return &query_db.KeyRanges{}
+		} else if expr.Operator.Type == query_parser.IsNot {
+			// k is not nil
+			// True for all keys
+			return &query_db.KeyRanges{KeyRangeAll}
+		} else if isStringLiteral(expr.Operand2) {
+			// k <op> <string-literal>
+			switch expr.Operator.Type {
+			case query_parser.Equal:
+				return &query_db.KeyRanges{computeKeyRangeForSingleValue(expr.Operand2.Str)}
+			case query_parser.GreaterThan:
+				return &query_db.KeyRanges{query_db.KeyRange{string(append([]byte(expr.Operand2.Str), 0)), MaxRangeLimit}}
+			case query_parser.GreaterThanOrEqual:
+				return &query_db.KeyRanges{query_db.KeyRange{expr.Operand2.Str, MaxRangeLimit}}
+			case query_parser.Like:
+				return &query_db.KeyRanges{computeKeyRangeForLike(expr.Operand2.Prefix)}
+			case query_parser.NotLike:
+				return computeKeyRangesForNotLike(expr.Operand2.Prefix)
+			case query_parser.LessThan:
+				return &query_db.KeyRanges{query_db.KeyRange{"", expr.Operand2.Str}}
+			case query_parser.LessThanOrEqual:
+				return &query_db.KeyRanges{query_db.KeyRange{"", string(append([]byte(expr.Operand2.Str), 0))}}
+			default: // case query_parser.NotEqual:
+				return &query_db.KeyRanges{
+					query_db.KeyRange{"", expr.Operand2.Str},
+					query_db.KeyRange{string(append([]byte(expr.Operand2.Str), 0)), MaxRangeLimit},
+				}
+			}
+		} else if isStringLiteral(expr.Operand1) {
+			//<string-literal> <op> k
+			switch expr.Operator.Type {
+			case query_parser.Equal:
+				return &query_db.KeyRanges{computeKeyRangeForSingleValue(expr.Operand1.Str)}
+			case query_parser.GreaterThan:
+				return &query_db.KeyRanges{query_db.KeyRange{"", expr.Operand1.Str}}
+			case query_parser.GreaterThanOrEqual:
+				return &query_db.KeyRanges{query_db.KeyRange{"", string(append([]byte(expr.Operand1.Str), 0))}}
+			case query_parser.LessThan:
+				return &query_db.KeyRanges{query_db.KeyRange{string(append([]byte(expr.Operand1.Str), 0)), MaxRangeLimit}}
+			case query_parser.LessThanOrEqual:
+				return &query_db.KeyRanges{query_db.KeyRange{expr.Operand1.Str, MaxRangeLimit}}
+			default: // case query_parser.NotEqual:
+				return &query_db.KeyRanges{
+					query_db.KeyRange{"", expr.Operand1.Str},
+					query_db.KeyRange{string(append([]byte(expr.Operand1.Str), 0)), MaxRangeLimit},
+				}
+			}
+		} else {
+			// A function or a field s being compared to the key.
+			return &query_db.KeyRanges{KeyRangeAll}
 		}
 	} else { // not a key compare, so it applies to the entire key range
 		return &query_db.KeyRanges{KeyRangeAll}
diff --git a/v23/syncbase/nosql/internal/query/query_checker/query_checker_test.go b/v23/syncbase/nosql/internal/query/query_checker/query_checker_test.go
index dc7fa12..9d410b0 100644
--- a/v23/syncbase/nosql/internal/query/query_checker/query_checker_test.go
+++ b/v23/syncbase/nosql/internal/query/query_checker/query_checker_test.go
@@ -90,8 +90,50 @@
 		{"select k, v.name from Customer limit 200"},
 		{"select k, v.name from Customer offset 100"},
 		{"select k, v.name from Customer where k = \"foo\""},
-		{"select v from Customer where t = \"Foo.Bar\""},
-		{"select k, v from Customer where t = \"Foo.Bar\" and k like \"abc%\" limit 100 offset 200"},
+		{"select v.z from Customer where k = v.y"},
+		{"select v.z from Customer where k <> v.y"},
+		{"select v.z from Customer where k < v.y"},
+		{"select v.z from Customer where k <= v.y"},
+		{"select v.z from Customer where k > v.y"},
+		{"select v.z from Customer where k >= v.y"},
+		{"select v from Customer where k is nil"},
+		{"select v from Customer where k is not nil"},
+		{"select k, v.name from Customer where \"foo\" = k"},
+		{"select v.z from Customer where v.y = k"},
+		{"select v.z from Customer where v.y <> k"},
+		{"select v.z from Customer where v.y < k"},
+		{"select v.z from Customer where v.y <= k"},
+		{"select v.z from Customer where v.y > k"},
+		{"select v.z from Customer where v.y >= k"},
+		{"select v.z from Customer where \"abc%\" = k"},
+		{"select v from Customer where k is nil"},
+		{"select v from Customer where k is not nil"},
+		{"select v from Customer where Type(v) = \"Foo.Bar\""},
+		{"select v from Customer where Type(v) <> \"Foo.Bar\""},
+		{"select v from Customer where Type(v) < \"Foo.Bar\""},
+		{"select v from Customer where Type(v) <= \"Foo.Bar\""},
+		{"select v from Customer where Type(v) > \"Foo.Bar\""},
+		{"select v from Customer where Type(v) >= \"Foo.Bar\""},
+		{"select v from Customer where Type(v) like \"%.Foo.Bar\""},
+		{"select v from Customer where Type(v) not like \"%.Foo.Bar\""},
+		{"select v from Customer where Type(v) is nil"},
+		{"select v from Customer where Type(v) is not nil"},
+		{"select v from Customer where \"Foo.Bar\" = Type(v)"},
+		{"select v from Customer where \"Foo.Bar\" <> Type(v)"},
+		{"select v from Customer where \"Foo.Bar\" < Type(v)"},
+		{"select v from Customer where \"Foo.Bar\" > Type(v)"},
+		{"select v from Customer where \"Foo.Bar\" <= Type(v)"},
+		{"select v from Customer where \"Foo.Bar\" >= Type(v)"},
+		{"select v.z from Customer where Type(v) = 2"},
+		{"select v.z from Customer where Type(v) <> \"foo\""},
+		{"select v.z from Customer where Type(v) < \"foo\""},
+		{"select v.z from Customer where Type(v) <= \"foo\""},
+		{"select v.z from Customer where Type(v) > \"foo\""},
+		{"select v.z from Customer where Type(v) >= \"foo\""},
+		{"select v.z from Customer where \"foo\" = Type(v)"},
+		{"select k, v from Customer where Type(v) = \"Foo.Bar\" and k like \"abc%\" limit 100 offset 200"},
+		{"select v from Customer where Type(v) is nil"},
+		{"select v from Customer where Type(v) is not nil"},
 		{"select v.z from Customer where k not like \"foo\""},
 		{"select v.z from Customer where k not like \"foo%\""},
 		{"select v from Customer where v.A = true"},
@@ -146,13 +188,20 @@
 			},
 		},
 		{
+			"select k, v from Customer where \"abc\" = k or \"def\" = k",
+			&query_db.KeyRanges{
+				query_db.KeyRange{"abc", appendZeroByte("abc")},
+				query_db.KeyRange{"def", appendZeroByte("def")},
+			},
+		},
+		{
 			"select k, v from Customer where k >= \"foo\" and k < \"goo\"",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"foo", "goo"},
 			},
 		},
 		{
-			"select k, v from Customer where k >= \"foo\" and k <= \"goo\"",
+			"select k, v from Customer where \"foo\" <= k and \"goo\" >= k",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"foo", appendZeroByte("goo")},
 			},
@@ -185,7 +234,7 @@
 			},
 		},
 		{
-			"select v from Customer where t = \"Foo.Bar\" and k >= \"100\" and k < \"200\" and v.foo > 50 and v.bar <= 1000 and v.baz <> -20.7",
+			"select v from Customer where Type(v) = \"Foo.Bar\" and k >= \"100\" and k < \"200\" and v.foo > 50 and v.bar <= 1000 and v.baz <> -20.7",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"100", "200"},
 			},
@@ -195,7 +244,7 @@
 			&query_db.KeyRanges{},
 		},
 		{
-			"select k, v from Customer where t = \"Foo.Bar\" and k like \"abc%\" limit 100 offset 200",
+			"select k, v from Customer where Type(v) = \"Foo.Bar\" and k like \"abc%\" limit 100 offset 200",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"abc", "abd"},
 			},
@@ -365,53 +414,35 @@
 		{"select a from Customer", syncql.NewErrInvalidSelectField(db.GetContext(), 7)},
 		{"select v from Bob", syncql.NewErrTableCantAccess(db.GetContext(), 14, "Bob", errors.New("No such table: Bob"))},
 		{"select k.a from Customer", syncql.NewErrDotNotationDisallowedForKey(db.GetContext(), 9)},
-		{"select k from Customer where t.a = \"Foo.Bar\"", syncql.NewErrDotNotationDisallowedForType(db.GetContext(), 31)},
+		{"select k from Customer where t.a = \"Foo.Bar\"", syncql.NewErrBadFieldInWhere(db.GetContext(), 29)},
 		{"select v from Customer where a=1", syncql.NewErrBadFieldInWhere(db.GetContext(), 29)},
 		{"select v from Customer limit 0", syncql.NewErrLimitMustBeGe0(db.GetContext(), 29)},
-		{"select v.z from Customer where t = 2", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where t <> \"foo\"", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where t < \"foo\"", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where t <= \"foo\"", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where t > \"foo\"", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where t >= \"foo\"", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where \"foo\" = t", syncql.NewErrTypeExpressionForm(db.GetContext(), 31)},
 		{"select v.z from Customer where v.x like v.y", syncql.NewErrLikeExpressionsRequireRhsString(db.GetContext(), 31)},
-		{"select v.z from Customer where k = v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where k <> v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where k < v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where k <= v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where k > v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where k >= v.y", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
-		{"select v.z from Customer where \"abc%\" = k", syncql.NewErrKeyExpressionForm(db.GetContext(), 31)},
 		{"select v.z from Customer where k like \"a\\bc%\"", syncql.NewErrInvalidEscapedChar(db.GetContext(), 38)},
 		{"select v from Customer where v.A > false", syncql.NewErrBoolInvalidExpression(db.GetContext(), 33)},
 		{"select v from Customer where true <= v.A", syncql.NewErrBoolInvalidExpression(db.GetContext(), 34)},
 		{"select v from Customer where Foo(\"2015/07/22\", true, 3.14157) = true", syncql.NewErrFunctionNotFound(db.GetContext(), 29, "Foo")},
-		{"select v from Customer where t is nil", syncql.NewErrTypeExpressionForm(db.GetContext(), 29)},
-		{"select v from Customer where k is nil", syncql.NewErrKeyExpressionForm(db.GetContext(), 29)},
 		{"select v from Customer where nil is v.ZipCode", syncql.NewErrIsIsNotRequireLhsValue(db.GetContext(), 29)},
 		{"select v from Customer where v.ZipCode is \"94303\"", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 42)},
 		{"select v from Customer where v.ZipCode is 94303", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 42)},
 		{"select v from Customer where v.ZipCode is true", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 42)},
 		{"select v from Customer where v.ZipCode is 943.03", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 42)},
-		{"select v from Customer where t is not nil", syncql.NewErrTypeExpressionForm(db.GetContext(), 29)},
-		{"select v from Customer where k is not nil", syncql.NewErrKeyExpressionForm(db.GetContext(), 29)},
 		{"select v from Customer where nil is not v.ZipCode", syncql.NewErrIsIsNotRequireLhsValue(db.GetContext(), 29)},
 		{"select v from Customer where v.ZipCode is not \"94303\"", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 46)},
 		{"select v from Customer where v.ZipCode is not 94303", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 46)},
 		{"select v from Customer where v.ZipCode is not true", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 46)},
 		{"select v from Customer where v.ZipCode is not 943.03", syncql.NewErrIsIsNotRequireRhsNil(db.GetContext(), 46)},
-		{"select v from Customer where t = \"Customer\" and y(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 65, "y", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and YM(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 66, "YM", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and YMD(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 67, "YMD", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and YMDH(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 68, "YMDH", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and YMDHM(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 69, "YMDHM", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and YMDHMS(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionReturnedError(db.GetContext(), 70, "YMDHMS", errors.New("unknown time zone ABC"))},
-		{"select v from Customer where t = \"Customer\" and Now(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionArgCount(db.GetContext(), 48, "Now", 0, 2)},
-		{"select v from Customer where t = \"Customer\" and LowerCase(v.Name, 2) = \"smith\"", syncql.NewErrFunctionArgCount(db.GetContext(), 48, "LowerCase", 1, 2)},
-		{"select v from Customer where t = \"Customer\" and UpperCase(v.Name, 2) = \"SMITH\"", syncql.NewErrFunctionArgCount(db.GetContext(), 48, "UpperCase", 1, 2)},
+		{"select v from Customer where Type(v) = \"Customer\" and y(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 71, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and YM(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 72, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and YMD(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 73, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and YMDH(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 74, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and YMDHM(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 75, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and YMDHMS(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrLocationConversionError(db.GetContext(), 76, errors.New("unknown time zone ABC"))},
+		{"select v from Customer where Type(v) = \"Customer\" and Now(v.InvoiceDate, \"ABC\") = 2015", syncql.NewErrFunctionArgCount(db.GetContext(), 54, "Now", 0, 2)},
+		{"select v from Customer where Type(v) = \"Customer\" and LowerCase(v.Name, 2) = \"smith\"", syncql.NewErrFunctionArgCount(db.GetContext(), 54, "LowerCase", 1, 2)},
+		{"select v from Customer where Type(v) = \"Customer\" and UpperCase(v.Name, 2) = \"SMITH\"", syncql.NewErrFunctionArgCount(db.GetContext(), 54, "UpperCase", 1, 2)},
 		{"select Date() from Customer", syncql.NewErrFunctionArgCount(db.GetContext(), 7, "Date", 1, 0)},
-		{"select Y(v.InvoiceDate, \"Foo\") from Customer where t = \"Invoice\"", syncql.NewErrFunctionReturnedError(db.GetContext(), 24, "Y", errors.New("unknown time zone Foo"))},
+		{"select Y(v.InvoiceDate, \"Foo\") from Customer where Type(v) = \"Invoice\"", syncql.NewErrLocationConversionError(db.GetContext(), 24, errors.New("unknown time zone Foo"))},
 	}
 
 	for _, test := range basic {
diff --git a/v23/syncbase/nosql/internal/query/query_functions/date_funcs.go b/v23/syncbase/nosql/internal/query/query_functions/date_funcs.go
index 74dc7f2..1a1ed91 100644
--- a/v23/syncbase/nosql/internal/query/query_functions/date_funcs.go
+++ b/v23/syncbase/nosql/internal/query/query_functions/date_funcs.go
@@ -9,21 +9,31 @@
 
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/conversions"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/syncbase/v23/syncbase/nosql/query_db"
+	"v.io/syncbase/v23/syncbase/nosql/syncql"
 )
 
 // If possible, check if arg is convertable to a time.  Fields and not yet computed
 // functions cannot be checked and will just return nil.
-func checkIfPossibleThatArgIsConvertableToTime(arg *query_parser.Operand) error {
+func checkIfPossibleThatArgIsConvertableToTime(db query_db.Database, arg *query_parser.Operand) error {
 	// If arg is a literal or an already computed function,
 	// make sure it can be converted to a time.
 	switch arg.Type {
 	case query_parser.TypBigInt, query_parser.TypBigRat, query_parser.TypBool, query_parser.TypComplex, query_parser.TypFloat, query_parser.TypInt, query_parser.TypStr, query_parser.TypTime, query_parser.TypUint:
 		_, err := conversions.ConvertValueToTime(arg)
-		return err
+		if err != nil {
+			return syncql.NewErrTimeConversionError(db.GetContext(), arg.Off, err)
+		} else {
+			return nil
+		}
 	case query_parser.TypFunction:
 		if arg.Function.Computed {
 			_, err := conversions.ConvertValueToTime(arg.Function.RetValue)
-			return err
+			if err != nil {
+				return syncql.NewErrTimeConversionError(db.GetContext(), arg.Off, err)
+			} else {
+				return nil
+			}
 		}
 	}
 	return nil
@@ -31,18 +41,26 @@
 
 // If possible, check if arg is convertable to a location.  Fields and not yet computed
 // functions cannot be checked and will just return nil.
-func checkIfPossibleThatArgIsConvertableToLocation(arg *query_parser.Operand) error {
+func checkIfPossibleThatArgIsConvertableToLocation(db query_db.Database, arg *query_parser.Operand) error {
 	var locStr *query_parser.Operand
 	var err error
 	switch arg.Type {
 	case query_parser.TypBigInt, query_parser.TypBigRat, query_parser.TypBool, query_parser.TypComplex, query_parser.TypFloat, query_parser.TypInt, query_parser.TypStr, query_parser.TypTime, query_parser.TypUint:
 		if locStr, err = conversions.ConvertValueToString(arg); err != nil {
-			return err
+			if err != nil {
+				return syncql.NewErrLocationConversionError(db.GetContext(), arg.Off, err)
+			} else {
+				return nil
+			}
 		}
 	case query_parser.TypFunction:
 		if arg.Function.Computed {
 			if locStr, err = conversions.ConvertValueToString(arg.Function.RetValue); err != nil {
-				return err
+				if err != nil {
+					return syncql.NewErrLocationConversionError(db.GetContext(), arg.Off, err)
+				} else {
+					return nil
+				}
 			}
 		} else {
 			// Arg is uncomputed function, can't make determination about arg.
@@ -53,7 +71,11 @@
 		return nil
 	}
 	_, err = time.LoadLocation(locStr.Str)
-	return err
+	if err != nil {
+		return syncql.NewErrLocationConversionError(db.GetContext(), arg.Off, err)
+	} else {
+		return nil
+	}
 }
 
 // Input: "YYYY-MM-DD TZ"
@@ -237,18 +259,18 @@
 	return &o
 }
 
-func timeAndStringArgsCheck(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
+func timeAndStringArgsCheck(db query_db.Database, off int64, args []*query_parser.Operand) error {
 	// The first arg must be a time.
-	if err := checkIfPossibleThatArgIsConvertableToTime(args[0]); err != nil {
-		return args[0], err
+	if err := checkIfPossibleThatArgIsConvertableToTime(db, args[0]); err != nil {
+		return err
 	}
 	// The second arg must be a string and convertable to a location.
-	if err := checkIfPossibleThatArgIsConvertableToLocation(args[1]); err != nil {
-		return args[1], err
+	if err := checkIfPossibleThatArgIsConvertableToLocation(db, args[1]); err != nil {
+		return err
 	}
-	return nil, nil
+	return nil
 }
 
-func singleTimeArgCheck(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
-	return checkIfPossibleThatArgIsConvertableToString(args[0])
+func singleTimeArgCheck(db query_db.Database, off int64, args []*query_parser.Operand) error {
+	return checkIfPossibleThatArgIsConvertableToString(db, args[0])
 }
diff --git a/v23/syncbase/nosql/internal/query/query_functions/math_funcs.go b/v23/syncbase/nosql/internal/query/query_functions/math_funcs.go
index cfb01ae..5628180 100644
--- a/v23/syncbase/nosql/internal/query/query_functions/math_funcs.go
+++ b/v23/syncbase/nosql/internal/query/query_functions/math_funcs.go
@@ -7,6 +7,8 @@
 import (
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/conversions"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/syncbase/v23/syncbase/nosql/query_db"
+	"v.io/syncbase/v23/syncbase/nosql/syncql"
 )
 
 func complexFunc(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
@@ -23,15 +25,14 @@
 	return makeComplexOp(off, complex(r.Float, i.Float)), nil
 }
 
-func twoFloatsArgsCheck(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
+func twoFloatsArgsCheck(db query_db.Database, off int64, args []*query_parser.Operand) error {
 	// The two args must be convertable to floats.
-	if err := checkIfPossibleThatArgIsConvertableToFloat(args[0]); err != nil {
-		return args[0], err
+	for i := 0; i < 2; i++ {
+		if err := checkIfPossibleThatArgIsConvertableToFloat(args[i]); err != nil {
+			return syncql.NewErrFloatConversionError(db.GetContext(), args[i].Off, err)
+		}
 	}
-	if err := checkIfPossibleThatArgIsConvertableToFloat(args[1]); err != nil {
-		return args[1], err
-	}
-	return nil, nil
+	return nil
 }
 
 // If possible, check if arg is convertable to a float.  Fields and not yet computed
diff --git a/v23/syncbase/nosql/internal/query/query_functions/query_functions.go b/v23/syncbase/nosql/internal/query/query_functions/query_functions.go
index 326bbf8..285d875 100644
--- a/v23/syncbase/nosql/internal/query/query_functions/query_functions.go
+++ b/v23/syncbase/nosql/internal/query/query_functions/query_functions.go
@@ -15,7 +15,7 @@
 )
 
 type queryFunc func(int64, []*query_parser.Operand) (*query_parser.Operand, error)
-type checkArgsFunc func(int64, []*query_parser.Operand) (*query_parser.Operand, error)
+type checkArgsFunc func(query_db.Database, int64, []*query_parser.Operand) error
 
 type function struct {
 	argTypes      []query_parser.OperandType
@@ -40,6 +40,7 @@
 	functions["now"] = function{[]query_parser.OperandType{}, query_parser.TypTime, now, nil}
 
 	functions["lowercase"] = function{[]query_parser.OperandType{query_parser.TypStr}, query_parser.TypStr, lowerCase, singleStringArgCheck}
+	functions["type"] = function{[]query_parser.OperandType{query_parser.TypObject}, query_parser.TypStr, typeFunc, singleFieldArgCheck}
 	functions["uppercase"] = function{[]query_parser.OperandType{query_parser.TypStr}, query_parser.TypStr, upperCase, singleStringArgCheck}
 
 	functions["complex"] = function{[]query_parser.OperandType{query_parser.TypFloat, query_parser.TypFloat}, query_parser.TypComplex, complexFunc, twoFloatsArgsCheck}
@@ -102,8 +103,8 @@
 		return syncql.NewErrFunctionNotFound(db.GetContext(), f.Off, f.Name)
 	} else {
 		if entry.checkArgsAddr != nil {
-			if arg, err := entry.checkArgsAddr(f.Off, args); err != nil {
-				return syncql.NewErrFunctionReturnedError(db.GetContext(), arg.Off, f.Name, err)
+			if err := entry.checkArgsAddr(db, f.Off, args); err != nil {
+				return err
 			}
 		}
 	}
@@ -116,7 +117,7 @@
 	} else {
 		retValue, err := entry.funcAddr(f.Off, args)
 		if err != nil {
-			return nil, syncql.NewErrFunctionReturnedError(db.GetContext(), f.Off, f.Name, err)
+			return nil, err
 		} else {
 			return retValue, nil
 		}
@@ -124,6 +125,9 @@
 }
 
 func ConvertFunctionRetValueToVdlValue(o *query_parser.Operand) *vdl.Value {
+	if o == nil {
+		return vdl.ValueOf(nil)
+	}
 	switch o.Type {
 	case query_parser.TypBool:
 		return vdl.ValueOf(o.Bool)
@@ -145,7 +149,7 @@
 		// Other types can't be converted and *shouldn't* be returned
 		// from a function.  This case will result in a nil for this
 		// column in the row.
-		return nil
+		return vdl.ValueOf(nil)
 	}
 }
 
@@ -157,6 +161,13 @@
 	return &o
 }
 
+func makeStrOpWithAlt(off int64, s string, alt string) *query_parser.Operand {
+	o := makeStrOp(off, s)
+	o.HasAltStr = true
+	o.AltStr = alt
+	return o
+}
+
 func makeComplexOp(off int64, c complex128) *query_parser.Operand {
 	var o query_parser.Operand
 	o.Off = off
@@ -165,24 +176,41 @@
 	return &o
 }
 
-func singleStringArgCheck(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
-	return checkIfPossibleThatArgIsConvertableToString(args[0])
+func singleStringArgCheck(db query_db.Database, off int64, args []*query_parser.Operand) error {
+	return checkIfPossibleThatArgIsConvertableToString(db, args[0])
+}
+
+func singleFieldArgCheck(db query_db.Database, off int64, args []*query_parser.Operand) error {
+	// single argument must be of type field
+	// It must begin with a v segment.
+	if args[0].Type != query_parser.TypField || len(args[0].Column.Segments) < 1 || strings.ToLower(args[0].Column.Segments[0].Value) != "v" {
+		return syncql.NewErrArgMustBeField(db.GetContext(), args[0].Off)
+	}
+	return nil
 }
 
 // If possible, check if arg is convertable to a string.  Fields and not yet computed
 // functions cannot be checked and will just return nil.
-func checkIfPossibleThatArgIsConvertableToString(arg *query_parser.Operand) (*query_parser.Operand, error) {
+func checkIfPossibleThatArgIsConvertableToString(db query_db.Database, arg *query_parser.Operand) error {
 	// If arg is a literal or an already computed function,
 	// make sure it can be converted to a string.
 	switch arg.Type {
 	case query_parser.TypBigInt, query_parser.TypBigRat, query_parser.TypBool, query_parser.TypComplex, query_parser.TypFloat, query_parser.TypInt, query_parser.TypStr, query_parser.TypTime, query_parser.TypUint:
 		_, err := conversions.ConvertValueToString(arg)
-		return arg, err
+		if err != nil {
+			return syncql.NewErrStringConversionError(db.GetContext(), arg.Off, err)
+		} else {
+			return nil
+		}
 	case query_parser.TypFunction:
 		if arg.Function.Computed {
 			_, err := conversions.ConvertValueToString(arg.Function.RetValue)
-			return arg, err
+			if err != nil {
+				return syncql.NewErrStringConversionError(db.GetContext(), arg.Off, err)
+			} else {
+				return nil
+			}
 		}
 	}
-	return nil, nil
+	return nil
 }
diff --git a/v23/syncbase/nosql/internal/query/query_functions/str_funcs.go b/v23/syncbase/nosql/internal/query/query_functions/str_funcs.go
index 5a253ee..77b6eac 100644
--- a/v23/syncbase/nosql/internal/query/query_functions/str_funcs.go
+++ b/v23/syncbase/nosql/internal/query/query_functions/str_funcs.go
@@ -5,10 +5,12 @@
 package query_functions
 
 import (
+	"errors"
 	"strings"
 
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/conversions"
 	"v.io/syncbase/v23/syncbase/nosql/internal/query/query_parser"
+	"v.io/v23/vdl"
 )
 
 func lowerCase(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
@@ -26,3 +28,13 @@
 	}
 	return makeStrOp(off, strings.ToUpper(strOp.Str)), nil
 }
+
+func typeFunc(off int64, args []*query_parser.Operand) (*query_parser.Operand, error) {
+	// If operand is not an object, we can't get a type
+	if args[0].Type != query_parser.TypObject {
+		return nil, errors.New("Type function argument must be object.")
+	}
+	t := args[0].Object.Type()
+	pkg, name := vdl.SplitIdent(t.Name())
+	return makeStrOpWithAlt(off, pkg+"."+name, name), nil
+}
diff --git a/v23/syncbase/nosql/internal/query/query_parser/doc.go b/v23/syncbase/nosql/internal/query/query_parser/doc.go
index 915ac29..3676075 100644
--- a/v23/syncbase/nosql/internal/query/query_parser/doc.go
+++ b/v23/syncbase/nosql/internal/query/query_parser/doc.go
@@ -58,7 +58,6 @@
 // <operand> ::=
 //   K
 //   | V[<period><field>]
-//   | T
 //   | <literal>
 //   | <function>
 //
@@ -81,5 +80,5 @@
 //   | <float_literal>
 //
 // Example:
-// select v.foo.bar, v.baz[2] from foobarbaz where (v.foo = 42 and v.bar not like "abc%) or (k >= "100" and  k < "200")
+// select v.foo.bar, v.baz[2] from foobarbaz where Type(v) = "Customer" and (v.foo = 42 and v.bar not like "abc%) or (k >= "100" and  k < "200")
 package query_parser
diff --git a/v23/syncbase/nosql/internal/query/test/db_objects.vdl b/v23/syncbase/nosql/internal/query/test/db_objects.vdl
index 487f40e..a35dd1f 100644
--- a/v23/syncbase/nosql/internal/query/test/db_objects.vdl
+++ b/v23/syncbase/nosql/internal/query/test/db_objects.vdl
@@ -158,3 +158,7 @@
 	S    set[string]
 	T    set[time.Time]
 }
+
+type BigData struct {
+	Key string // A dup of the key stored in the value.
+}
diff --git a/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go b/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go
index a402510..5584378 100644
--- a/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go
+++ b/v23/syncbase/nosql/internal/query/test/db_objects.vdl.go
@@ -462,6 +462,15 @@
 }) {
 }
 
+type BigData struct {
+	Key string // A dup of the key stored in the value.
+}
+
+func (BigData) __VDLReflect(struct {
+	Name string `vdl:"v.io/syncbase/v23/syncbase/nosql/internal/query/test.BigData"`
+}) {
+}
+
 func init() {
 	vdl.Register((*AddressInfo)(nil))
 	vdl.Register((*CreditAgency)(nil))
@@ -485,4 +494,5 @@
 	vdl.Register((*FunWithMaps)(nil))
 	vdl.Register((*ManyMaps)(nil))
 	vdl.Register((*ManySets)(nil))
+	vdl.Register((*BigData)(nil))
 }
diff --git a/v23/syncbase/nosql/internal/query/test/query_test.go b/v23/syncbase/nosql/internal/query/test/query_test.go
index 8f24388..0d4cce7 100644
--- a/v23/syncbase/nosql/internal/query/test/query_test.go
+++ b/v23/syncbase/nosql/internal/query/test/query_test.go
@@ -121,6 +121,7 @@
 var previousAddressesTable table
 var manyMapsTable table
 var manySetsTable table
+var bigTable table
 
 type kv struct {
 	key   string
@@ -374,6 +375,15 @@
 		},
 	}
 	db.tables = append(db.tables, manySetsTable)
+
+	bigTable.name = "BigTable"
+
+	for i := 100; i < 301; i++ {
+		k := fmt.Sprintf("%d", i)
+		b := vdl.ValueOf(BigData{k})
+		bigTable.rows = append(bigTable.rows, kv{k, b})
+	}
+	db.tables = append(db.tables, bigTable)
 }
 
 type keyRangesTest struct {
@@ -436,7 +446,7 @@
 	basic := []execSelectTest{
 		{
 			// Select values for all customer records.
-			"select v from Customer where t = \"Customer\"",
+			"select v from Customer where Type(v) = \"Customer\"",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[0].value},
@@ -445,6 +455,96 @@
 			},
 		},
 		{
+			// Select values for all customer records.
+			"select v from Customer where Type(v) not like \"%Customer\"",
+			[]string{"v"},
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[1].value},
+				[]*vdl.Value{custTable.rows[2].value},
+				[]*vdl.Value{custTable.rows[3].value},
+				[]*vdl.Value{custTable.rows[5].value},
+				[]*vdl.Value{custTable.rows[6].value},
+				[]*vdl.Value{custTable.rows[7].value},
+				[]*vdl.Value{custTable.rows[8].value},
+			},
+		},
+		{
+			// Select values for all customer records.
+			"select Type(v) from Customer where Type(v) not like \"%Customer\"",
+			[]string{"Type"},
+			[][]*vdl.Value{
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+			},
+		},
+		{
+			// All customers have a v.Credit with type CreditReport.
+			"select v from Customer where Type(v.Credit) = \"CreditReport\"",
+			[]string{"v"},
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[0].value},
+				[]*vdl.Value{custTable.rows[4].value},
+				[]*vdl.Value{custTable.rows[9].value},
+			},
+		},
+		{
+			// Only customer "001" has an equifax report.
+			"select v from Customer where Type(v.Credit.Report.EquifaxReport) = \"EquifaxCreditReport\"",
+			[]string{"v"},
+			[][]*vdl.Value{
+				[]*vdl.Value{custTable.rows[0].value},
+			},
+		},
+		{
+			// Print the types of every record
+			"select Type(v) from Customer",
+			[]string{"Type"},
+			[][]*vdl.Value{
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Invoice")},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer")},
+			},
+		},
+		{
+			// Print the types of every credit report
+			"select Type(v.Credit.Report) from Customer",
+			[]string{"Type"},
+			[][]*vdl.Value{
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf(nil)},
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.AgencyReport")},
+			},
+		},
+		{
+			// Print the types of every cusomer's v.Credit.Report.EquifaxReport
+			"select Type(v.Credit.Report.EquifaxReport) from Customer where Type(v) = \"Customer\"",
+			[]string{"Type"},
+			[][]*vdl.Value{
+				[]*vdl.Value{vdl.ValueOf("v.io/syncbase/v23/syncbase/nosql/internal/query/test.EquifaxCreditReport")},
+				[]*vdl.Value{vdl.ValueOf(vdl.ValueOf(nil))},
+				[]*vdl.Value{vdl.ValueOf(vdl.ValueOf(nil))},
+			},
+		},
+		{
 			// Select values where v.InvoiceNum is nil
 			// Since InvoiceNum does not exist for Invoice,
 			// this will return just customers.
@@ -536,7 +636,7 @@
 		},
 		{
 			// Select keys & values for all customer records.
-			"select k, v from Customer where t = \"Customer\"",
+			"select k, v from Customer where \"Customer\" = Type(v)",
 			[]string{"k", "v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), custTable.rows[0].value},
@@ -546,7 +646,7 @@
 		},
 		{
 			// Select keys & names for all customer records.
-			"select k, v.Name from Customer where t = \"Customer\"",
+			"select k, v.Name from Customer where Type(v) = \"Customer\"",
 			[]string{"k", "v.Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[0].key), vdl.ValueOf("John Smith")},
@@ -575,7 +675,7 @@
 		},
 		{
 			// Select keys & values fo all invoice records.
-			"select k, v from Customer where t = \"Invoice\"",
+			"select k, v from Customer where Type(v) = \"Invoice\"",
 			[]string{"k", "v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[1].key), custTable.rows[1].value},
@@ -589,7 +689,7 @@
 		},
 		{
 			// Select key, cust id, invoice number and amount for $88 invoices.
-			"select k, v.CustId as ID, v.InvoiceNum as InvoiceNumber, v.Amount as Amt from Customer where t = \"Invoice\" and v.Amount = 88",
+			"select k, v.CustId as ID, v.InvoiceNum as InvoiceNumber, v.Amount as Amt from Customer where Type(v) = \"Invoice\" and v.Amount = 88",
 			[]string{"k", "ID", "InvoiceNumber", "Amt"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[3].key), vdl.ValueOf(int64(1)), vdl.ValueOf(int64(1005)), vdl.ValueOf(int64(88))},
@@ -717,7 +817,7 @@
 		},
 		{
 			// Select id, name for customers whose last name is Masterson.
-			"select v.Id as ID, v.Name as Name from Customer where t = \"Customer\" and v.Name like \"%Masterson\"",
+			"select v.Id as ID, v.Name as Name from Customer where Type(v) = \"Customer\" and v.Name like \"%Masterson\"",
 			[]string{"ID", "Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(int64(2)), vdl.ValueOf("Bat Masterson")},
@@ -725,7 +825,7 @@
 		},
 		{
 			// Select records where v.Address.City is "Collins" or type is Invoice.
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\"",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\"",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[1].value},
@@ -844,7 +944,7 @@
 		},
 		{
 			// Select customer name for customer Id (i.e., key) "001".
-			"select v.Name as Name from Customer where t = \"Customer\" and k = \"001\"",
+			"select v.Name as Name from Customer where Type(v) = \"Customer\" and k = \"001\"",
 			[]string{"Name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("John Smith")},
@@ -893,7 +993,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" limit 3",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[1].value},
@@ -904,7 +1004,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 5",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[6].value},
@@ -921,21 +1021,21 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 8",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		{
 			// Select records where v.Address.City = "Collins" or type is Invoice.
 			// Offset 23
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\" offset 23",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" offset 23",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		{
 			// Select records where v.Address.City = "Collins" is 84 or type is Invoice.
 			// Limit 3 Offset 2
-			"select v from Customer where v.Address.City = \"Collins\" or t = \"Invoice\" limit 3 offset 2",
+			"select v from Customer where v.Address.City = \"Collins\" or Type(v) = \"Invoice\" limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[3].value},
@@ -946,7 +1046,7 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or (Type(v) = \"Invoice\" and v.InvoiceNum is not nil) limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[3].value},
@@ -957,14 +1057,14 @@
 		{
 			// 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",
+			"select v from Customer where v.Address.City = \"Collins\" or (Type(v) = \"Invoice\" and v.InvoiceNum is nil) limit 3 offset 2",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
 		// Test functions.
 		{
 			// Select invoice records where date is 2015-03-17
-			"select v from Customer where t = \"Invoice\" and YMD(v.InvoiceDate, \"America/Los_Angeles\") = Date(\"2015-03-17 PDT\")",
+			"select v from Customer where Type(v) = \"Invoice\" and YMD(v.InvoiceDate, \"America/Los_Angeles\") = Date(\"2015-03-17 PDT\")",
 			[]string{"v"},
 			[][]*vdl.Value{
 				[]*vdl.Value{custTable.rows[5].value},
@@ -1060,7 +1160,7 @@
 		// Test string functions in where clause.
 		{
 			// Select invoices shipped to Any street -- using LowerCase.
-			"select k from Customer where t = \"Invoice\" and LowerCase(v.ShipTo.Street) like \"%any%\"",
+			"select k from Customer where Type(v) = \"Invoice\" and LowerCase(v.ShipTo.Street) like \"%any%\"",
 			[]string{"k"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
@@ -1071,7 +1171,7 @@
 		},
 		{
 			// Select invoices shipped to Any street -- using UpperCase.
-			"select k from Customer where t = \"Invoice\" and UpperCase(v.ShipTo.Street) like \"%ANY%\"",
+			"select k from Customer where Type(v) = \"Invoice\" and UpperCase(v.ShipTo.Street) like \"%ANY%\"",
 			[]string{"k"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(custTable.rows[5].key)},
@@ -1117,7 +1217,7 @@
 		},
 		// LowerCase function
 		{
-			"select LowerCase(v.Name) as name from Customer where t = \"Customer\"",
+			"select LowerCase(v.Name) as name from Customer where Type(v) = \"Customer\"",
 			[]string{"name"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("john smith")},
@@ -1127,7 +1227,7 @@
 		},
 		// UpperCase function
 		{
-			"select UpperCase(v.Name) as NAME from Customer where t = \"Customer\"",
+			"select UpperCase(v.Name) as NAME from Customer where Type(v) = \"Customer\"",
 			[]string{"NAME"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf("JOHN SMITH")},
@@ -1137,7 +1237,7 @@
 		},
 		// YMDHMS function
 		{
-			"select k, YMDHMS(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDHMS(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDHMS",
@@ -1148,7 +1248,7 @@
 		},
 		// YMDHM function
 		{
-			"select k, YMDHM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDHM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDHM",
@@ -1159,7 +1259,7 @@
 		},
 		// YMDH function
 		{
-			"select k, YMDH(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMDH(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMDH",
@@ -1170,7 +1270,7 @@
 		},
 		// YMD function
 		{
-			"select k, YMD(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YMD(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YMD",
@@ -1181,7 +1281,7 @@
 		},
 		// YM function
 		{
-			"select k, YM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"002003\"",
+			"select k, YM(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"002003\"",
 			[]string{
 				"k",
 				"YM",
@@ -1192,7 +1292,7 @@
 		},
 		// Y function
 		{
-			"select k, Y(v.InvoiceDate, \"America/Los_Angeles\") from Customer where t = \"Invoice\" and k = \"001001\"",
+			"select k, Y(v.InvoiceDate, \"America/Los_Angeles\") from Customer where Type(v) = \"Invoice\" and k = \"001001\"",
 			[]string{
 				"k",
 				"Y",
@@ -1203,7 +1303,7 @@
 		},
 		// Nested functions
 		{
-			"select Y(YM(YMD(YMDH(YMDHM(YMDHMS(v.InvoiceDate, \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\")  from Customer where t = \"Invoice\" and k = \"001001\"",
+			"select Y(YM(YMD(YMDH(YMDHM(YMDHMS(v.InvoiceDate, \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\"), \"America/Los_Angeles\")  from Customer where Type(v) = \"Invoice\" and k = \"001001\"",
 			[]string{"Y"},
 			[][]*vdl.Value{
 				[]*vdl.Value{vdl.ValueOf(t2015)},
@@ -1211,7 +1311,7 @@
 		},
 		// Bad arg to function.  Expression is false.
 		{
-			"select v from Customer where t = \"Invoice\" and YMD(v.InvoiceDate, v.Foo) = v.InvoiceDate",
+			"select v from Customer where Type(v) = \"Invoice\" and YMD(v.InvoiceDate, v.Foo) = v.InvoiceDate",
 			[]string{"v"},
 			[][]*vdl.Value{},
 		},
@@ -1465,6 +1565,318 @@
 				},
 			},
 		},
+		{
+			"select k, v.Key from BigTable where k < \"101\" or k = \"200\" or k like \"300%\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{svPair("100"), svPair("200"), svPair("300")},
+		},
+		{
+			"select k, v.Key from BigTable where \"101\" > k or \"200\" = k or k like \"300%\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{svPair("100"), svPair("200"), svPair("300")},
+		},
+		{
+			"select k, v.Key from BigTable where k is nil",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k is not nil and \"103\" = v.Key",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{svPair("103")},
+		},
+		{
+			"select k, v.Key from BigTable where k like \"10_\" or k like \"20_\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("100"),
+				svPair("101"),
+				svPair("102"),
+				svPair("103"),
+				svPair("104"),
+				svPair("105"),
+				svPair("106"),
+				svPair("107"),
+				svPair("108"),
+				svPair("109"),
+				svPair("200"),
+				svPair("201"),
+				svPair("202"),
+				svPair("203"),
+				svPair("204"),
+				svPair("205"),
+				svPair("206"),
+				svPair("207"),
+				svPair("208"),
+				svPair("209"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like \"_%9\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("109"),
+				svPair("119"),
+				svPair("129"),
+				svPair("139"),
+				svPair("149"),
+				svPair("159"),
+				svPair("169"),
+				svPair("179"),
+				svPair("189"),
+				svPair("199"),
+				svPair("209"),
+				svPair("219"),
+				svPair("229"),
+				svPair("239"),
+				svPair("249"),
+				svPair("259"),
+				svPair("269"),
+				svPair("279"),
+				svPair("289"),
+				svPair("299"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like \"__0\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("100"),
+				svPair("110"),
+				svPair("120"),
+				svPair("130"),
+				svPair("140"),
+				svPair("150"),
+				svPair("160"),
+				svPair("170"),
+				svPair("180"),
+				svPair("190"),
+				svPair("200"),
+				svPair("210"),
+				svPair("220"),
+				svPair("230"),
+				svPair("240"),
+				svPair("250"),
+				svPair("260"),
+				svPair("270"),
+				svPair("280"),
+				svPair("290"),
+				svPair("300"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like \"10%\" or  k like \"20%\" or  k like \"30%\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("100"),
+				svPair("101"),
+				svPair("102"),
+				svPair("103"),
+				svPair("104"),
+				svPair("105"),
+				svPair("106"),
+				svPair("107"),
+				svPair("108"),
+				svPair("109"),
+				svPair("200"),
+				svPair("201"),
+				svPair("202"),
+				svPair("203"),
+				svPair("204"),
+				svPair("205"),
+				svPair("206"),
+				svPair("207"),
+				svPair("208"),
+				svPair("209"),
+				svPair("300"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like \"1__\" and  k like \"_2_\" and  k like \"__3\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{svPair("123")},
+		},
+		{
+			"select k, v.Key from BigTable where (k >  \"100\" and k < \"103\") or (k > \"205\" and k < \"208\")",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("101"),
+				svPair("102"),
+				svPair("206"),
+				svPair("207"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where ( \"100\" < k and \"103\" > k) or (\"205\" < k and \"208\" > k)",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("101"),
+				svPair("102"),
+				svPair("206"),
+				svPair("207"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k <=  \"100\" or k = \"101\" or k >= \"300\" or (k <> \"299\" and k not like \"300\" and k >= \"298\")",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("100"),
+				svPair("101"),
+				svPair("298"),
+				svPair("300"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where \"100\" >= k or \"101\" = k or \"300\" <= k or (\"299\" <> k and k not like \"300\" and \"298\" <= k)",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("100"),
+				svPair("101"),
+				svPair("298"),
+				svPair("300"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like  \"1%\" and k like \"%9\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{
+				svPair("109"),
+				svPair("119"),
+				svPair("129"),
+				svPair("139"),
+				svPair("149"),
+				svPair("159"),
+				svPair("169"),
+				svPair("179"),
+				svPair("189"),
+				svPair("199"),
+			},
+		},
+		{
+			"select k, v.Key from BigTable where k like  \"3%\" and k like \"30%\" and k like \"300%\"",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{svPair("300")},
+		},
+		{
+			"select k, v.Key from BigTable where \"110\" > k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 109),
+		},
+		{
+			"select k, v.Key from BigTable where \"110\" < k and \"205\" > k",
+			[]string{"k", "v.Key"},
+			svPairs(111, 204),
+		},
+		{
+			"select k, v.Key from BigTable where \"110\" <= k and \"205\" >= k",
+			[]string{"k", "v.Key"},
+			svPairs(110, 205),
+		},
+		{
+			"select k, v.Key from BigTable where k is nil",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k is not nil",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where k <> k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k < k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k > k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k = k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where k <= k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where k >= k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where k = v.Key",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where v.Key = k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where V.Key = K",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where k <> v.key",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where v.key <> k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k < v.key",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where v.key < k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where k > v.key",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select k, v.Key from BigTable where v.key > k",
+			[]string{"k", "v.Key"},
+			[][]*vdl.Value{},
+		},
+		{
+			"select K, V.Key from BigTable where k >= v.Key",
+			[]string{"K", "V.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where v.Key >= k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select K, V.Key from BigTable where k <= v.Key",
+			[]string{"K", "V.Key"},
+			svPairs(100, 300),
+		},
+		{
+			"select k, v.Key from BigTable where v.Key <= k",
+			[]string{"k", "v.Key"},
+			svPairs(100, 300),
+		},
 	}
 
 	for _, test := range basic {
@@ -1487,6 +1899,21 @@
 	}
 }
 
+func svPair(s string) []*vdl.Value {
+	v := vdl.ValueOf(s)
+	return []*vdl.Value{v, v}
+}
+
+// Genearate k,v pairs for start to finish (*INCLUSIVE*)
+func svPairs(start, finish int64) [][]*vdl.Value {
+	retVal := [][]*vdl.Value{}
+	for i := start; i <= finish; i++ {
+		v := vdl.ValueOf(fmt.Sprintf("%d", i))
+		retVal = append(retVal, []*vdl.Value{v, v})
+	}
+	return retVal
+}
+
 // Use Now to verify it is "pre" executed such that all the rows
 // have the same time.
 func TestPreExecFunctions(t *testing.T) {
@@ -1584,7 +2011,7 @@
 		},
 		{
 			// All selected rows will have key prefix of "abc".
-			"select k, v from Customer where t = \"Foo.Bar\" and k like \"abc%\"",
+			"select k, v from Customer where Type(v) = \"Foo.Bar\" and k like \"abc%\"",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"abc", plusOne("abc")},
 			},
@@ -1592,7 +2019,7 @@
 		},
 		{
 			// Need all keys
-			"select k, v from Customer where t = \"Foo.Bar\" or k like \"abc%\"",
+			"select k, v from Customer where Type(v) = \"Foo.Bar\" or k like \"abc%\"",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"", ""},
 			},
@@ -1608,7 +2035,7 @@
 		},
 		{
 			// All selected rows will have key prefix of "foo".
-			"select k, v from Customer where t = \"Foo.Bar\" and k like \"foo_bar\"",
+			"select k, v from Customer where Type(v) = \"Foo.Bar\" and k like \"foo_bar\"",
 			&query_db.KeyRanges{
 				query_db.KeyRange{"foo", plusOne("foo")},
 			},
@@ -1778,7 +2205,7 @@
 		},
 		{
 			// 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\"",
+			"select k, v from Customer where k = \"xyz\" or Type(v) = \"foo.Bar\"",
 			"wxyz",
 			query.FETCH_VALUE,
 		},
@@ -1818,11 +2245,11 @@
 func TestEval(t *testing.T) {
 	basic := []evalTest{
 		{
-			"select k, v from Customer where t = \"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer\"",
+			"select k, v from Customer where Type(v) = \"v.io/syncbase/v23/syncbase/nosql/internal/query/test.Customer\"",
 			custTable.rows[0].key, custTable.rows[0].value, true,
 		},
 		{
-			"select k, v from Customer where t = \"Customer\"",
+			"select k, v from Customer where Type(v) = \"Customer\"",
 			numTable.rows[0].key, custTable.rows[0].value, true,
 		},
 		{
@@ -2057,7 +2484,7 @@
 func TestProjection(t *testing.T) {
 	basic := []projectionTest{
 		{
-			"select k, v from Customer where t = \"Customer\"",
+			"select k, v from Customer where Type(v) = \"Customer\"",
 			"123456", custTable.rows[0].value,
 			[]*vdl.Value{
 				vdl.ValueOf("123456"),
@@ -2065,7 +2492,7 @@
 			},
 		},
 		{
-			"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\"",
+			"select k, v, v.Name, v.Id, v.Active, v.Credit.Agency, v.Credit.Report.EquifaxReport.Rating, v.Address.Street, v.Address.City, v.Address.State, v.Address.Zip from Customer where Type(v) = \"Customer\"",
 			custTable.rows[0].key, custTable.rows[0].value,
 			[]*vdl.Value{
 				vdl.ValueOf(custTable.rows[0].key),
@@ -2111,7 +2538,7 @@
 func TestExecSelectSingleRow(t *testing.T) {
 	basic := []execSelectSingleRowTest{
 		{
-			"select k, v from Customer where t = \"Customer\"",
+			"select k, v from Customer where Type(v) = \"Customer\"",
 			"123456", custTable.rows[0].value,
 			[]*vdl.Value{
 				vdl.ValueOf("123456"),
@@ -2119,7 +2546,7 @@
 			},
 		},
 		{
-			"select k, v from Customer where t = \"Customer\" and k like \"123%\"",
+			"select k, v from Customer where Type(v) = \"Customer\" and k like \"123%\"",
 			"123456", custTable.rows[0].value,
 			[]*vdl.Value{
 				vdl.ValueOf("123456"),
@@ -2127,12 +2554,12 @@
 			},
 		},
 		{
-			"select k, v from Customer where t = \"Invoice\" and k like \"123%\"",
+			"select k, v from Customer where Type(v) = \"Invoice\" and k like \"123%\"",
 			"123456", custTable.rows[0].value,
 			[]*vdl.Value{},
 		},
 		{
-			"select k, v from Customer where t = \"Customer\" and k like \"456%\"",
+			"select k, v from Customer where Type(v) = \"Customer\" and k like \"456%\"",
 			"123456", custTable.rows[0].value,
 			[]*vdl.Value{},
 		},
@@ -2149,7 +2576,7 @@
 			[]*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\"",
+			"select k, v, v.Name, v.Id, v.Active, v.Credit.Report.EquifaxReport.Rating, v.Credit.Report.ExperianReport.Rating, v.Credit.Report.TransUnionReport.Rating, v.Address.Street, v.Address.City, v.Address.State, v.Address.Zip from Customer where Type(v) = \"Customer\"",
 			custTable.rows[0].key, custTable.rows[0].value,
 			[]*vdl.Value{
 				vdl.ValueOf(custTable.rows[0].key),
@@ -2210,6 +2637,14 @@
 			// The following error text is dependent on implementation of Database.
 			syncql.NewErrExpected(db.GetContext(), 30, "positive integer literal"),
 		},
+		{
+			"select k, v.Key from BigTable where 110 <= k and 205 >= k",
+			syncql.NewErrKeyExpressionLiteral(db.GetContext(), 36),
+		},
+		{
+			"select k, v.Key from BigTable where Type(k) = \"BigData\"",
+			syncql.NewErrArgMustBeField(db.GetContext(), 41),
+		},
 	}
 
 	for _, test := range basic {
@@ -2229,20 +2664,6 @@
 			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},
 					},
@@ -2276,7 +2697,7 @@
 	}
 
 	for _, test := range basic {
-		r, _, _ := query.ResolveField(db, test.k, test.v, &test.f)
+		r := query.ResolveField(db, test.k, test.v, &test.f)
 		if !reflect.DeepEqual(r, test.r) {
 			t.Errorf("got %v(%s), want %v(%s)", r, r.Type(), test.r, test.r.Type())
 		}
diff --git a/v23/syncbase/nosql/syncql/syncql.vdl b/v23/syncbase/nosql/syncql/syncql.vdl
index 75b58e2..f6267bf 100644
--- a/v23/syncbase/nosql/syncql/syncql.vdl
+++ b/v23/syncbase/nosql/syncql/syncql.vdl
@@ -7,7 +7,7 @@
 // SyncQL errors
 error (
 	BadFieldInWhere(off int64) {
-		"en": "[{off}]Where field must be 'k', 'v[{.<ident>}...]' or 't'.",
+		"en": "[{off}]Where field must be 'k' or 'v[{.<ident>}...]'.",
 	}
 	BoolInvalidExpression(off int64) {
 		"en": "[{off}]Boolean operands may only be used in equals and not equals expressions.",
@@ -21,9 +21,6 @@
 	DotNotationDisallowedForKey(off int64) {
 		"en": "[{off}]Dot notation may not be used on a key field.",
 	}
-	DotNotationDisallowedForType(off int64) {
-		"en": "[{off}]Dot notation may not be used with type.",
-	}
 	ErrorCompilingRegularExpression(off int64, regex string, err error) {
 		"en": "[{off}]The following error encountered compiling regex '{regex}': {err}",
 	}
@@ -54,8 +51,20 @@
 	FunctionNotFound(off int64, name string) {
 		"en": "[{off}]Function '{name}' not found.",
 	}
-	FunctionReturnedError(off int64, name string, err error) {
-		"en": "[{off}]Function '{name}' returned error: {err}.",
+	ArgMustBeField(off int64) {
+		"en": "[{off}]Argument must be a value field (i.e., must begin with 'v').",
+	}
+	TimeConversionError(off int64, err error) {
+		"en": "[{off}]Can't convert to time: {err}.",
+	}
+	LocationConversionError(off int64, err error) {
+		"en": "[{off}]Can't convert to location: {err}.",
+	}
+	StringConversionError(off int64, err error) {
+		"en": "[{off}]Can't convert to string: {err}.",
+	}
+	FloatConversionError(off int64, err error) {
+		"en": "[{off}]Can't convert to float: {err}.",
 	}
 	IsIsNotRequireLhsValue(off int64) {
 		"en": "[{off}]'Is/is not' expressions require left operand to be a value operand.",
@@ -70,8 +79,8 @@
 	InvalidSelectField(off int64) {
 		"en": "[{off}]Select field must be 'k' or 'v[{.<ident>}...]'.",
 	}
-	KeyExpressionForm(off int64) {
-		"en": "[{off}]Key (i.e., 'k') expressions must be of form 'k  [=|<>|>|>=|<|<=|like|not like] <string-literal>'.",
+	KeyExpressionLiteral(off int64) {
+		"en": "[{off}]Key (i.e., 'k') compares against literals must be string literal.",
 	}
 	KeyValueStreamError(off int64, err error) {
 		"en": "[{off}]KeyValueStream error: {err}.",
@@ -94,9 +103,6 @@
 	TableCantAccess(off int64, table string, err error) {
 		"en": "[{off}]Table {table} does not exist (or cannot be accessed): {err}.",
 	}
-	TypeExpressionForm(off int64) {
-		"en": "[{off}]Type expressions must be 't = <string-literal>'.",
-	}
 	Unexpected(off int64, found string) {
 		"en": "[{off}]Unexpected: {found}.",
 	}
diff --git a/v23/syncbase/nosql/syncql/syncql.vdl.go b/v23/syncbase/nosql/syncql/syncql.vdl.go
index 81531e6..778646d 100644
--- a/v23/syncbase/nosql/syncql/syncql.vdl.go
+++ b/v23/syncbase/nosql/syncql/syncql.vdl.go
@@ -15,12 +15,11 @@
 )
 
 var (
-	ErrBadFieldInWhere                 = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.BadFieldInWhere", verror.NoRetry, "{1:}{2:} [{3}]Where field must be 'k', 'v[{.<ident>}...]' or 't'.")
+	ErrBadFieldInWhere                 = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.BadFieldInWhere", verror.NoRetry, "{1:}{2:} [{3}]Where field must be 'k' or 'v[{.<ident>}...]'.")
 	ErrBoolInvalidExpression           = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.BoolInvalidExpression", verror.NoRetry, "{1:}{2:} [{3}]Boolean operands may only be used in equals and not equals expressions.")
 	ErrCheckOfUnknownStatementType     = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.CheckOfUnknownStatementType", verror.NoRetry, "{1:}{2:} [{3}]Cannot semantically check unknown statement type.")
 	ErrCouldNotConvert                 = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.CouldNotConvert", verror.NoRetry, "{1:}{2:} [{3}]Could not convert {4} to {5}.")
 	ErrDotNotationDisallowedForKey     = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.DotNotationDisallowedForKey", verror.NoRetry, "{1:}{2:} [{3}]Dot notation may not be used on a key field.")
-	ErrDotNotationDisallowedForType    = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.DotNotationDisallowedForType", verror.NoRetry, "{1:}{2:} [{3}]Dot notation may not be used with type.")
 	ErrErrorCompilingRegularExpression = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.ErrorCompilingRegularExpression", verror.NoRetry, "{1:}{2:} [{3}]The following error encountered compiling regex '{4}': {5}")
 	ErrExecOfUnknownStatementType      = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.ExecOfUnknownStatementType", verror.NoRetry, "{1:}{2:} [{3}]Cannot execute unknown statement type: {4}.")
 	ErrExpected                        = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.Expected", verror.NoRetry, "{1:}{2:} [{3}]Expected '{4}'.")
@@ -31,12 +30,16 @@
 	ErrFunctionArgCount                = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.FunctionArgCount", verror.NoRetry, "{1:}{2:} [{3}]Function '{4}' expects {5} args, found: {6}.")
 	ErrFunctionArgBad                  = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.FunctionArgBad", verror.NoRetry, "{1:}{2:} [{3}]Function '{4}' arg '{5}' could not be resolved.")
 	ErrFunctionNotFound                = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.FunctionNotFound", verror.NoRetry, "{1:}{2:} [{3}]Function '{4}' not found.")
-	ErrFunctionReturnedError           = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.FunctionReturnedError", verror.NoRetry, "{1:}{2:} [{3}]Function '{4}' returned error: {5}.")
+	ErrArgMustBeField                  = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.ArgMustBeField", verror.NoRetry, "{1:}{2:} [{3}]Argument must be a value field (i.e., must begin with 'v').")
+	ErrTimeConversionError             = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.TimeConversionError", verror.NoRetry, "{1:}{2:} [{3}]Can't convert to time: {4}.")
+	ErrLocationConversionError         = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.LocationConversionError", verror.NoRetry, "{1:}{2:} [{3}]Can't convert to location: {4}.")
+	ErrStringConversionError           = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.StringConversionError", verror.NoRetry, "{1:}{2:} [{3}]Can't convert to string: {4}.")
+	ErrFloatConversionError            = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.FloatConversionError", verror.NoRetry, "{1:}{2:} [{3}]Can't convert to float: {4}.")
 	ErrIsIsNotRequireLhsValue          = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.IsIsNotRequireLhsValue", verror.NoRetry, "{1:}{2:} [{3}]'Is/is not' expressions require left operand to be a value operand.")
 	ErrIsIsNotRequireRhsNil            = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.IsIsNotRequireRhsNil", verror.NoRetry, "{1:}{2:} [{3}]'Is/is not' expressions require right operand to be nil.")
 	ErrInvalidEscapedChar              = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.InvalidEscapedChar", verror.NoRetry, "{1:}{2:} [{3}Expected backslash, percent, or underscore after backslash.]")
 	ErrInvalidSelectField              = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.InvalidSelectField", verror.NoRetry, "{1:}{2:} [{3}]Select field must be 'k' or 'v[{.<ident>}...]'.")
-	ErrKeyExpressionForm               = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.KeyExpressionForm", verror.NoRetry, "{1:}{2:} [{3}]Key (i.e., 'k') expressions must be of form 'k  [=|<>|>|>=|<|<=|like|not like] <string-literal>'.")
+	ErrKeyExpressionLiteral            = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.KeyExpressionLiteral", verror.NoRetry, "{1:}{2:} [{3}]Key (i.e., 'k') compares against literals must be string literal.")
 	ErrKeyValueStreamError             = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.KeyValueStreamError", verror.NoRetry, "{1:}{2:} [{3}]KeyValueStream error: {4}.")
 	ErrLikeExpressionsRequireRhsString = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.LikeExpressionsRequireRhsString", verror.NoRetry, "{1:}{2:} [{3}]Like expressions require right operand of type <string-literal>.")
 	ErrLimitMustBeGe0                  = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.LimitMustBeGe0", verror.NoRetry, "{1:}{2:} [{3}]Limit must be > 0.")
@@ -44,19 +47,17 @@
 	ErrOffsetMustBeGe0                 = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.OffsetMustBeGe0", verror.NoRetry, "{1:}{2:} [{3}]Offset must be > 0.")
 	ErrScanError                       = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.ScanError", verror.NoRetry, "{1:}{2:} [{3}]Scan error: {4}.")
 	ErrTableCantAccess                 = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.TableCantAccess", verror.NoRetry, "{1:}{2:} [{3}]Table {4} does not exist (or cannot be accessed): {5}.")
-	ErrTypeExpressionForm              = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.TypeExpressionForm", verror.NoRetry, "{1:}{2:} [{3}]Type expressions must be 't = <string-literal>'.")
 	ErrUnexpected                      = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.Unexpected", verror.NoRetry, "{1:}{2:} [{3}]Unexpected: {4}.")
 	ErrUnexpectedEndOfStatement        = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.UnexpectedEndOfStatement", verror.NoRetry, "{1:}{2:} [{3}]No statement found.")
 	ErrUnknownIdentifier               = verror.Register("v.io/syncbase/v23/syncbase/nosql/syncql.UnknownIdentifier", verror.NoRetry, "{1:}{2:} [{3}]Uknown identifier: {4}.")
 )
 
 func init() {
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrBadFieldInWhere.ID), "{1:}{2:} [{3}]Where field must be 'k', 'v[{.<ident>}...]' or 't'.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrBadFieldInWhere.ID), "{1:}{2:} [{3}]Where field must be 'k' or 'v[{.<ident>}...]'.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrBoolInvalidExpression.ID), "{1:}{2:} [{3}]Boolean operands may only be used in equals and not equals expressions.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrCheckOfUnknownStatementType.ID), "{1:}{2:} [{3}]Cannot semantically check unknown statement type.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrCouldNotConvert.ID), "{1:}{2:} [{3}]Could not convert {4} to {5}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrDotNotationDisallowedForKey.ID), "{1:}{2:} [{3}]Dot notation may not be used on a key field.")
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrDotNotationDisallowedForType.ID), "{1:}{2:} [{3}]Dot notation may not be used with type.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrErrorCompilingRegularExpression.ID), "{1:}{2:} [{3}]The following error encountered compiling regex '{4}': {5}")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrExecOfUnknownStatementType.ID), "{1:}{2:} [{3}]Cannot execute unknown statement type: {4}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrExpected.ID), "{1:}{2:} [{3}]Expected '{4}'.")
@@ -67,12 +68,16 @@
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrFunctionArgCount.ID), "{1:}{2:} [{3}]Function '{4}' expects {5} args, found: {6}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrFunctionArgBad.ID), "{1:}{2:} [{3}]Function '{4}' arg '{5}' could not be resolved.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrFunctionNotFound.ID), "{1:}{2:} [{3}]Function '{4}' not found.")
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrFunctionReturnedError.ID), "{1:}{2:} [{3}]Function '{4}' returned error: {5}.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrArgMustBeField.ID), "{1:}{2:} [{3}]Argument must be a value field (i.e., must begin with 'v').")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrTimeConversionError.ID), "{1:}{2:} [{3}]Can't convert to time: {4}.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrLocationConversionError.ID), "{1:}{2:} [{3}]Can't convert to location: {4}.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrStringConversionError.ID), "{1:}{2:} [{3}]Can't convert to string: {4}.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrFloatConversionError.ID), "{1:}{2:} [{3}]Can't convert to float: {4}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrIsIsNotRequireLhsValue.ID), "{1:}{2:} [{3}]'Is/is not' expressions require left operand to be a value operand.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrIsIsNotRequireRhsNil.ID), "{1:}{2:} [{3}]'Is/is not' expressions require right operand to be nil.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrInvalidEscapedChar.ID), "{1:}{2:} [{3}Expected backslash, percent, or underscore after backslash.]")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrInvalidSelectField.ID), "{1:}{2:} [{3}]Select field must be 'k' or 'v[{.<ident>}...]'.")
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrKeyExpressionForm.ID), "{1:}{2:} [{3}]Key (i.e., 'k') expressions must be of form 'k  [=|<>|>|>=|<|<=|like|not like] <string-literal>'.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrKeyExpressionLiteral.ID), "{1:}{2:} [{3}]Key (i.e., 'k') compares against literals must be string literal.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrKeyValueStreamError.ID), "{1:}{2:} [{3}]KeyValueStream error: {4}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrLikeExpressionsRequireRhsString.ID), "{1:}{2:} [{3}]Like expressions require right operand of type <string-literal>.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrLimitMustBeGe0.ID), "{1:}{2:} [{3}]Limit must be > 0.")
@@ -80,7 +85,6 @@
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrOffsetMustBeGe0.ID), "{1:}{2:} [{3}]Offset must be > 0.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrScanError.ID), "{1:}{2:} [{3}]Scan error: {4}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrTableCantAccess.ID), "{1:}{2:} [{3}]Table {4} does not exist (or cannot be accessed): {5}.")
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrTypeExpressionForm.ID), "{1:}{2:} [{3}]Type expressions must be 't = <string-literal>'.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUnexpected.ID), "{1:}{2:} [{3}]Unexpected: {4}.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUnexpectedEndOfStatement.ID), "{1:}{2:} [{3}]No statement found.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUnknownIdentifier.ID), "{1:}{2:} [{3}]Uknown identifier: {4}.")
@@ -111,11 +115,6 @@
 	return verror.New(ErrDotNotationDisallowedForKey, ctx, off)
 }
 
-// NewErrDotNotationDisallowedForType returns an error with the ErrDotNotationDisallowedForType ID.
-func NewErrDotNotationDisallowedForType(ctx *context.T, off int64) error {
-	return verror.New(ErrDotNotationDisallowedForType, ctx, off)
-}
-
 // NewErrErrorCompilingRegularExpression returns an error with the ErrErrorCompilingRegularExpression ID.
 func NewErrErrorCompilingRegularExpression(ctx *context.T, off int64, regex string, err error) error {
 	return verror.New(ErrErrorCompilingRegularExpression, ctx, off, regex, err)
@@ -166,9 +165,29 @@
 	return verror.New(ErrFunctionNotFound, ctx, off, name)
 }
 
-// NewErrFunctionReturnedError returns an error with the ErrFunctionReturnedError ID.
-func NewErrFunctionReturnedError(ctx *context.T, off int64, name string, err error) error {
-	return verror.New(ErrFunctionReturnedError, ctx, off, name, err)
+// NewErrArgMustBeField returns an error with the ErrArgMustBeField ID.
+func NewErrArgMustBeField(ctx *context.T, off int64) error {
+	return verror.New(ErrArgMustBeField, ctx, off)
+}
+
+// NewErrTimeConversionError returns an error with the ErrTimeConversionError ID.
+func NewErrTimeConversionError(ctx *context.T, off int64, err error) error {
+	return verror.New(ErrTimeConversionError, ctx, off, err)
+}
+
+// NewErrLocationConversionError returns an error with the ErrLocationConversionError ID.
+func NewErrLocationConversionError(ctx *context.T, off int64, err error) error {
+	return verror.New(ErrLocationConversionError, ctx, off, err)
+}
+
+// NewErrStringConversionError returns an error with the ErrStringConversionError ID.
+func NewErrStringConversionError(ctx *context.T, off int64, err error) error {
+	return verror.New(ErrStringConversionError, ctx, off, err)
+}
+
+// NewErrFloatConversionError returns an error with the ErrFloatConversionError ID.
+func NewErrFloatConversionError(ctx *context.T, off int64, err error) error {
+	return verror.New(ErrFloatConversionError, ctx, off, err)
 }
 
 // NewErrIsIsNotRequireLhsValue returns an error with the ErrIsIsNotRequireLhsValue ID.
@@ -191,9 +210,9 @@
 	return verror.New(ErrInvalidSelectField, ctx, off)
 }
 
-// NewErrKeyExpressionForm returns an error with the ErrKeyExpressionForm ID.
-func NewErrKeyExpressionForm(ctx *context.T, off int64) error {
-	return verror.New(ErrKeyExpressionForm, ctx, off)
+// NewErrKeyExpressionLiteral returns an error with the ErrKeyExpressionLiteral ID.
+func NewErrKeyExpressionLiteral(ctx *context.T, off int64) error {
+	return verror.New(ErrKeyExpressionLiteral, ctx, off)
 }
 
 // NewErrKeyValueStreamError returns an error with the ErrKeyValueStreamError ID.
@@ -231,11 +250,6 @@
 	return verror.New(ErrTableCantAccess, ctx, off, table, err)
 }
 
-// NewErrTypeExpressionForm returns an error with the ErrTypeExpressionForm ID.
-func NewErrTypeExpressionForm(ctx *context.T, off int64) error {
-	return verror.New(ErrTypeExpressionForm, ctx, off)
-}
-
 // NewErrUnexpected returns an error with the ErrUnexpected ID.
 func NewErrUnexpected(ctx *context.T, off int64, found string) error {
 	return verror.New(ErrUnexpected, ctx, off, found)
diff --git a/x/ref/syncbase/sb51/doc.go b/x/ref/syncbase/sb51/doc.go
index 73609c1..0cd9c36 100644
--- a/x/ref/syncbase/sb51/doc.go
+++ b/x/ref/syncbase/sb51/doc.go
@@ -25,11 +25,11 @@
 // Sample run (assuming a syncbase service is mounted at '/:8101/syncbase',
 // otherwise specify using -service flag):
 //     > $V23_ROOT/roadmap/go/bin/sb51 sh -create-missing -make-demo -format=csv demoapp demodb
-//     ? select v.Name, v.Address.State from DemoCustomers where t = "Customer";
+//     ? select v.Name, v.Address.State from DemoCustomers where Type(v) = "Customer";
 //     v.Name,v.Address.State
 //     John Smith,CA
 //     Bat Masterson,IA
-//     ? select v.CustId, v.InvoiceNum, v.ShipTo.Zip, v.Amount from DemoCustomers where t = "Invoice" and v.Amount > 100;
+//     ? select v.CustId, v.InvoiceNum, v.ShipTo.Zip, v.Amount from DemoCustomers where Type(v) = "Invoice" and v.Amount > 100;
 //     v.CustId,v.InvoiceNum,v.ShipTo.Zip,v.Amount
 //     2,1001,50055,166
 //     2,1002,50055,243