// Convert takes a type and a value, and returns the type: // - nil for NULL value // - int64 for integer number types that fit in 64 bits // (signed or unsigned are all converted to signed) // - float64 for floating point values that fit in a float // - []byte for everything else func Convert(mysqlType int64, val sqltypes.Value) (interface{}, error) { if val.IsNull() { return nil, nil } switch mysqlType { case VT_TINY, VT_SHORT, VT_LONG, VT_LONGLONG, VT_INT24: return strconv.ParseInt(val.String(), 0, 64) case VT_FLOAT, VT_DOUBLE: return strconv.ParseFloat(val.String(), 64) } return val.Raw(), nil }
func (si *SchemaInfo) updateLastChange(createTime sqltypes.Value) { if createTime.IsNull() { return } t, err := strconv.ParseInt(createTime.String(), 10, 64) if err != nil { relog.Warning("Could not parse time %s: %v", createTime.String(), err) return } if si.lastChange.Unix() < t { si.lastChange = time.Unix(t, 0) } }
func validateValue(col *schema.TableColumn, value sqltypes.Value) error { if value.IsNull() { return nil } if sqltypes.IsIntegral(col.Type) { if !value.IsNumeric() { return NewTabletError(ErrFail, vtrpc.ErrorCode_BAD_INPUT, "type mismatch, expecting numeric type for %v for column: %v", value, col) } } else if col.Type == sqltypes.VarBinary { if !value.IsString() { return NewTabletError(ErrFail, vtrpc.ErrorCode_BAD_INPUT, "type mismatch, expecting string type for %v for column: %v", value, col) } } return nil }
func validateValue(col *schema.TableColumn, value sqltypes.Value) { if value.IsNull() { return } switch col.Category { case schema.CAT_NUMBER: if !value.IsNumeric() { panic(NewTabletError(FAIL, "Type mismatch, expecting numeric type for %v", value)) } case schema.CAT_VARBINARY: if !value.IsString() { panic(NewTabletError(FAIL, "Type mismatch, expecting string type for %v", value)) } } }
// AddColumn adds a column to the Table. func (ta *Table) AddColumn(name string, columnType querypb.Type, defval sqltypes.Value, extra string) { index := len(ta.Columns) ta.Columns = append(ta.Columns, TableColumn{Name: strings.ToLower(name)}) ta.Columns[index].Type = columnType if extra == "auto_increment" { ta.Columns[index].IsAuto = true // Ignore default value, if any return } if defval.IsNull() { return } // Schema values are trusted. ta.Columns[index].Default = sqltypes.MakeTrusted(ta.Columns[index].Type, defval.Raw()) }
func validateValue(col *schema.TableColumn, value sqltypes.Value) error { if value.IsNull() { return nil } switch col.Category { case schema.CAT_NUMBER: if !value.IsNumeric() { return NewTabletError(ErrFail, "type mismatch, expecting numeric type for %v for column: %v", value, col) } case schema.CAT_VARBINARY: if !value.IsString() { return NewTabletError(ErrFail, "type mismatch, expecting string type for %v for column: %v", value, col) } } return nil }
// AddColumn adds a column to the Table. func (ta *Table) AddColumn(name string, columnType querypb.Type, defval sqltypes.Value, extra string) { index := len(ta.Columns) ta.Columns = append(ta.Columns, TableColumn{Name: name}) ta.Columns[index].Type = columnType if extra == "auto_increment" { ta.Columns[index].IsAuto = true // Ignore default value, if any return } if defval.IsNull() { return } if sqltypes.IsIntegral(ta.Columns[index].Type) { ta.Columns[index].Default = sqltypes.MakeNumeric(defval.Raw()) } else { ta.Columns[index].Default = sqltypes.MakeString(defval.Raw()) } }
// getWhereClause returns a whereClause based on desired upper and lower // bounds for primary key. func (qs *QuerySplitter) getWhereClause(whereClause *sqlparser.Where, bindVars map[string]interface{}, start, end sqltypes.Value) *sqlparser.Where { var startClause *sqlparser.ComparisonExpr var endClause *sqlparser.ComparisonExpr var clauses sqlparser.BoolExpr // No upper or lower bound, just return the where clause of original query if start.IsNull() && end.IsNull() { return whereClause } pk := &sqlparser.ColName{ Name: sqlparser.SQLName(qs.splitColumn), } if !start.IsNull() { startClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.GreaterEqualStr, Left: pk, Right: sqlparser.ValArg([]byte(":" + startBindVarName)), } bindVars[startBindVarName] = start.ToNative() } // splitColumn < end if !end.IsNull() { endClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.LessThanStr, Left: pk, Right: sqlparser.ValArg([]byte(":" + endBindVarName)), } bindVars[endBindVarName] = end.ToNative() } if startClause == nil { clauses = endClause } else { if endClause == nil { clauses = startClause } else { // splitColumn >= start AND splitColumn < end clauses = &sqlparser.AndExpr{ Left: startClause, Right: endClause, } } } if whereClause != nil { clauses = &sqlparser.AndExpr{ Left: &sqlparser.ParenBoolExpr{Expr: whereClause.Expr}, Right: &sqlparser.ParenBoolExpr{Expr: clauses}, } } return &sqlparser.Where{ Type: sqlparser.WhereStr, Expr: clauses, } }
// getWhereClause returns a whereClause based on desired upper and lower // bounds for primary key. func (qs *QuerySplitter) getWhereClause(start, end sqltypes.Value) *sqlparser.Where { var startClause *sqlparser.ComparisonExpr var endClause *sqlparser.ComparisonExpr var clauses sqlparser.BoolExpr // No upper or lower bound, just return the where clause of original query if start.IsNull() && end.IsNull() { return qs.sel.Where } pk := &sqlparser.ColName{ Name: []byte(qs.splitColumn), } // splitColumn >= start if !start.IsNull() { startClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.AST_GE, Left: pk, Right: sqlparser.NumVal((start).Raw()), } } // splitColumn < end if !end.IsNull() { endClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.AST_LT, Left: pk, Right: sqlparser.NumVal((end).Raw()), } } if startClause == nil { clauses = endClause } else { if endClause == nil { clauses = startClause } else { // splitColumn >= start AND splitColumn < end clauses = &sqlparser.AndExpr{ Left: startClause, Right: endClause, } } } if qs.sel.Where != nil { clauses = &sqlparser.AndExpr{ Left: qs.sel.Where.Expr, Right: clauses, } } return &sqlparser.Where{ Type: sqlparser.AST_WHERE, Expr: clauses, } }
func (ti *TableInfo) computePrefix(conn PoolConnection, createTime sqltypes.Value, hashRegistry map[string]string) string { if createTime.IsNull() { relog.Warning("%s has no time stamp. Will not be cached.", ti.Name) return "" } createTable, err := conn.ExecuteFetch(fmt.Sprintf("show create table %s", ti.Name), 10000, false) if err != nil { relog.Warning("Couldnt read table info: %v", err) return "" } // Normalize & remove auto_increment because it changes on every insert norm1 := strings.ToLower(createTable.Rows[0][1].String()) norm2 := autoIncr.ReplaceAllLiteralString(norm1, "") thash := base64fnv(norm2 + createTime.String()) if _, ok := hashRegistry[thash]; ok { relog.Warning("Hash collision for %s (schema revert?). Will not be cached", ti.Name) return "" } hashRegistry[thash] = ti.Name return thash }
// Convert takes a type and a value, and returns the type: // - nil for NULL value // - uint64 for unsigned BIGINT values // - int64 for all other integer values (signed and unsigned) // - float64 for floating point values that fit in a float // - []byte for everything else func Convert(field Field, val sqltypes.Value) (interface{}, error) { if val.IsNull() { return nil, nil } switch field.Type { case VT_LONGLONG: if field.Flags&VT_UNSIGNED_FLAG == VT_UNSIGNED_FLAG { return strconv.ParseUint(val.String(), 0, 64) } return strconv.ParseInt(val.String(), 0, 64) case VT_TINY, VT_SHORT, VT_LONG, VT_INT24: // Regardless of whether UNSIGNED_FLAG is set in field.Flags, we map all // signed and unsigned values to a signed Go type because // - Go doesn't officially support uint64 in their SQL interface // - there is no loss of the value // The only exception we make are for unsigned BIGINTs, see VT_LONGLONG above. return strconv.ParseInt(val.String(), 0, 64) case VT_FLOAT, VT_DOUBLE: return strconv.ParseFloat(val.String(), 64) } return val.Raw(), nil }
func (ta *Table) AddColumn(name string, columnType string, defval sqltypes.Value, extra string) { index := len(ta.Columns) ta.Columns = append(ta.Columns, TableColumn{Name: name}) if strings.Contains(columnType, "int") { ta.Columns[index].Category = CAT_NUMBER } else if strings.HasPrefix(columnType, "varbinary") { ta.Columns[index].Category = CAT_VARBINARY } else { ta.Columns[index].Category = CAT_OTHER } if extra == "auto_increment" { ta.Columns[index].IsAuto = true // Ignore default value, if any return } if defval.IsNull() { return } if ta.Columns[index].Category == CAT_NUMBER { ta.Columns[index].Default = sqltypes.MakeNumeric(defval.Raw()) } else { ta.Columns[index].Default = sqltypes.MakeString(defval.Raw()) } }
// getWhereClause returns a whereClause based on desired upper and lower // bounds for primary key. func (qs *QuerySplitter) getWhereClause(whereClause *sqlparser.Where, bindVars map[string]interface{}, start, end sqltypes.Value) *sqlparser.Where { var startClause *sqlparser.ComparisonExpr var endClause *sqlparser.ComparisonExpr var clauses sqlparser.BoolExpr // No upper or lower bound, just return the where clause of original query if start.IsNull() && end.IsNull() { return whereClause } pk := &sqlparser.ColName{ Name: sqlparser.SQLName(qs.splitColumn), } if !start.IsNull() { startClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.AST_GE, Left: pk, Right: sqlparser.ValArg([]byte(":" + startBindVarName)), } if start.IsNumeric() { v, _ := start.ParseInt64() bindVars[startBindVarName] = v } else if start.IsString() { bindVars[startBindVarName] = start.Raw() } else if start.IsFractional() { v, _ := start.ParseFloat64() bindVars[startBindVarName] = v } } // splitColumn < end if !end.IsNull() { endClause = &sqlparser.ComparisonExpr{ Operator: sqlparser.AST_LT, Left: pk, Right: sqlparser.ValArg([]byte(":" + endBindVarName)), } if end.IsNumeric() { v, _ := end.ParseInt64() bindVars[endBindVarName] = v } else if end.IsString() { bindVars[endBindVarName] = end.Raw() } else if end.IsFractional() { v, _ := end.ParseFloat64() bindVars[endBindVarName] = v } } if startClause == nil { clauses = endClause } else { if endClause == nil { clauses = startClause } else { // splitColumn >= start AND splitColumn < end clauses = &sqlparser.AndExpr{ Left: startClause, Right: endClause, } } } if whereClause != nil { clauses = &sqlparser.AndExpr{ Left: &sqlparser.ParenBoolExpr{Expr: whereClause.Expr}, Right: &sqlparser.ParenBoolExpr{Expr: clauses}, } } return &sqlparser.Where{ Type: sqlparser.AST_WHERE, Expr: clauses, } }