6 "github.com/vapor/errors"
9 //Column describe a column
15 //Table describe a table
19 Columns map[string]*Column
20 ForeignKeys map[string]*ForeignKey
23 //ForeignKey describe a foreign key
24 type ForeignKey struct {
30 func isType(got Type, want Type) bool {
31 return got == want || got == Any
34 func knownType(t Type) bool {
35 return t == Bool || t == String || t == Integer || t == Object
38 func valueTypes(vals []interface{}) ([]Type, error) {
39 valTypes := make([]Type, len(vals))
40 for i, val := range vals {
42 case int, uint, int32, uint32, int64, uint64:
49 return nil, fmt.Errorf("unsupported value type %T", val)
55 // typeCheck will statically type check expr with vals as the parameters
56 // and using tbl to determine available attributes and environments. It
57 // returns the inferred types of arbitrary json keys as a map.
58 func typeCheck(expr expr, tbl *Table, vals []interface{}) (map[string]Type, error) {
59 valTypes, err := valueTypes(vals)
63 selectorTypes := make(map[string]Type)
64 typ, err := typeCheckExpr(expr, tbl, valTypes, selectorTypes)
68 ok, err := assertType(expr, typ, Bool, selectorTypes)
73 return nil, fmt.Errorf("filter predicate must evaluate to bool, got %s", typ)
75 return selectorTypes, nil
78 func typeCheckExpr(expr expr, tbl *Table, valTypes []Type, selectorTypes map[string]Type) (typ Type, err error) {
79 if expr == nil { // no expr is a valid, bool type
83 switch e := expr.(type) {
85 return typeCheckExpr(e.inner, tbl, valTypes, selectorTypes)
87 leftTyp, err := typeCheckExpr(e.l, tbl, valTypes, selectorTypes)
91 rightTyp, err := typeCheckExpr(e.r, tbl, valTypes, selectorTypes)
98 ok, err := assertType(e.l, leftTyp, Bool, selectorTypes)
103 return typ, fmt.Errorf("%s expects bool operands", e.op.name)
106 ok, err = assertType(e.r, rightTyp, Bool, selectorTypes)
111 return typ, fmt.Errorf("%s expects bool operands", e.op.name)
115 // The = operand requires left and right types to be equal. If
116 // one of our types is known but the other is not, we need to
117 // coerce the untyped one to a matching type.
118 if !knownType(leftTyp) && knownType(rightTyp) {
119 err := setType(e.l, rightTyp, selectorTypes)
125 if !knownType(rightTyp) && knownType(leftTyp) {
126 err := setType(e.r, leftTyp, selectorTypes)
132 if !isType(leftTyp, String) && !isType(leftTyp, Integer) {
133 return typ, fmt.Errorf("%s expects integer or string operands", e.op.name)
135 if !isType(rightTyp, String) && !isType(rightTyp, Integer) {
136 return typ, fmt.Errorf("%s expects integer or string operands", e.op.name)
138 if knownType(rightTyp) && knownType(leftTyp) && leftTyp != rightTyp {
139 return typ, fmt.Errorf("%s expects operands of matching types", e.op.name)
143 panic(fmt.Errorf("unsupported operator: %s", e.op.name))
145 case placeholderExpr:
146 if len(valTypes) == 0 {
149 if e.num <= 0 || e.num > len(valTypes) {
150 return typ, fmt.Errorf("unbound placeholder: $%d", e.num)
152 return valTypes[e.num-1], nil
154 col, ok := tbl.Columns[e.attr]
156 return typ, fmt.Errorf("invalid attribute: %s", e.attr)
166 panic(fmt.Errorf("value expr with invalid token type: %s", e.typ))
169 typ, err = typeCheckExpr(e.objExpr, tbl, valTypes, selectorTypes)
173 ok, err := assertType(e.objExpr, typ, Object, selectorTypes)
178 return typ, errors.New("selector `.` can only be used on objects")
181 // Unfortunately, we can't know the type of the field within the
182 // object yet. Depending on the context, we might be able to assign it
183 // a type later in setType.
186 fk, ok := tbl.ForeignKeys[e.ident]
188 return typ, fmt.Errorf("invalid environment `%s`", e.ident)
190 typ, err = typeCheckExpr(e.expr, fk.Table, valTypes, selectorTypes)
194 ok, err = assertType(e.expr, typ, Bool, selectorTypes)
199 return typ, errors.New(e.ident + "(...) body must have type bool")
203 panic(fmt.Errorf("unrecognized expr type %T", expr))
207 func assertType(expr expr, got, want Type, selectorTypes map[string]Type) (bool, error) {
208 if !isType(got, want) { // type does not match
211 if got != Any { // matching type *and* it's a concrete type
214 // got is `Any`. we should restrict expr to be `want`.
215 err := setType(expr, want, selectorTypes)
219 func setType(expr expr, typ Type, selectorTypes map[string]Type) error {
220 switch e := expr.(type) {
222 return setType(e.inner, typ, selectorTypes)
223 case placeholderExpr:
224 // This is a special case for when we parse a txfeed filter at
225 // txfeed creation time. We don't have access to concrete values
226 // yet, so the parameters are untyped.
229 /*path := strings.Join(jsonbPath(expr), ".")
230 boundTyp, ok := selectorTypes[path]
231 if ok && boundTyp != typ {
232 return fmt.Errorf("%q used as both %s and %s", path, boundTyp, typ)
234 selectorTypes[path] = typ*/
237 // This should be impossible because all other expressions are
239 panic(fmt.Errorf("unexpected setType on %T", expr))