syncbase: syncQL: query optimization and regex rewrite

1. Optimization: examine fewer key values by using ranges rather
   than prefixes.  The query package was written with the
   understanding that only prefixes could be specified when
   fetching key/values from the store (e.g., for the where clause
   expression 'k = "foo", all keys beginning with "foo" would be
   returned.  With this change, at most one key/value pair
   will be examined for the above case.
2. Optimize like expressions that contain no wildcards to an
   equal expression.  If a like is used where not needed, the
   expression is translated to an equals (escaped wildcard
   characters are unescaped as the equals expression does not
   expect escaped characters).
3. The computeRegularExpression function has been rewritten
   because the author (that's me) found it confusing and
   unmaintainable.

Change-Id: Ie66625f6af6baefd45f0292bbf0ac11b9f5d5d86
diff --git a/services/syncbase/server/nosql/database.go b/services/syncbase/server/nosql/database.go
index f2839d6..d18ab04 100644
--- a/services/syncbase/server/nosql/database.go
+++ b/services/syncbase/server/nosql/database.go
@@ -15,7 +15,6 @@
 	wire "v.io/syncbase/v23/services/syncbase/nosql"
 	"v.io/syncbase/v23/syncbase/nosql/query_db"
 	"v.io/syncbase/v23/syncbase/nosql/query_exec"
-	prefixutil "v.io/syncbase/v23/syncbase/util"
 	"v.io/syncbase/x/ref/services/syncbase/server/interfaces"
 	"v.io/syncbase/x/ref/services/syncbase/server/util"
 	"v.io/syncbase/x/ref/services/syncbase/server/watchable"
@@ -404,20 +403,20 @@
 	req *tableReq
 }
 
-func (t *tableDb) Scan(prefixes []string) (query_db.KeyValueStream, error) {
+func (t *tableDb) Scan(keyRanges query_db.KeyRanges) (query_db.KeyValueStream, error) {
 	return &kvs{
-		t:        t,
-		prefixes: prefixes,
-		curr:     -1,
-		validRow: false,
-		it:       nil,
-		err:      nil,
+		t:         t,
+		keyRanges: keyRanges,
+		curr:      -1,
+		validRow:  false,
+		it:        nil,
+		err:       nil,
 	}, nil
 }
 
 type kvs struct {
 	t         *tableDb
-	prefixes  []string
+	keyRanges query_db.KeyRanges
 	curr      int // current index into prefixes, -1 at start
 	validRow  bool
 	currKey   string
@@ -433,11 +432,16 @@
 	if s.curr == -1 {
 		s.curr++
 	}
-	for s.curr < len(s.prefixes) {
+	for s.curr < len(s.keyRanges) {
 		if s.it == nil {
-			start := prefixutil.PrefixRangeStart(s.prefixes[s.curr])
-			limit := prefixutil.PrefixRangeLimit(s.prefixes[s.curr])
-			s.it = s.t.qdb.st.Scan(util.ScanRangeArgs(util.JoinKeyParts(util.RowPrefix, s.t.req.name), string(start), string(limit)))
+			start := s.keyRanges[s.curr].Start
+			limit := s.keyRanges[s.curr].Limit
+			// 0-255 means examine all rows
+			if start == string([]byte{0}) && limit == string([]byte{255}) {
+				start = ""
+				limit = ""
+			}
+			s.it = s.t.qdb.st.Scan(util.ScanRangeArgs(util.JoinKeyParts(util.RowPrefix, s.t.req.name), start, limit))
 		}
 		if s.it.Advance() {
 			// key
@@ -490,8 +494,8 @@
 		s.it.Cancel()
 		s.it = nil
 	}
-	// set curr to end of prefixes so Advance will return false
-	s.curr = len(s.prefixes)
+	// set curr to end of keyRanges so Advance will return false
+	s.curr = len(s.keyRanges)
 }
 
 ////////////////////////////////////////