AdjustValueToType checks that the width (for strings, byte arrays, and bit strings) and scale (decimal). and, shape/srid (for geospatial types) fits the specified column type. Additionally, some precision truncation may occur for the specified column type. In case of decimals, it can truncate frac
(typ *types.T, inVal Datum)
| 6387 | // the width of the value is wider than a single character. For this exception, |
| 6388 | // AdjustValueToType performs the truncation itself. |
| 6389 | func AdjustValueToType(typ *types.T, inVal Datum) (outVal Datum, err error) { |
| 6390 | switch typ.Family() { |
| 6391 | case types.StringFamily, types.CollatedStringFamily: |
| 6392 | var sv string |
| 6393 | if v, ok := AsDString(inVal); ok { |
| 6394 | sv = string(v) |
| 6395 | } else if v, ok := inVal.(*DCollatedString); ok { |
| 6396 | sv = v.Contents |
| 6397 | } |
| 6398 | switch typ.Oid() { |
| 6399 | case oid.T_char: |
| 6400 | // "char" is supposed to truncate long values. |
| 6401 | sv = util.TruncateString(sv, 1) |
| 6402 | case oid.T_bpchar: |
| 6403 | // bpchar types truncate trailing whitespace. |
| 6404 | sv = strings.TrimRight(sv, " ") |
| 6405 | } |
| 6406 | |
| 6407 | var overlength int |
| 6408 | // Fast path. Check for skip counting the number of runes through iteration. |
| 6409 | if typ.Width() > 0 && len(sv) > int(typ.Width()) { |
| 6410 | overlength = utf8.RuneCountInString(sv) - int(typ.Width()) |
| 6411 | } else { |
| 6412 | overlength = 0 |
| 6413 | } |
| 6414 | if typ.Oid() == oid.T_varchar { |
| 6415 | // varchar types truncate extra trailing whitespace when |
| 6416 | // more characters than the varchar size are provided. |
| 6417 | for overlength > 0 { |
| 6418 | if sv[len(sv)-1] != ' ' { |
| 6419 | break |
| 6420 | } |
| 6421 | sv = sv[:len(sv)-1] |
| 6422 | overlength-- |
| 6423 | } |
| 6424 | } |
| 6425 | if overlength > 0 { |
| 6426 | return nil, pgerror.Newf(pgcode.StringDataRightTruncation, |
| 6427 | "value too long for type %s", |
| 6428 | typ.SQLString()) |
| 6429 | } |
| 6430 | |
| 6431 | if typ.Oid() == oid.T_bpchar || typ.Oid() == oid.T_char || typ.Oid() == oid.T_varchar { |
| 6432 | if _, ok := AsDString(inVal); ok { |
| 6433 | return NewDString(sv), nil |
| 6434 | } else if _, ok := inVal.(*DCollatedString); ok { |
| 6435 | return NewDCollatedString(sv, typ.Locale(), &CollationEnvironment{}) |
| 6436 | } |
| 6437 | } |
| 6438 | case types.IntFamily: |
| 6439 | if v, ok := AsDInt(inVal); ok { |
| 6440 | if typ.Width() == 32 || typ.Width() == 16 { |
| 6441 | // Width is defined in bits. |
| 6442 | width := uint(typ.Width() - 1) |
| 6443 | |
| 6444 | // We're performing range checks in line with Go's |
| 6445 | // implementation of math.(Max|Min)(16|32) numbers that store |
| 6446 | // the boundaries of the allowed range. |
no test coverage detected
searching dependent graphs…