// SanitizeVarFreeExpr verifies a default expression is valid, has the // correct type and contains no variable expressions. func SanitizeVarFreeExpr(expr parser.Expr, expectedType parser.Type, context string) error { if parser.ContainsVars(expr) { return exprContainsVarsError(context, expr) } typedExpr, err := parser.TypeCheck(expr, nil, expectedType) if err != nil { return err } if defaultType := typedExpr.ResolvedType(); !expectedType.Equal(defaultType) { return incompatibleExprTypeError(context, expectedType, defaultType) } return nil }
// CheckColumnType verifies that a given value is compatible // with the type requested by the column. If the value is a // placeholder, the type of the placeholder gets populated. func CheckColumnType(col ColumnDescriptor, typ parser.Type, pmap *parser.PlaceholderInfo) error { if typ == parser.TypeNull { return nil } var set parser.Type switch col.Type.Kind { case ColumnType_BOOL: set = parser.TypeBool case ColumnType_INT: set = parser.TypeInt case ColumnType_FLOAT: set = parser.TypeFloat case ColumnType_DECIMAL: set = parser.TypeDecimal case ColumnType_STRING: set = parser.TypeString case ColumnType_BYTES: set = parser.TypeBytes case ColumnType_DATE: set = parser.TypeDate case ColumnType_TIMESTAMP: set = parser.TypeTimestamp case ColumnType_TIMESTAMPTZ: set = parser.TypeTimestampTZ case ColumnType_INTERVAL: set = parser.TypeInterval default: return errors.Errorf("unsupported column type: %s", col.Type.Kind) } // If the value is a placeholder, then the column check above has // populated 'set' with a type to assign to it. if p, pok := typ.(parser.TPlaceholder); pok { if err := pmap.SetType(p.Name, set); err != nil { return fmt.Errorf("cannot infer type for placeholder %s from column %q: %s", p.Name, col.Name, err) } } else if !(typ.Equal(set) || (set == parser.TypeBytes && typ == parser.TypeString)) { // Not a placeholder; check that the value cast has succeeded. return fmt.Errorf("value type %s doesn't match type %s of column %q", typ, col.Type.Kind, col.Name) } return nil }