in sources/postgres/infoschema.go [552:656]
func cvtSQLScalar(conv *internal.Conv, srcCd schema.Column, spCd ddl.ColumnDef, val interface{}) (interface{}, error) {
switch spCd.T.Name {
case ddl.Bool:
switch v := val.(type) {
case bool:
return v, nil
case string:
return convBool(v)
}
case ddl.Bytes:
switch v := val.(type) {
case []byte:
return v, nil
}
case ddl.Date:
// The PostgreSQL driver uses time.Time to represent
// dates. Note that the database/sql library doesn't
// document how dates are represented, so maybe this
// isn't a driver issue, but a generic database/sql
// issue. We explicitly convert from time.Time to
// civil.Date (used by the Spanner client library).
switch v := val.(type) {
case string:
return convDate(v)
case time.Time:
return civil.DateOf(v), nil
}
case ddl.Int64:
switch v := val.(type) {
case []byte: // Parse as int64.
return convInt64(string(v))
case int64:
return v, nil
case float32: // Truncate.
return int64(v), nil
case float64: // Truncate.
return int64(v), nil
case string: // Parse as int64.
return convInt64(v)
}
case ddl.Float32:
switch v := val.(type) {
case []byte: // Note: PostgreSQL uses []byte for numeric.
return convFloat32(string(v))
case int64:
return float32(v), nil
case float32:
return v, nil
case float64:
return float32(v), nil
case string:
return convFloat32(v)
}
case ddl.Float64:
switch v := val.(type) {
case []byte: // Note: PostgreSQL uses []byte for numeric.
return convFloat64(string(v))
case int64:
return float64(v), nil
case float32:
return float64(v), nil
case float64:
return v, nil
case string:
return convFloat64(v)
}
case ddl.Numeric:
switch v := val.(type) {
case []byte: // Note: PostgreSQL uses []byte for numeric.
return convNumeric(conv, string(v))
}
case ddl.String:
switch v := val.(type) {
case bool:
return strconv.FormatBool(v), nil
case []byte:
return string(v), nil
case int64:
return strconv.FormatInt(v, 10), nil
case float32:
return strconv.FormatFloat(float64(v), 'g', -1, 32), nil
case float64:
return strconv.FormatFloat(v, 'g', -1, 64), nil
case string:
return v, nil
case time.Time:
return v.String(), nil
}
case ddl.Timestamp:
switch v := val.(type) {
case string:
return convTimestamp(srcCd.Type.Name, conv.Location, v)
case time.Time:
return v, nil
}
case ddl.JSON:
switch v := val.(type) {
case string:
return string(v), nil
case []uint8:
return string(v), nil
}
}
return nil, fmt.Errorf("can't convert value of type %s to Spanner type %s", reflect.TypeOf(val), reflect.TypeOf(spCd.T))
}