func parseAndNormalizeExpr(t *testing.T, sql string) (parser.Expr, qvalMap) { q, err := parser.ParseTraditional("SELECT " + sql) if err != nil { t.Fatalf("%s: %v", sql, err) } expr := q[0].(*parser.Select).Exprs[0].Expr expr, err = (parser.EvalContext{}).NormalizeExpr(expr) if err != nil { t.Fatalf("%s: %v", sql, err) } // Perform qualified name resolution because {analyze,simplify}Expr want // expressions containing qvalues. s := &scanNode{} s.desc = testTableDesc() s.visibleCols = s.desc.Columns if err := s.desc.AllocateIDs(); err != nil { t.Fatal(err) } expr, err = s.resolveQNames(expr) if err != nil { t.Fatalf("%s: %v", sql, err) } if _, err := parser.TypeCheckExpr(expr); err != nil { t.Fatalf("%s: %v", sql, err) } return expr, s.qvals }
func (n *scanNode) initWhere(where *parser.Where) error { if where == nil { return nil } n.filter, n.err = n.resolveQNames(where.Expr) if n.err == nil { // Normalize the expression (this will also evaluate any branches that are // constant). n.filter, n.err = parser.NormalizeExpr(n.filter) } if n.err == nil { var whereType parser.Datum whereType, n.err = parser.TypeCheckExpr(n.filter) if n.err == nil { if !(whereType == parser.DummyBool || whereType == parser.DNull) { n.err = fmt.Errorf("argument of WHERE must be type %s, not type %s", parser.DummyBool.Type(), whereType.Type()) } } } return n.err }
func makeColumnDefDescs(d *parser.ColumnTableDef) (*ColumnDescriptor, *IndexDescriptor, error) { col := &ColumnDescriptor{ Name: string(d.Name), Nullable: (d.Nullable != parser.NotNull), } var colDatumType parser.Datum switch t := d.Type.(type) { case *parser.BoolType: col.Type.Kind = ColumnType_BOOL colDatumType = parser.DummyBool case *parser.IntType: col.Type.Kind = ColumnType_INT col.Type.Width = int32(t.N) colDatumType = parser.DummyInt case *parser.FloatType: col.Type.Kind = ColumnType_FLOAT col.Type.Precision = int32(t.Prec) colDatumType = parser.DummyFloat case *parser.DecimalType: col.Type.Kind = ColumnType_DECIMAL col.Type.Width = int32(t.Scale) col.Type.Precision = int32(t.Prec) case *parser.DateType: col.Type.Kind = ColumnType_DATE colDatumType = parser.DummyDate case *parser.TimestampType: col.Type.Kind = ColumnType_TIMESTAMP colDatumType = parser.DummyTimestamp case *parser.IntervalType: col.Type.Kind = ColumnType_INTERVAL colDatumType = parser.DummyInterval case *parser.StringType: col.Type.Kind = ColumnType_STRING col.Type.Width = int32(t.N) colDatumType = parser.DummyString case *parser.BytesType: col.Type.Kind = ColumnType_BYTES colDatumType = parser.DummyBytes default: return nil, nil, util.Errorf("unexpected type %T", t) } if d.DefaultExpr != nil { // Verify the default expression type is compatible with the column type. defaultType, err := parser.TypeCheckExpr(d.DefaultExpr) if err != nil { return nil, nil, err } if colDatumType != defaultType { return nil, nil, fmt.Errorf("incompatible column type and default expression: %s vs %s", col.Type.Kind, defaultType.Type()) } s := d.DefaultExpr.String() col.DefaultExpr = &s } var idx *IndexDescriptor if d.PrimaryKey || d.Unique { idx = &IndexDescriptor{ Unique: true, ColumnNames: []string{string(d.Name)}, } } return col, idx, nil }