syncbase: query: Changes per kash comments on 10211, 10512, 10904.

Change-Id: I015f491811f6f682241591b65576d3950a74d746
diff --git a/v23/syncbase/nosql/internal/query/demo/demo.go b/v23/syncbase/nosql/internal/query/demo/demo.go
index 2cbb085..963a00d 100644
--- a/v23/syncbase/nosql/internal/query/demo/demo.go
+++ b/v23/syncbase/nosql/internal/query/demo/demo.go
@@ -2,50 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This demo program exercises the syncbase query language.
-// The program's in-memory database implements the following
-// interfaces in query_db:
-//     Database
-//     Table
-//     KeyValueStream
-//
-// The user can enter the following at the command line:
-//     1. dump - to get a dump of the database
-//     2. a syncbase select statement - which is executed and results printed to stdout
-//     3. exit (or empty line) - to exit the program
-//
-// To build example:
-//     v23 go install v.io/syncbase/v23/syncbase/nosql/internal/query/demo
-//
-// To run example:
-//     $V23_ROOT/roadmap/go/bin/demo
-//
-// Sample run:
-//     > $V23_ROOT/roadmap/go/bin/demo
-//     Enter query (or 'dump' or 'exit')? select v.Name, v.Address.State from Customer where t = "Customer"
-//     John Smith,CA
-//     Bat Masterson,IA
-//     Enter query (or 'dump' or 'exit')? select v.CustID, v.InvoiceNum, v.ShipTo.Zip, v.Amount from Customer where t = "Invoice" and v.Amount > 100
-//     2,1001,50055,166
-//     2,1002,50055,243
-//     2,1004,50055,787
-//     Enter query (or 'dump' or 'exit')? select k, v fro Customer
-//     select k, v fro Customer
-//                 ^
-//     Error: [Off:12] Expected 'from', found 'fro'
-//     Enter query (or 'dump' or 'exit')? select k, v from Customer
-//     001,{John Smith 1 true 65 {1 Main St. Palo Alto CA 94303}
-//     001001,{1 1000 42 {1 Main St. Palo Alto CA 94303}}
-//     001002,{1 1003 7 {2 Main St. Palo Alto CA 94303}}
-//     001003,{1 1005 88 {3 Main St. Palo Alto CA 94303}}
-//     002,{Bat Masterson 2 true 66 {777 Any St. Collins IA 50055}
-//     002001,{2 1001 166 {777 Any St. collins IA 50055}}
-//     002002,{2 1002 243 {888 Any St. collins IA 50055}}
-//     002003,{2 1004 787 {999 Any St. collins IA 50055}}
-//     002004,{2 1006 88 {101010 Any St. collins IA 50055}}
-//     exit
-//     >
-//
 package main
 
 import (
diff --git a/v23/syncbase/nosql/internal/query/demo/doc.go b/v23/syncbase/nosql/internal/query/demo/doc.go
new file mode 100644
index 0000000..28c7fba
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/demo/doc.go
@@ -0,0 +1,48 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This demo program exercises the syncbase query language.
+// The program's in-memory database implements the following
+// interfaces in query_db:
+//     Database
+//     Table
+//     KeyValueStream
+//
+// The user can enter the following at the command line:
+//     1. dump - to get a dump of the database
+//     2. a syncbase select statement - which is executed and results printed to stdout
+//     3. exit (or empty line) - to exit the program
+//
+// To build example:
+//     v23 go install v.io/syncbase/v23/syncbase/nosql/internal/query/demo
+//
+// To run example:
+//     $V23_ROOT/roadmap/go/bin/demo
+//
+// Sample run:
+//     > $V23_ROOT/roadmap/go/bin/demo
+//     Enter query (or 'dump' or 'exit')? select v.Name, v.Address.State from Customer where t = "Customer"
+//     John Smith,CA
+//     Bat Masterson,IA
+//     Enter query (or 'dump' or 'exit')? select v.CustID, v.InvoiceNum, v.ShipTo.Zip, v.Amount from Customer where t = "Invoice" and v.Amount > 100
+//     2,1001,50055,166
+//     2,1002,50055,243
+//     2,1004,50055,787
+//     Enter query (or 'dump' or 'exit')? select k, v fro Customer
+//     select k, v fro Customer
+//                 ^
+//     Error: [Off:12] Expected 'from', found 'fro'
+//     Enter query (or 'dump' or 'exit')? select k, v from Customer
+//     001,{John Smith 1 true 65 {1 Main St. Palo Alto CA 94303}
+//     001001,{1 1000 42 {1 Main St. Palo Alto CA 94303}}
+//     001002,{1 1003 7 {2 Main St. Palo Alto CA 94303}}
+//     001003,{1 1005 88 {3 Main St. Palo Alto CA 94303}}
+//     002,{Bat Masterson 2 true 66 {777 Any St. Collins IA 50055}
+//     002001,{2 1001 166 {777 Any St. collins IA 50055}}
+//     002002,{2 1002 243 {888 Any St. collins IA 50055}}
+//     002003,{2 1004 787 {999 Any St. collins IA 50055}}
+//     002004,{2 1006 88 {101010 Any St. collins IA 50055}}
+//     exit
+//     >
+package main
diff --git a/v23/syncbase/nosql/internal/query/doc.go b/v23/syncbase/nosql/internal/query/doc.go
new file mode 100644
index 0000000..e4b73fa
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/doc.go
@@ -0,0 +1,6 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package query performs SQL-like select queries on the Syncbase NoSQL database.
+package query
diff --git a/v23/syncbase/nosql/internal/query/eval.go b/v23/syncbase/nosql/internal/query/eval.go
index 56b31ce..e14cee7 100644
--- a/v23/syncbase/nosql/internal/query/eval.go
+++ b/v23/syncbase/nosql/internal/query/eval.go
@@ -1,6 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+
 package query
 
 import (
@@ -26,8 +27,11 @@
 	switch e.Operator.Type {
 	case query_parser.And:
 		return Eval(k, v, e.Operand1.Expr) && Eval(k, v, e.Operand2.Expr)
-	default: // query_parser.Or
+	case query_parser.Or:
 		return Eval(k, v, e.Operand1.Expr) || Eval(k, v, e.Operand2.Expr)
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -129,7 +133,7 @@
 	}
 	// Must be the same at this point.
 	if lhsValue.Type != rhsValue.Type {
-		return nil, nil, errors.New(fmt.Sprintf("Logic error: expeced like types, got: %v, %v", lhsValue, rhsValue))
+		return nil, nil, errors.New(fmt.Sprintf("Logic error: expected like types, got: %v, %v", lhsValue, rhsValue))
 	}
 
 	return lhsValue, rhsValue, nil
@@ -158,8 +162,11 @@
 		c.CompRegex = o.CompRegex // non-nil for rhs of like expressions
 	case query_parser.TypUint:
 		c.Str = strconv.FormatUint(o.Uint, 10)
-	default: // query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to string for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to string for comparison.")
 	}
 	return &c, nil
 }
