1/*
2Copyright 2019 Google LLC
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package spannertest
18
19// This file contains the part of the Spanner fake that evaluates expressions.
20
21import (
22	"bytes"
23	"fmt"
24	"regexp"
25	"strconv"
26	"strings"
27	"time"
28
29	"cloud.google.com/go/civil"
30	"cloud.google.com/go/spanner/spansql"
31	"google.golang.org/grpc/codes"
32	"google.golang.org/grpc/status"
33)
34
35// evalContext represents the context for evaluating an expression.
36type evalContext struct {
37	// cols and row are set during expr evaluation.
38	cols []colInfo
39	row  row
40
41	// If there are visible aliases, they are populated here.
42	aliases map[spansql.ID]spansql.Expr
43
44	params queryParams
45}
46
47// coercedValue represents a literal value that has been coerced to a different type.
48// This never leaves this package, nor is persisted.
49type coercedValue struct {
50	spansql.Expr             // not a real Expr
51	val          interface{} // internal representation
52	// TODO: type?
53	orig spansql.Expr
54}
55
56func (cv coercedValue) SQL() string { return cv.orig.SQL() }
57
58func (ec evalContext) evalExprList(list []spansql.Expr) ([]interface{}, error) {
59	var out []interface{}
60	for _, e := range list {
61		x, err := ec.evalExpr(e)
62		if err != nil {
63			return nil, err
64		}
65		out = append(out, x)
66	}
67	return out, nil
68}
69
70func (ec evalContext) evalBoolExpr(be spansql.BoolExpr) (*bool, error) {
71	switch be := be.(type) {
72	default:
73		return nil, fmt.Errorf("unhandled BoolExpr %T", be)
74	case spansql.BoolLiteral:
75		b := bool(be)
76		return &b, nil
77	case spansql.ID, spansql.Param, spansql.Paren, spansql.Func, spansql.InOp: // InOp is a bit weird.
78		e, err := ec.evalExpr(be)
79		if err != nil {
80			return nil, err
81		}
82		if e == nil {
83			return nil, nil // preserve NULLs
84		}
85		b, ok := e.(bool)
86		if !ok {
87			return nil, fmt.Errorf("got %T, want bool", e)
88		}
89		return &b, nil
90	case spansql.LogicalOp:
91		var lhs, rhs *bool
92		var err error
93		if be.LHS != nil {
94			lhs, err = ec.evalBoolExpr(be.LHS)
95			if err != nil {
96				return nil, err
97			}
98		}
99		rhs, err = ec.evalBoolExpr(be.RHS)
100		if err != nil {
101			return nil, err
102		}
103		// https://cloud.google.com/spanner/docs/operators#logical_operators
104		switch be.Op {
105		case spansql.And:
106			if lhs != nil {
107				if *lhs {
108					// TRUE AND x => x
109					return rhs, nil
110				}
111				// FALSE AND x => FALSE
112				return lhs, nil
113			}
114			// NULL AND FALSE => FALSE
115			if rhs != nil && !*rhs {
116				return rhs, nil
117			}
118			// NULL AND TRUE|NULL => NULL
119			return nil, nil
120		case spansql.Or:
121			if lhs != nil {
122				if *lhs {
123					// TRUE OR x => TRUE
124					return lhs, nil
125				}
126				// FALSE OR x => x
127				return rhs, nil
128			}
129			// NULL OR TRUE => TRUE
130			if rhs != nil && *rhs {
131				return rhs, nil
132			}
133			// NULL OR FALSE|NULL => NULL
134			return nil, nil
135		case spansql.Not:
136			if rhs == nil {
137				return nil, nil
138			}
139			b := !*rhs
140			return &b, nil
141		default:
142			return nil, fmt.Errorf("unhandled LogicalOp %d", be.Op)
143		}
144	case spansql.ComparisonOp:
145		// Per https://cloud.google.com/spanner/docs/operators#comparison_operators,
146		// "Cloud Spanner SQL will generally coerce literals to the type of non-literals, where present".
147		// Before evaluating be.LHS and be.RHS, do any necessary coercion.
148		be, err := ec.coerceComparisonOpArgs(be)
149		if err != nil {
150			return nil, err
151		}
152
153		lhs, err := ec.evalExpr(be.LHS)
154		if err != nil {
155			return nil, err
156		}
157		rhs, err := ec.evalExpr(be.RHS)
158		if err != nil {
159			return nil, err
160		}
161		if lhs == nil || rhs == nil {
162			// https://cloud.google.com/spanner/docs/operators#comparison_operators says
163			// "any operation with a NULL input returns NULL."
164			return nil, nil
165		}
166		var b bool
167		switch be.Op {
168		default:
169			return nil, fmt.Errorf("TODO: ComparisonOp %d", be.Op)
170		case spansql.Lt:
171			b = compareVals(lhs, rhs) < 0
172		case spansql.Le:
173			b = compareVals(lhs, rhs) <= 0
174		case spansql.Gt:
175			b = compareVals(lhs, rhs) > 0
176		case spansql.Ge:
177			b = compareVals(lhs, rhs) >= 0
178		case spansql.Eq:
179			b = compareVals(lhs, rhs) == 0
180		case spansql.Ne:
181			b = compareVals(lhs, rhs) != 0
182		case spansql.Like, spansql.NotLike:
183			left, ok := lhs.(string)
184			if !ok {
185				// TODO: byte works here too?
186				return nil, fmt.Errorf("LHS of LIKE is %T, not string", lhs)
187			}
188			right, ok := rhs.(string)
189			if !ok {
190				// TODO: byte works here too?
191				return nil, fmt.Errorf("RHS of LIKE is %T, not string", rhs)
192			}
193
194			b = evalLike(left, right)
195			if be.Op == spansql.NotLike {
196				b = !b
197			}
198		case spansql.Between, spansql.NotBetween:
199			rhs2, err := ec.evalExpr(be.RHS2)
200			if err != nil {
201				return nil, err
202			}
203			b = compareVals(rhs, lhs) <= 0 && compareVals(lhs, rhs2) <= 0
204			if be.Op == spansql.NotBetween {
205				b = !b
206			}
207		}
208		return &b, nil
209	case spansql.IsOp:
210		lhs, err := ec.evalExpr(be.LHS)
211		if err != nil {
212			return nil, err
213		}
214		var b bool
215		switch rhs := be.RHS.(type) {
216		default:
217			return nil, fmt.Errorf("unhandled IsOp %T", rhs)
218		case spansql.BoolLiteral:
219			if lhs == nil {
220				// For `X IS TRUE`, X being NULL is okay, and this evaluates
221				// to false. Same goes for `X IS FALSE`.
222				lhs = !bool(rhs)
223			}
224			lhsBool, ok := lhs.(bool)
225			if !ok {
226				return nil, fmt.Errorf("non-bool value %T on LHS for %s", lhs, be.SQL())
227			}
228			b = (lhsBool == bool(rhs))
229		case spansql.NullLiteral:
230			b = (lhs == nil)
231		}
232		if be.Neg {
233			b = !b
234		}
235		return &b, nil
236	}
237}
238
239func (ec evalContext) evalArithOp(e spansql.ArithOp) (interface{}, error) {
240	switch e.Op {
241	case spansql.Neg:
242		rhs, err := ec.evalExpr(e.RHS)
243		if err != nil {
244			return nil, err
245		}
246		switch rhs := rhs.(type) {
247		case float64:
248			return -rhs, nil
249		case int64:
250			return -rhs, nil
251		}
252		return nil, fmt.Errorf("RHS of %s evaluates to %T, want FLOAT64 or INT64", e.SQL(), rhs)
253	case spansql.BitNot:
254		rhs, err := ec.evalExpr(e.RHS)
255		if err != nil {
256			return nil, err
257		}
258		switch rhs := rhs.(type) {
259		case int64:
260			return ^rhs, nil
261		case []byte:
262			b := append([]byte(nil), rhs...) // deep copy
263			for i := range b {
264				b[i] = ^b[i]
265			}
266			return b, nil
267		}
268		return nil, fmt.Errorf("RHS of %s evaluates to %T, want INT64 or BYTES", e.SQL(), rhs)
269	case spansql.Div:
270		lhs, err := ec.evalFloat64(e.LHS)
271		if err != nil {
272			return nil, err
273		}
274		rhs, err := ec.evalFloat64(e.RHS)
275		if err != nil {
276			return nil, err
277		}
278		if rhs == 0 {
279			// TODO: Does real Spanner use a specific error code here?
280			return nil, fmt.Errorf("divide by zero")
281		}
282		return lhs / rhs, nil
283	case spansql.Add, spansql.Sub, spansql.Mul:
284		lhs, err := ec.evalExpr(e.LHS)
285		if err != nil {
286			return nil, err
287		}
288		rhs, err := ec.evalExpr(e.RHS)
289		if err != nil {
290			return nil, err
291		}
292		i1, ok1 := lhs.(int64)
293		i2, ok2 := rhs.(int64)
294		if ok1 && ok2 {
295			switch e.Op {
296			case spansql.Add:
297				return i1 + i2, nil
298			case spansql.Sub:
299				return i1 - i2, nil
300			case spansql.Mul:
301				return i1 * i2, nil
302			}
303		}
304		f1, err := asFloat64(e.LHS, lhs)
305		if err != nil {
306			return nil, err
307		}
308		f2, err := asFloat64(e.RHS, rhs)
309		if err != nil {
310			return nil, err
311		}
312		switch e.Op {
313		case spansql.Add:
314			return f1 + f2, nil
315		case spansql.Sub:
316			return f1 - f2, nil
317		case spansql.Mul:
318			return f1 * f2, nil
319		}
320	case spansql.BitAnd, spansql.BitXor, spansql.BitOr:
321		lhs, err := ec.evalExpr(e.LHS)
322		if err != nil {
323			return nil, err
324		}
325		rhs, err := ec.evalExpr(e.RHS)
326		if err != nil {
327			return nil, err
328		}
329		i1, ok1 := lhs.(int64)
330		i2, ok2 := rhs.(int64)
331		if ok1 && ok2 {
332			switch e.Op {
333			case spansql.BitAnd:
334				return i1 & i2, nil
335			case spansql.BitXor:
336				return i1 ^ i2, nil
337			case spansql.BitOr:
338				return i1 | i2, nil
339			}
340		}
341		b1, ok1 := lhs.([]byte)
342		b2, ok2 := rhs.([]byte)
343		if !ok1 || !ok2 {
344			return nil, fmt.Errorf("arguments of %s evaluate to (%T, %T), want (INT64, INT64) or (BYTES, BYTES)", e.SQL(), lhs, rhs)
345		}
346		if len(b1) != len(b2) {
347			return nil, fmt.Errorf("arguments of %s evaluate to BYTES of unequal lengths (%d vs %d)", e.SQL(), len(b1), len(b2))
348		}
349		var f func(x, y byte) byte
350		switch e.Op {
351		case spansql.BitAnd:
352			f = func(x, y byte) byte { return x & y }
353		case spansql.BitXor:
354			f = func(x, y byte) byte { return x ^ y }
355		case spansql.BitOr:
356			f = func(x, y byte) byte { return x | y }
357		}
358		b := make([]byte, len(b1))
359		for i := range b1 {
360			b[i] = f(b1[i], b2[i])
361		}
362		return b, nil
363	}
364	// TODO: Concat, BitShl, BitShr
365	return nil, fmt.Errorf("TODO: evalArithOp(%s %v)", e.SQL(), e.Op)
366}
367
368func (ec evalContext) evalFunc(e spansql.Func) (interface{}, spansql.Type, error) {
369	if f, ok := functions[e.Name]; ok {
370		args := make([]interface{}, len(e.Args))
371		for i, arg := range e.Args {
372			val, err := ec.evalExpr(arg)
373			if err != nil {
374				return nil, spansql.Type{}, err
375			}
376			args[i] = val
377		}
378		return f.Eval(args)
379	}
380	return nil, spansql.Type{}, status.Errorf(codes.Unimplemented, "function %q is not implemented", e.Name)
381}
382
383// evalFloat64 evaluates an expression and returns its FLOAT64 value.
384// If the expression does not yield a FLOAT64 or INT64 it returns an error.
385func (ec evalContext) evalFloat64(e spansql.Expr) (float64, error) {
386	v, err := ec.evalExpr(e)
387	if err != nil {
388		return 0, err
389	}
390	return asFloat64(e, v)
391}
392
393func asFloat64(e spansql.Expr, v interface{}) (float64, error) {
394	switch v := v.(type) {
395	default:
396		return 0, fmt.Errorf("expression %s evaluates to %T, want FLOAT64 or INT64", e.SQL(), v)
397	case float64:
398		return v, nil
399	case int64:
400		return float64(v), nil
401	}
402}
403
404func (ec evalContext) evalExpr(e spansql.Expr) (interface{}, error) {
405	// Several cases below are handled by this.
406	// It evaluates a BoolExpr (which returns *bool for a tri-state BOOL)
407	// and converts it to true/false/nil.
408	evalBool := func(be spansql.BoolExpr) (interface{}, error) {
409		b, err := ec.evalBoolExpr(be)
410		if err != nil {
411			return nil, err
412		}
413		if b == nil {
414			return nil, nil // (*bool)(nil) -> interface nil
415		}
416		return *b, nil
417	}
418
419	switch e := e.(type) {
420	default:
421		return nil, fmt.Errorf("TODO: evalExpr(%s %T)", e.SQL(), e)
422	case coercedValue:
423		return e.val, nil
424	case spansql.PathExp:
425		return ec.evalPathExp(e)
426	case spansql.ID:
427		return ec.evalID(e)
428	case spansql.Param:
429		qp, ok := ec.params[string(e)]
430		if !ok {
431			return 0, fmt.Errorf("unbound param %s", e.SQL())
432		}
433		return qp.Value, nil
434	case spansql.IntegerLiteral:
435		return int64(e), nil
436	case spansql.FloatLiteral:
437		return float64(e), nil
438	case spansql.StringLiteral:
439		return string(e), nil
440	case spansql.BytesLiteral:
441		return []byte(e), nil
442	case spansql.NullLiteral:
443		return nil, nil
444	case spansql.BoolLiteral:
445		return bool(e), nil
446	case spansql.Paren:
447		return ec.evalExpr(e.Expr)
448	case spansql.Func:
449		v, _, err := ec.evalFunc(e)
450		if err != nil {
451			return nil, err
452		}
453		return v, nil
454	case spansql.Array:
455		var arr []interface{}
456		for _, elt := range e {
457			v, err := ec.evalExpr(elt)
458			if err != nil {
459				return nil, err
460			}
461			arr = append(arr, v)
462		}
463		// TODO: enforce or coerce to consistent types.
464		return arr, nil
465	case spansql.ArithOp:
466		return ec.evalArithOp(e)
467	case spansql.LogicalOp:
468		return evalBool(e)
469	case spansql.ComparisonOp:
470		return evalBool(e)
471	case spansql.InOp:
472		// This is implemented here in evalExpr instead of evalBoolExpr
473		// because it can return FALSE/TRUE/NULL.
474		// The docs are a bit confusing here, so there's probably some bugs here around NULL handling.
475		// TODO: Can this now simplify using evalBool?
476
477		if len(e.RHS) == 0 {
478			// "IN with an empty right side expression is always FALSE".
479			return e.Neg, nil
480		}
481		lhs, err := ec.evalExpr(e.LHS)
482		if err != nil {
483			return false, err
484		}
485		if lhs == nil {
486			// "IN with a NULL left side expression and a non-empty right side expression is always NULL".
487			return nil, nil
488		}
489		var b bool
490		for _, rhse := range e.RHS {
491			rhs, err := ec.evalExpr(rhse)
492			if err != nil {
493				return false, err
494			}
495			if !e.Unnest {
496				if lhs == rhs {
497					b = true
498				}
499			} else {
500				if rhs == nil {
501					// "IN UNNEST(<NULL array>) returns FALSE (not NULL)".
502					return e.Neg, nil
503				}
504				arr, ok := rhs.([]interface{})
505				if !ok {
506					return nil, fmt.Errorf("UNNEST argument evaluated as %T, want array", rhs)
507				}
508				for _, rhs := range arr {
509					// == isn't okay here.
510					if compareVals(lhs, rhs) == 0 {
511						b = true
512					}
513				}
514			}
515		}
516		if e.Neg {
517			b = !b
518		}
519		return b, nil
520	case spansql.IsOp:
521		return evalBool(e)
522	case aggSentinel:
523		// Match up e.AggIndex with the column.
524		// They might have been reordered.
525		ci := -1
526		for i, col := range ec.cols {
527			if col.AggIndex == e.AggIndex {
528				ci = i
529				break
530			}
531		}
532		if ci < 0 {
533			return 0, fmt.Errorf("internal error: did not find aggregate column %d", e.AggIndex)
534		}
535		return ec.row[ci], nil
536	}
537}
538
539// resolveColumnIndex turns an ID or PathExp into a table column index.
540func (ec evalContext) resolveColumnIndex(e spansql.Expr) (int, error) {
541	switch e := e.(type) {
542	case spansql.ID:
543		for i, col := range ec.cols {
544			if col.Name == e {
545				return i, nil
546			}
547		}
548	case spansql.PathExp:
549		for i, col := range ec.cols {
550			if pathExpEqual(e, col.Alias) {
551				return i, nil
552			}
553		}
554	}
555	return 0, fmt.Errorf("couldn't resolve [%s] as a table column", e.SQL())
556}
557
558func (ec evalContext) evalPathExp(pe spansql.PathExp) (interface{}, error) {
559	// TODO: support more than only naming an aliased table column.
560	if i, err := ec.resolveColumnIndex(pe); err == nil {
561		return ec.row.copyDataElem(i), nil
562	}
563	return nil, fmt.Errorf("couldn't resolve path expression %s", pe.SQL())
564}
565
566func (ec evalContext) evalID(id spansql.ID) (interface{}, error) {
567	if i, err := ec.resolveColumnIndex(id); err == nil {
568		return ec.row.copyDataElem(i), nil
569	}
570	if e, ok := ec.aliases[id]; ok {
571		// Make a copy of the context without this alias
572		// to prevent an evaluation cycle.
573		innerEC := ec
574		innerEC.aliases = make(map[spansql.ID]spansql.Expr)
575		for alias, e := range ec.aliases {
576			if alias != id {
577				innerEC.aliases[alias] = e
578			}
579		}
580		return innerEC.evalExpr(e)
581	}
582	return nil, fmt.Errorf("couldn't resolve identifier %s", id)
583}
584
585func (ec evalContext) coerceComparisonOpArgs(co spansql.ComparisonOp) (spansql.ComparisonOp, error) {
586	// https://cloud.google.com/spanner/docs/operators#comparison_operators
587
588	if co.RHS2 != nil {
589		// TODO: Handle co.RHS2 for BETWEEN. The rules for that aren't clear.
590		return co, nil
591	}
592
593	// Look for a string literal on LHS or RHS.
594	var err error
595	if slit, ok := co.LHS.(spansql.StringLiteral); ok {
596		co.LHS, err = ec.coerceString(co.RHS, slit)
597		return co, err
598	}
599	if slit, ok := co.RHS.(spansql.StringLiteral); ok {
600		co.RHS, err = ec.coerceString(co.LHS, slit)
601		return co, err
602	}
603
604	// TODO: Other coercion literals. The int64/float64 code elsewhere may be able to be simplified.
605
606	return co, nil
607}
608
609// coerceString converts a string literal into something compatible with the target expression.
610func (ec evalContext) coerceString(target spansql.Expr, slit spansql.StringLiteral) (spansql.Expr, error) {
611	ci, err := ec.colInfo(target)
612	if err != nil {
613		return nil, err
614	}
615	if ci.Type.Array {
616		return nil, fmt.Errorf("unable to coerce string literal %q to match array type", slit)
617	}
618	switch ci.Type.Base {
619	case spansql.String:
620		return slit, nil
621	case spansql.Date:
622		d, err := parseAsDate(string(slit))
623		if err != nil {
624			return nil, fmt.Errorf("coercing string literal %q to DATE: %v", slit, err)
625		}
626		return coercedValue{
627			val:  d,
628			orig: slit,
629		}, nil
630	case spansql.Timestamp:
631		t, err := parseAsTimestamp(string(slit))
632		if err != nil {
633			return nil, fmt.Errorf("coercing string literal %q to TIMESTAMP: %v", slit, err)
634		}
635		return coercedValue{
636			val:  t,
637			orig: slit,
638		}, nil
639	}
640
641	// TODO: Any others?
642
643	return nil, fmt.Errorf("unable to coerce string literal %q to match %v", slit, ci.Type)
644}
645
646func evalLiteralOrParam(lop spansql.LiteralOrParam, params queryParams) (int64, error) {
647	switch v := lop.(type) {
648	case spansql.IntegerLiteral:
649		return int64(v), nil
650	case spansql.Param:
651		return paramAsInteger(v, params)
652	default:
653		return 0, fmt.Errorf("LiteralOrParam with %T not supported", v)
654	}
655}
656
657func paramAsInteger(p spansql.Param, params queryParams) (int64, error) {
658	qp, ok := params[string(p)]
659	if !ok {
660		return 0, fmt.Errorf("unbound param %s", p.SQL())
661	}
662	switch v := qp.Value.(type) {
663	default:
664		return 0, fmt.Errorf("can't interpret parameter %s (%s) value of type %T as integer", p.SQL(), qp.Type.SQL(), v)
665	case int64:
666		return v, nil
667	case string:
668		x, err := strconv.ParseInt(v, 10, 64)
669		if err != nil {
670			return 0, fmt.Errorf("bad int64 string %q: %v", v, err)
671		}
672		return x, nil
673	}
674}
675
676// compareValLists compares pair-wise elements of a and b.
677// If desc is not nil, it indicates which comparisons should be reversed.
678func compareValLists(a, b []interface{}, desc []bool) int {
679	for i := range a {
680		cmp := compareVals(a[i], b[i])
681		if cmp == 0 {
682			continue
683		}
684		if desc != nil && desc[i] {
685			cmp = -cmp
686		}
687		return cmp
688	}
689	return 0
690}
691
692func compareVals(x, y interface{}) int {
693	// NULL is always the minimum possible value.
694	if x == nil && y == nil {
695		return 0
696	} else if x == nil {
697		return -1
698	} else if y == nil {
699		return 1
700	}
701
702	// TODO: coerce between more comparable types? factor this out for expressions other than comparisons.
703
704	switch x := x.(type) {
705	default:
706		panic(fmt.Sprintf("unhandled comparison on %T", x))
707	case bool:
708		// false < true
709		y := y.(bool)
710		if !x && y {
711			return -1
712		} else if x && !y {
713			return 1
714		}
715		return 0
716	case int64:
717		if s, ok := y.(string); ok {
718			var err error
719			y, err = strconv.ParseInt(s, 10, 64)
720			if err != nil {
721				panic(fmt.Sprintf("bad int64 string %q: %v", s, err))
722			}
723		}
724		if f, ok := y.(float64); ok {
725			// Coersion from INT64 to FLOAT64 is allowed.
726			return compareVals(x, f)
727		}
728		y := y.(int64)
729		if x < y {
730			return -1
731		} else if x > y {
732			return 1
733		}
734		return 0
735	case float64:
736		// Coersion from INT64 to FLOAT64 is allowed.
737		if i, ok := y.(int64); ok {
738			y = float64(i)
739		}
740		y := y.(float64)
741		if x < y {
742			return -1
743		} else if x > y {
744			return 1
745		}
746		return 0
747	case string:
748		return strings.Compare(x, y.(string))
749	case civil.Date:
750		y := y.(civil.Date)
751		if x.Before(y) {
752			return -1
753		} else if x.After(y) {
754			return 1
755		}
756		return 0
757	case time.Time:
758		y := y.(time.Time)
759		if x.Before(y) {
760			return -1
761		} else if x.After(y) {
762			return 1
763		}
764		return 0
765	case []byte:
766		return bytes.Compare(x, y.([]byte))
767	}
768}
769
770var (
771	boolType    = spansql.Type{Base: spansql.Bool}
772	int64Type   = spansql.Type{Base: spansql.Int64}
773	float64Type = spansql.Type{Base: spansql.Float64}
774	stringType  = spansql.Type{Base: spansql.String}
775)
776
777func (ec evalContext) colInfo(e spansql.Expr) (colInfo, error) {
778	// TODO: more types
779	switch e := e.(type) {
780	case spansql.BoolLiteral:
781		return colInfo{Type: boolType}, nil
782	case spansql.IntegerLiteral:
783		return colInfo{Type: int64Type}, nil
784	case spansql.StringLiteral:
785		return colInfo{Type: stringType}, nil
786	case spansql.BytesLiteral:
787		return colInfo{Type: spansql.Type{Base: spansql.Bytes}}, nil
788	case spansql.ArithOp:
789		t, err := ec.arithColType(e)
790		if err != nil {
791			return colInfo{}, err
792		}
793		return colInfo{Type: t}, nil
794	case spansql.LogicalOp, spansql.ComparisonOp, spansql.IsOp:
795		return colInfo{Type: spansql.Type{Base: spansql.Bool}}, nil
796	case spansql.PathExp, spansql.ID:
797		// TODO: support more than only naming a table column.
798		i, err := ec.resolveColumnIndex(e)
799		if err == nil {
800			return ec.cols[i], nil
801		}
802		// Let errors fall through.
803	case spansql.Param:
804		qp, ok := ec.params[string(e)]
805		if !ok {
806			return colInfo{}, fmt.Errorf("unbound param %s", e.SQL())
807		}
808		return colInfo{Type: qp.Type}, nil
809	case spansql.Paren:
810		return ec.colInfo(e.Expr)
811	case spansql.Func:
812		_, t, err := ec.evalFunc(e)
813		if err != nil {
814			return colInfo{}, err
815		}
816		return colInfo{Type: t}, nil
817	case spansql.Array:
818		// Assume all element of an array literal have the same type.
819		if len(e) == 0 {
820			// TODO: What does the real Spanner do here?
821			return colInfo{Type: spansql.Type{Base: spansql.Int64, Array: true}}, nil
822		}
823		ci, err := ec.colInfo(e[0])
824		if err != nil {
825			return colInfo{}, err
826		}
827		if ci.Type.Array {
828			return colInfo{}, fmt.Errorf("can't nest array literals")
829		}
830		ci.Type.Array = true
831		return ci, nil
832	case spansql.NullLiteral:
833		// There isn't necessarily something sensible here.
834		// Empirically, though, the real Spanner returns Int64.
835		return colInfo{Type: int64Type}, nil
836	case aggSentinel:
837		return colInfo{Type: e.Type, AggIndex: e.AggIndex}, nil
838	}
839	return colInfo{}, fmt.Errorf("can't deduce column type from expression [%s] (type %T)", e.SQL(), e)
840}
841
842func (ec evalContext) arithColType(ao spansql.ArithOp) (spansql.Type, error) {
843	// The type depends on the particular operator and the argument types.
844	// https://cloud.google.com/spanner/docs/functions-and-operators#arithmetic_operators
845
846	var lhs, rhs spansql.Type
847	var err error
848	if ao.LHS != nil {
849		ci, err := ec.colInfo(ao.LHS)
850		if err != nil {
851			return spansql.Type{}, err
852		}
853		lhs = ci.Type
854	}
855	ci, err := ec.colInfo(ao.RHS)
856	if err != nil {
857		return spansql.Type{}, err
858	}
859	rhs = ci.Type
860
861	switch ao.Op {
862	default:
863		return spansql.Type{}, fmt.Errorf("can't deduce column type from ArithOp [%s]", ao.SQL())
864	case spansql.Neg, spansql.BitNot:
865		return rhs, nil
866	case spansql.Add, spansql.Sub, spansql.Mul:
867		if lhs == int64Type && rhs == int64Type {
868			return int64Type, nil
869		}
870		return float64Type, nil
871	case spansql.Div:
872		return float64Type, nil
873	case spansql.Concat:
874		if !lhs.Array {
875			return stringType, nil
876		}
877		return lhs, nil
878	case spansql.BitShl, spansql.BitShr, spansql.BitAnd, spansql.BitXor, spansql.BitOr:
879		// "All bitwise operators return the same type and the same length as the first operand."
880		return lhs, nil
881	}
882}
883
884func pathExpEqual(a, b spansql.PathExp) bool {
885	if len(a) != len(b) {
886		return false
887	}
888	for i := range a {
889		if a[i] != b[i] {
890			return false
891		}
892	}
893	return true
894}
895
896func evalLike(str, pat string) bool {
897	/*
898		% matches any number of chars.
899		_ matches a single char.
900		TODO: handle escaping
901	*/
902
903	// Lean on regexp for simplicity.
904	pat = regexp.QuoteMeta(pat)
905	if !strings.HasPrefix(pat, "%") {
906		pat = "^" + pat
907	}
908	if !strings.HasSuffix(pat, "%") {
909		pat = pat + "$"
910	}
911	pat = strings.Replace(pat, "%", ".*", -1)
912	pat = strings.Replace(pat, "_", ".", -1)
913	match, err := regexp.MatchString(pat, str)
914	if err != nil {
915		panic(fmt.Sprintf("internal error: constructed bad regexp /%s/: %v", pat, err))
916	}
917	return match
918}
919