@@ -186,8 +193,11 @@
 		bi.SetUint64(o.Uint)
 		var br big.Rat
 		c.BigRat = br.SetInt(&bi)
-	default: // query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to big.Rat for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to big.Rat for comparison.")
 	}
 	return &c, nil
 }
@@ -205,8 +215,11 @@
 		c.Float = float64(o.Int)
 	case query_parser.TypUint:
 		c.Float = float64(o.Uint)
-	default: // query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to float64 for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to float64 for comparison.")
 	}
 	return &c, nil
 }
@@ -226,8 +239,11 @@
 		var b big.Int
 		b.SetUint64(o.Uint)
 		c.BigInt = &b
-	default: // case query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to big.Int for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to big.Int for comparison.")
 	}
 	return &c, nil
 }
@@ -241,8 +257,11 @@
 		return nil, errors.New("Cannot convert bool to int64 for comparison.")
 	case query_parser.TypInt:
 		c.Int = o.Int
-	default: //case query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to int64 for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to int64 for comparison.")
 	}
 	return &c, nil
 }
@@ -256,8 +275,11 @@
 		return nil, errors.New("Cannot convert bool to int64 for comparison.")
 	case query_parser.TypUint:
 		c.Uint = o.Uint
-	default: //case query_parser.TypObject
+	case query_parser.TypObject:
 		return nil, errors.New("Cannot convert object to int64 for comparison.")
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return nil, errors.New("Cannot convert operand to int64 for comparison.")
 	}
 	return &c, nil
 }
@@ -266,8 +288,11 @@
 	switch oper.Type {
 	case query_parser.Equal:
 		return lhsValue.Bool == rhsValue.Bool
-	default: // query_parser.NotEqual
+	case query_parser.NotEqual:
 		return lhsValue.Bool != rhsValue.Bool
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -283,8 +308,11 @@
 		return lhsValue.BigInt.Cmp(rhsValue.BigInt) <= 0
 	case query_parser.GreaterThan:
 		return lhsValue.BigInt.Cmp(rhsValue.BigInt) > 0
-	default: // case query_parser.GreaterThanOrEqual
+	case query_parser.GreaterThanOrEqual:
 		return lhsValue.BigInt.Cmp(rhsValue.BigInt) >= 0
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -300,8 +328,11 @@
 		return lhsValue.BigRat.Cmp(rhsValue.BigRat) <= 0
 	case query_parser.GreaterThan:
 		return lhsValue.BigRat.Cmp(rhsValue.BigRat) > 0
-	default: // case query_parser.GreaterThanOrEqual
+	case query_parser.GreaterThanOrEqual:
 		return lhsValue.BigRat.Cmp(rhsValue.BigRat) >= 0
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -317,8 +348,11 @@
 		return lhsValue.Float <= rhsValue.Float
 	case query_parser.GreaterThan:
 		return lhsValue.Float > rhsValue.Float
-	default: // case query_parser.GreaterThanOrEqual
+	case query_parser.GreaterThanOrEqual:
 		return lhsValue.Float >= rhsValue.Float
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -334,8 +368,11 @@
 		return lhsValue.Int <= rhsValue.Int
 	case query_parser.GreaterThan:
 		return lhsValue.Int > rhsValue.Int
-	default: // case query_parser.GreaterThanOrEqual
+	case query_parser.GreaterThanOrEqual:
 		return lhsValue.Int >= rhsValue.Int
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -351,8 +388,11 @@
 		return lhsValue.Uint <= rhsValue.Uint
 	case query_parser.GreaterThan:
 		return lhsValue.Uint > rhsValue.Uint
-	default: // case query_parser.GreaterThanOrEqual
+	case query_parser.GreaterThanOrEqual:
 		return lhsValue.Uint >= rhsValue.Uint
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -378,8 +418,11 @@
 		return lhsValue.Str >= rhsValue.Str
 	case query_parser.Like:
 		return rhsValue.CompRegex.MatchString(lhsValue.Str)
-	default: // query_parser.NotLike:
+	case query_parser.NotLike:
 		return !rhsValue.CompRegex.MatchString(lhsValue.Str)
+	default:
+		// TODO(jkline): Log this logic error and all other similar cases.
+		return false
 	}
 }
 
@@ -487,8 +530,7 @@
 			return reflect.ValueOf(v).Type().PkgPath() + "." + name, true, name
 		}
 	}
-	var object interface{}
-	object = v
+	object := v
 	segments := f.Segments
 	// The first segment will always be v itself, skip it.
 	for i := 1; i < len(segments); i++ {
@@ -527,60 +569,66 @@
 	}
 }
 
+// EvalWhereUsingOnlyKey return type.  See that function for details.
+type EvalWithKeyResult int
+
+const (
+	INCLUDE EvalWithKeyResult = iota
+	EXCLUDE
+	FETCH_VALUE
+)
+
 // Evaluate the where clause to determine if the row should be selected, but do so using only
 // the key.  Possible returns are:
-// true: the row should included in the results
-// false: the row should NOT be included
-// error: the value and/or type of the value are required to determine if row should be included.
+// 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, true is returned.
-// If the result is false, but no other experssions (i.e., expressions which refer to the type
-// of the value or the value itself) were encountered, false is returned; else, an error is
+// 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.
-func EvalWhereUsingOnlyKey(s *query_parser.SelectStatement, k string) (bool, error) {
+func EvalWhereUsingOnlyKey(s *query_parser.SelectStatement, k string) EvalWithKeyResult {
 	if s.Where == nil { // all rows will be in result
-		return true, nil
+		return INCLUDE
 	}
 	return evalExprUsingOnlyKey(s.Where.Expr, k)
 }
 
-func evalExprUsingOnlyKey(e *query_parser.Expression, k string) (bool, error) {
+func evalExprUsingOnlyKey(e *query_parser.Expression, k string) EvalWithKeyResult {
 	switch e.Operator.Type {
 	case query_parser.And:
-		op1Result, err1 := evalExprUsingOnlyKey(e.Operand1.Expr, k)
-		op2Result, err2 := evalExprUsingOnlyKey(e.Operand2.Expr, k)
-		if op1Result && op2Result {
-			return true, nil
-		} else if (op1Result == false && err1 == nil) || (op2Result == false && err2 == nil) {
-			// One of the operands evaluated to false with no error.
+		op1Result := evalExprUsingOnlyKey(e.Operand1.Expr, k)
+		op2Result := evalExprUsingOnlyKey(e.Operand2.Expr, k)
+		if op1Result == INCLUDE && op2Result == INCLUDE {
+			return INCLUDE
+		} else if op1Result == EXCLUDE || op2Result == EXCLUDE {
+			// One of the operands evaluated to EXCLUDE.
 			// As such, the value is not needed to reject the row.
-			return false, nil
+			return EXCLUDE
 		} else {
-			if err1 != nil {
-				return false, err1
-			} else {
-				return false, err2
-			}
+			return FETCH_VALUE
 		}
 	case query_parser.Or:
-		op1Result, err1 := evalExprUsingOnlyKey(e.Operand1.Expr, k)
-		op2Result, err2 := evalExprUsingOnlyKey(e.Operand2.Expr, k)
-		if op1Result || op2Result {
-			return true, nil
+		op1Result := evalExprUsingOnlyKey(e.Operand1.Expr, k)
+		op2Result := evalExprUsingOnlyKey(e.Operand2.Expr, k)
+		if op1Result == INCLUDE || op2Result == INCLUDE {
+			return INCLUDE
+		} else if op1Result == EXCLUDE && op2Result == EXCLUDE {
+			return EXCLUDE
 		} else {
-			if err1 != nil {
-				return false, err1
-			} else {
-				return false, err2 // err2 may or may not be nil
-			}
+			return FETCH_VALUE
 		}
 	default: // =, > >=, <, <=, Like, <>, NotLike
 		if !query_checker.IsKey(e.Operand1) {
-			// Non-key expressions are evaluated as false.
-			return false, errors.New("Value required for answer.") // err text not used
+			return FETCH_VALUE
 		} else {
-			return evalComparisonOperators(k, nil, e), nil
+			if evalComparisonOperators(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 a4c563d..a6c1c99 100644
--- a/v23/syncbase/nosql/internal/query/query.go
+++ b/v23/syncbase/nosql/internal/query/query.go
@@ -1,11 +1,6 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-//
-// Package query performs SQL-like select queries on the Syncbase NoSQL database.
-//
-// Note: Presently, the query package is deliberately not depending on other parts of syncbase.
-// This will change at a future date.
 
 package query
 
@@ -115,21 +110,19 @@
 		return false
 	}
 	for rs.keyValueStream.Advance() {
-		if err := rs.keyValueStream.Err(); err != nil {
-			rs.err = Error(rs.selectStatement.Off, err.Error())
-			return false
-		}
 		k, v := rs.keyValueStream.KeyValue()
-		if err := rs.keyValueStream.Err(); err != nil {
-			rs.err = Error(rs.selectStatement.Off, err.Error())
-			return false
-		}
 		// EvalWhereUsingOnlyKey
-		// true: the row should included in the results
-		// false: the row should NOT be included
-		// error: the value and/or type of the value are required to determine...
-		match, err := EvalWhereUsingOnlyKey(rs.selectStatement, k)
-		if err != nil {
+		// INCLUDE: the row should be included in the results
+		// EXCLUDE: the row should NOT be included
+		// FETCH_VALUE: the value and/or type of the value are required to make determination.
+		rv := EvalWhereUsingOnlyKey(rs.selectStatement, k)
+		var match bool
+		switch rv {
+		case INCLUDE:
+			match = true
+		case EXCLUDE:
+			match = false
+		case FETCH_VALUE:
 			match = Eval(k, v, rs.selectStatement.Where.Expr)
 		}
 		if match {
@@ -143,6 +136,9 @@
 			}
 		}
 	}
+	if err := rs.keyValueStream.Err(); err != nil {
+		rs.err = Error(rs.selectStatement.Off, err.Error())
+	}
 	return false
 }
 
diff --git a/v23/syncbase/nosql/internal/query/query_checker/doc.go b/v23/syncbase/nosql/internal/query/query_checker/doc.go
new file mode 100644
index 0000000..7dc7039
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/query_checker/doc.go
@@ -0,0 +1,15 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package query_checker performs a semantic check on an AST produced
+// by the query_parser package.
+//
+// For the foreseeasble future, only SelectStatements are supported.
+// The following clauses are checked sequentially,
+// SelectClause
+// FromClause
+// WhereClause (optional)
+// LimitClause (optional)
+// ResultsOffsetClause (optional)
+package query_checker
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 3c7e4d5..fb1ba20 100644
--- a/v23/syncbase/nosql/internal/query/query_checker/query_checker.go
+++ b/v23/syncbase/nosql/internal/query/query_checker/query_checker.go
@@ -1,17 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-//
-// Package query_checker performs a semantic check on an AST produced
-// by the query_parser package.
-//
-// For the foreseeasble future, only SelectStatements are supported.
-// The following clauses are checked sequentially,
-// SelectClause
-// FromClause
-// WhereClause (optional)
-// LimitClause (optional)
-// ResultsOffsetClause (optional)
+
 package query_checker
 
 import (
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 8a1bcf5..b819c9d 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
@@ -1,6 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+
 package query_checker_test
 
 import (
@@ -44,9 +45,6 @@
 
 var db mockDB
 
-func TestCreate(t *testing.T) {
-}
-
 type checkSelectTest struct {
 	query string
 }
diff --git a/v23/syncbase/nosql/internal/query/query_db/doc.go b/v23/syncbase/nosql/internal/query/query_db/doc.go
new file mode 100644
index 0000000..2c5b2ed
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/query_db/doc.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package query_db defines the interfaces a consumer of the query package would need to
+// implement.
+//
+// The Database interface is used to get Table interfaces (by name).
+// The Table interface is used to get a KeyValueStream (by key prefixes).
+// The KeyValueStream is used to consume key value pairs that match the prefixes.
+package query_db
diff --git a/v23/syncbase/nosql/internal/query/query_db/query_db.go b/v23/syncbase/nosql/internal/query/query_db/query_db.go
index a019ad4..10e5ec0 100644
--- a/v23/syncbase/nosql/internal/query/query_db/query_db.go
+++ b/v23/syncbase/nosql/internal/query/query_db/query_db.go
@@ -1,14 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-//
-// Package query_db defines the interfaces a consumer of the query package would need to
-// implement.
-//
-// The Database interface is used to get Table interfaces (by name).
-// The Table interface is used to get a KeyValueStream (by key prefixes).
-// The KeyValueStream is used to consume key value pairs that match the prefixes.
-//
+
 package query_db
 
 type Database interface {
@@ -23,13 +16,31 @@
 	Scan(prefixes []string) (KeyValueStream, error)
 }
 
-// If Advance() returns true, KeyValue() will return the first/next
-// key value pair.  If not advanced through the whole stream (i.e.,
-// until Advance() returns false), Cancel() should be called.
-// Err should be checked after every call to Advance().
 type KeyValueStream interface {
+	// Advance stages an element so the client can retrieve it
+	// with KeyValue.  Advance returns true iff there is an
+	// element to retrieve.  The client must call Advance before
+	// calling KeyValue.  The client must call Cancel if it does
+	// not iterate through all elements (i.e. until Advance
+	// returns false).  Advance may block if an element is not
+	// immediately available.
 	Advance() bool
+
+	// KeyValue returns the element that was staged by Advance.
+	// KeyValue may panic if Advance returned false or was not
+	// called at all.  KeyValue does not block.
 	KeyValue() (string, interface{})
+
+	// Err returns a non-nil error iff the stream encountered
+	// any errors.  Err does not block.
 	Err() error
+
+	// Cancel notifies the stream provider that it can stop
+	// producing elements.  The client must call Cancel if it does
+	// not iterate through all elements (i.e. until Advance
+	// returns false).  Cancel is idempotent and can be called
+	// concurrently with a goroutine that is iterating via
+	// Advance/Value.  Cancel causes Advance to subsequently
+	// return  false.  Cancel does not block.
 	Cancel()
 }
diff --git a/v23/syncbase/nosql/internal/query/query_parser/doc.go b/v23/syncbase/nosql/internal/query/query_parser/doc.go
new file mode 100644
index 0000000..18f041f
--- /dev/null
+++ b/v23/syncbase/nosql/internal/query/query_parser/doc.go
@@ -0,0 +1,68 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package query_parser is a parser to parse a simplified select statement (a la SQL) for the
+// Vanadium key value store (a.k.a., syncbase).
+//
+// The select is of the form:
+//
+// <query_specification> ::=
+//   SELECT <field_clause> <from_clause> [<where_clause>] [<limit_offset_clause>]
+//
+// <field_clause> ::= <field>[{<comma><field>}...]
+//
+// <field> ::= <segment>[{<period><segment>}...]
+//
+// <segment> ::= <identifier>
+//
+// <from_clause> ::= FROM <table>
+//
+// <table> ::= <identifier>
+//
+// <where_clause> ::= WHERE <expression>
+//
+// <limit_offset_clause> ::=
+// <limit_clause> [<offset_clause>]
+// | <offset_clause> [<limit_clause>]
+//
+// <limit_clause> ::= LIMIT <int_literal>
+//
+// <offset_clause> ::= OFFSET <int_literal>
+//
+// <expression> ::=
+//   ( <expression> )
+//   | <logical_expression>
+//   | <binary_expression>
+//
+// <logical_expression> ::=
+//   <expression> <logical_op> <expression>
+//
+// <logical_op> ::=
+//   AND
+//   | OR
+//
+// <binary_expression> ::=
+//   <operand> <binary_op> <operand>
+//
+// <operand> ::=
+//   <field>
+//   | <literal>
+//
+// <binary_op> ::=
+//   =
+//   | <>
+//   | <
+//   | >
+//   | <=
+//   | >=
+//   | EQUAL
+//   | NOT EQUAL
+//   | LIKE
+//   | NOT LIKE
+//
+// <literal> ::= <string_literal> | <char_literal> | <int_literal> | <float_literal>
+//
+// Example:
+// select foo.bar, baz from foobarbaz where foo = 42 and bar not like "abc%"
+package query_parser
diff --git a/v23/syncbase/nosql/internal/query/query_parser/query_parser.go b/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
index e9a77d5..61cce96 100644
--- a/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
+++ b/v23/syncbase/nosql/internal/query/query_parser/query_parser.go
@@ -1,71 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-//
-// Package query_parser is a parser to parse a simplified select statement (a la SQL) for the
-// Vanadium key value store (a.k.a., syncbase).
-//
-// The select is of the form:
-//
-// <query_specification> ::=
-//   SELECT <field_clause> <from_clause> [<where_clause>] [<limit_offset_clause>]
-//
-// <field_clause> ::= <field>[{<comma><field>}...]
-//
-// <field> ::= <segment>[{<period><segment>}...]
-//
-// <segment> ::= <identifier>
-//
-// <from_clause> ::= FROM <table>
-//
-// <table> ::= <identifier>
-//
-// <where_clause> ::= WHERE <expression>
-//
-// <limit_offset_clause> ::=
-// <limit_clause> [<offset_clause>]
-// | <offset_clause> [<limit_clause>]
-//
-// <limit_clause> ::= LIMIT <int_literal>
-//
-// <offset_clause> ::= OFFSET <int_literal>
-//
-// <expression> ::=
-//   ( <expression> )
-//   | <logical_expression>
-//   | <binary_expression>
-//
-// <logical_expression> ::=
-//   <expression> <logical_op> <expression>
-//
-// <logical_op> ::=
-//   AND
-//   | OR
-//
-// <binary_expression> ::=
-//   <operand> <binary_op> <operand>
-//
-// <operand> ::=
-//   <field>
-//   | <literal>
-//
-// <binary_op> ::=
-//   =
-//   | <>
-//   | <
-//   | >
-//   | <=
-//   | >=
-//   | EQUAL
-//   | NOT EQUAL
-//   | LIKE
-//   | NOT LIKE
-//
-// <literal> ::= <string_literal> | <char_literal> | <int_literal> | <float_literal>
-//
-// Example:
-// select foo.bar, baz from foobarbaz where foo = 42 and bar not like "abc%"
-//
+
 package query_parser
 
 import (
diff --git a/v23/syncbase/nosql/internal/query/query_parser/query_parser_test.go b/v23/syncbase/nosql/internal/query/query_parser/query_parser_test.go
index c2ea1db..78a6075 100644
--- a/v23/syncbase/nosql/internal/query/query_parser/query_parser_test.go
+++ b/v23/syncbase/nosql/internal/query/query_parser/query_parser_test.go
@@ -1,6 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+
 package query_parser_test
 
 import (
diff --git a/v23/syncbase/nosql/internal/query/query_test.go b/v23/syncbase/nosql/internal/query/query_test.go
index e8bb006..dced5d7 100644
--- a/v23/syncbase/nosql/internal/query/query_test.go
+++ b/v23/syncbase/nosql/internal/query/query_test.go
@@ -1,6 +1,7 @@
 // Copyright 2015 The Vanadium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+
 package query_test
 
 import (
@@ -131,7 +132,7 @@
 
 var customerRows []customerKV
 
-func TestCreate(t *testing.T) {
+func init() {
 	sampleRow = Customer{"John Smith", 123456, true, 'A', "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(1234567890), big.NewRat(123, 1), byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), Nest1{Nest2{"foo", true, 42}}}
 	sampleRow123 = Customer{"John Smith", 123, true, 123, "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(123), big.NewRat(123, 1), byte(123), uint16(123), uint32(123), uint64(123), int16(123), int32(123), Nest1{Nest2{"foo", true, 123}}}
 	sampleRow = Customer{"John Smith", 123456, true, 'A', "1 Main St.", "Palo Alto", "CA", "94303", big.NewInt(1234567890), big.NewRat(123, 1), byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), Nest1{Nest2{"foo", true, 42}}}
@@ -185,8 +186,7 @@
 type evalWhereUsingOnlyKeyTest struct {
 	query  string
 	key    string
-	result bool
-	err    error
+	result query.EvalWithKeyResult
 }
 
 type evalTest struct {
@@ -611,36 +611,31 @@
 			// Row will be selected using only the key.
 			"select k, v from Customer where k like \"abc%\"",
 			"abcdef",
-			true,
-			nil,
+			query.INCLUDE,
 		},
 		{
 			// Row will be rejected using only the key.
 			"select k, v from Customer where k like \"abc\"",
 			"abcd",
-			false,
-			nil,
+			query.EXCLUDE,
 		},
 		{
 			// Need value to determine if row should be selected.
 			"select k, v from Customer where k = \"abc\" or v.zip = \"94303\"",
 			"abcd",
-			false,
-			errors.New("Value required for answer."),
+			query.FETCH_VALUE,
 		},
 		{
 			// Need value (i.e., its type) to determine if row should be selected.
 			"select k, v from Customer where k = \"xyz\" or t = \"foo.Bar\"",
 			"wxyz",
-			false,
-			errors.New("Value required for answer."),
+			query.FETCH_VALUE,
 		},
 		{
 			// Although value is in where clause, it is not needed to reject row.
 			"select k, v from Customer where k = \"abcd\" and v.zip = \"94303\"",
 			"abcde",
-			false,
-			nil,
+			query.EXCLUDE,
 		},
 	}
 
@@ -657,13 +652,10 @@
 			if semErr == nil {
 				switch sel := (*s).(type) {
 				case query_parser.SelectStatement:
-					result, err := query.EvalWhereUsingOnlyKey(&sel, test.key)
+					result := query.EvalWhereUsingOnlyKey(&sel, test.key)
 					if result != test.result {
 						t.Errorf("query: %s; got %v, want %v", test.query, result, test.result)
 					}
-					if (err == nil && test.err != nil) || (err != nil && test.err == nil) {
-						t.Errorf("query: %s; got %v, want %v", test.query, err, test.err)
-					}
 				default:
 					t.Errorf("query: %s; got %v, want query_parser.SelectStatement", test.query, reflect.TypeOf(*s))
 				}