diff --git a/pkg/sql/colexec/colexecbase/cast.eg.go b/pkg/sql/colexec/colexecbase/cast.eg.go index 7507dd6d39c3..9d41c398fb09 100644 --- a/pkg/sql/colexec/colexecbase/cast.eg.go +++ b/pkg/sql/colexec/colexecbase/cast.eg.go @@ -17,6 +17,7 @@ import ( "strconv" "strings" "time" + "unicode/utf8" "github.com/cockroachdb/apd/v3" "github.com/cockroachdb/cockroach/pkg/col/coldata" @@ -205,6 +206,12 @@ func GetCastOperator( default: return &castBoolIntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castBoolStringOp{castOpBase: base}, nil + } } } case types.BytesFamily: @@ -212,6 +219,12 @@ func GetCastOperator( case -1: default: switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castBytesStringOp{castOpBase: base}, nil + } case types.UuidFamily: switch toType.Width() { case -1: @@ -247,6 +260,12 @@ func GetCastOperator( default: return &castDateIntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castDateStringOp{castOpBase: base}, nil + } } } case types.DecimalFamily: @@ -282,6 +301,12 @@ func GetCastOperator( default: return &castDecimalIntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castDecimalStringOp{castOpBase: base}, nil + } } } case types.FloatFamily: @@ -311,6 +336,12 @@ func GetCastOperator( default: return &castFloatIntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castFloatStringOp{castOpBase: base}, nil + } } } case types.IntFamily: @@ -343,6 +374,12 @@ func GetCastOperator( default: return &castInt2IntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castInt2StringOp{castOpBase: base}, nil + } } case 32: switch toType.Family() { @@ -372,6 +409,12 @@ func GetCastOperator( default: return &castInt4IntOp{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castInt4StringOp{castOpBase: base}, nil + } } case -1: default: @@ -401,6 +444,25 @@ func GetCastOperator( case 32: return &castIntInt4Op{castOpBase: base}, nil } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castIntStringOp{castOpBase: base}, nil + } + } + } + case types.IntervalFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castIntervalStringOp{castOpBase: base}, nil + } } } case types.JsonFamily: @@ -499,6 +561,45 @@ func GetCastOperator( } } } + case types.TimestampFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castTimestampStringOp{castOpBase: base}, nil + } + } + } + case types.TimestampTZFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castTimestamptzStringOp{castOpBase: base}, nil + } + } + } + case types.UuidFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return &castUuidStringOp{castOpBase: base}, nil + } + } + } } } return nil, errors.Errorf("unhandled cast %s -> %s", fromType.SQLString(), toType.SQLString()) @@ -621,6 +722,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } } case types.BytesFamily: @@ -628,6 +735,12 @@ func IsCastSupported(fromType, toType *types.T) bool { case -1: default: switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } case types.UuidFamily: switch toType.Width() { case -1: @@ -663,6 +776,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } } case types.DecimalFamily: @@ -698,6 +817,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } } case types.FloatFamily: @@ -727,6 +852,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } } case types.IntFamily: @@ -759,6 +890,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } case 32: switch toType.Family() { @@ -788,6 +925,12 @@ func IsCastSupported(fromType, toType *types.T) bool { default: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } case -1: default: @@ -817,6 +960,25 @@ func IsCastSupported(fromType, toType *types.T) bool { case 32: return true } + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } + } + } + case types.IntervalFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } } } case types.JsonFamily: @@ -915,6 +1077,45 @@ func IsCastSupported(fromType, toType *types.T) bool { } } } + case types.TimestampFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } + } + } + case types.TimestampTZFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } + } + } + case types.UuidFamily: + switch fromType.Width() { + case -1: + default: + switch toType.Family() { + case types.StringFamily: + switch toType.Width() { + case -1: + default: + return true + } + } + } } } return false @@ -927,6 +1128,7 @@ type castOpBase struct { colIdx int outputIdx int evalCtx *eval.Context + buf bytes.Buffer } func (c *castOpBase) Reset(ctx context.Context) { @@ -1164,9 +1366,13 @@ func (c *castBoolFloatOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1186,9 +1392,13 @@ func (c *castBoolFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1214,9 +1424,13 @@ func (c *castBoolFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1236,9 +1450,13 @@ func (c *castBoolFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1296,9 +1514,13 @@ func (c *castBoolInt2Op) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1318,9 +1540,13 @@ func (c *castBoolInt2Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1346,9 +1572,13 @@ func (c *castBoolInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1368,9 +1598,13 @@ func (c *castBoolInt2Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1428,9 +1662,13 @@ func (c *castBoolInt4Op) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1450,9 +1688,13 @@ func (c *castBoolInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1478,9 +1720,13 @@ func (c *castBoolInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1500,9 +1746,13 @@ func (c *castBoolInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1560,9 +1810,13 @@ func (c *castBoolIntOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1582,9 +1836,13 @@ func (c *castBoolIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1610,9 +1868,13 @@ func (c *castBoolIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1632,9 +1894,13 @@ func (c *castBoolIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -1663,14 +1929,14 @@ func (c *castBoolIntOp) Next() coldata.Batch { return batch } -type castBytesUuidOp struct { +type castBoolStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castBytesUuidOp{} -var _ colexecop.ClosableOperator = &castBytesUuidOp{} +var _ colexecop.ResettableOperator = &castBoolStringOp{} +var _ colexecop.ClosableOperator = &castBoolStringOp{} -func (c *castBytesUuidOp) Next() coldata.Batch { +func (c *castBoolStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -1684,7 +1950,7 @@ func (c *castBytesUuidOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Bool() inputNulls := inputVec.Nulls() outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() @@ -1692,9 +1958,13 @@ func (c *castBytesUuidOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1704,34 +1974,74 @@ func (c *castBytesUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromBytes(v) - if err != nil { - colexecerror.ExpectedError(err) - } - r = _uuid.GetBytes() - - outputCol.Set(tupleIdx, r) - } - } - } else { - { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + r = []byte(strconv.FormatBool(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromBytes(v) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(strconv.FormatBool(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } @@ -1740,9 +2050,13 @@ func (c *castBytesUuidOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1752,34 +2066,74 @@ func (c *castBytesUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromBytes(v) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(strconv.FormatBool(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromBytes(v) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(strconv.FormatBool(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } @@ -1791,14 +2145,14 @@ func (c *castBytesUuidOp) Next() coldata.Batch { return batch } -type castDateDecimalOp struct { +type castBytesStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDateDecimalOp{} -var _ colexecop.ClosableOperator = &castDateDecimalOp{} +var _ colexecop.ResettableOperator = &castBytesStringOp{} +var _ colexecop.ClosableOperator = &castBytesStringOp{} -func (c *castDateDecimalOp) Next() coldata.Batch { +func (c *castBytesStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -1812,17 +2166,21 @@ func (c *castDateDecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Bytes() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1830,12 +2188,31 @@ func (c *castDateDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r []byte - r.SetInt64(int64(v)) + _format := evalCtx.SessionData().DataConversionConfig.BytesEncodeFormat + r = []byte(lex.EncodeByteArrayToRawBytes(string(v), _format, false /* skipHexPrefix */)) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -1843,28 +2220,47 @@ func (c *castDateDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } - //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r []byte - r.SetInt64(int64(v)) + _format := evalCtx.SessionData().DataConversionConfig.BytesEncodeFormat + r = []byte(lex.EncodeByteArrayToRawBytes(string(v), _format, false /* skipHexPrefix */)) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -1872,9 +2268,13 @@ func (c *castDateDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1882,12 +2282,31 @@ func (c *castDateDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r []byte - r.SetInt64(int64(v)) + _format := evalCtx.SessionData().DataConversionConfig.BytesEncodeFormat + r = []byte(lex.EncodeByteArrayToRawBytes(string(v), _format, false /* skipHexPrefix */)) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -1895,28 +2314,47 @@ func (c *castDateDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } - //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r []byte - r.SetInt64(int64(v)) + _format := evalCtx.SessionData().DataConversionConfig.BytesEncodeFormat + r = []byte(lex.EncodeByteArrayToRawBytes(string(v), _format, false /* skipHexPrefix */)) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -1927,14 +2365,14 @@ func (c *castDateDecimalOp) Next() coldata.Batch { return batch } -type castDateFloatOp struct { +type castBytesUuidOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDateFloatOp{} -var _ colexecop.ClosableOperator = &castDateFloatOp{} +var _ colexecop.ResettableOperator = &castBytesUuidOp{} +var _ colexecop.ClosableOperator = &castBytesUuidOp{} -func (c *castDateFloatOp) Next() coldata.Batch { +func (c *castBytesUuidOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -1948,17 +2386,21 @@ func (c *castDateFloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Bytes() inputNulls := inputVec.Nulls() - outputCol := outputVec.Float64() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -1966,33 +2408,41 @@ func (c *castDateFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - r = float64(v) + _uuid, err := uuid.FromBytes(v) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } - //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - r = float64(v) + _uuid, err := uuid.FromBytes(v) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _uuid.GetBytes() - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -2000,9 +2450,13 @@ func (c *castDateFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2010,33 +2464,41 @@ func (c *castDateFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - r = float64(v) + _uuid, err := uuid.FromBytes(v) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } - //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - r = float64(v) + _uuid, err := uuid.FromBytes(v) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _uuid.GetBytes() - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -2047,14 +2509,14 @@ func (c *castDateFloatOp) Next() coldata.Batch { return batch } -type castDateInt2Op struct { +type castDateDecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDateInt2Op{} -var _ colexecop.ClosableOperator = &castDateInt2Op{} +var _ colexecop.ResettableOperator = &castDateDecimalOp{} +var _ colexecop.ClosableOperator = &castDateDecimalOp{} -func (c *castDateInt2Op) Next() coldata.Batch { +func (c *castDateDecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2070,15 +2532,19 @@ func (c *castDateInt2Op) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2086,22 +2552,26 @@ func (c *castDateInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r apd.Decimal - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } - r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2112,13 +2582,13 @@ func (c *castDateInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r apd.Decimal - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } - r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -2128,9 +2598,13 @@ func (c *castDateInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2138,22 +2612,26 @@ func (c *castDateInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r apd.Decimal - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } - r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2164,13 +2642,13 @@ func (c *castDateInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r apd.Decimal - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } - r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -2183,14 +2661,14 @@ func (c *castDateInt2Op) Next() coldata.Batch { return batch } -type castDateInt4Op struct { +type castDateFloatOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDateInt4Op{} -var _ colexecop.ClosableOperator = &castDateInt4Op{} +var _ colexecop.ResettableOperator = &castDateFloatOp{} +var _ colexecop.ClosableOperator = &castDateFloatOp{} -func (c *castDateInt4Op) Next() coldata.Batch { +func (c *castDateFloatOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2206,15 +2684,19 @@ func (c *castDateInt4Op) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Float64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2222,22 +2704,22 @@ func (c *castDateInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r float64 - shifted := v >> uint(31) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(v) + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2248,13 +2730,9 @@ func (c *castDateInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r float64 - shifted := v >> uint(31) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(v) + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -2264,9 +2742,13 @@ func (c *castDateInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2274,22 +2756,22 @@ func (c *castDateInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r float64 - shifted := v >> uint(31) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(v) + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2300,13 +2782,9 @@ func (c *castDateInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r float64 - shifted := v >> uint(31) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(v) + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -2319,14 +2797,14 @@ func (c *castDateInt4Op) Next() coldata.Batch { return batch } -type castDateIntOp struct { +type castDateInt2Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castDateIntOp{} -var _ colexecop.ClosableOperator = &castDateIntOp{} +var _ colexecop.ResettableOperator = &castDateInt2Op{} +var _ colexecop.ClosableOperator = &castDateInt2Op{} -func (c *castDateIntOp) Next() coldata.Batch { +func (c *castDateInt2Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2342,15 +2820,19 @@ func (c *castDateIntOp) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Int16() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2358,16 +2840,26 @@ func (c *castDateIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r int16 + + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2378,8 +2870,14 @@ func (c *castDateIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r int16 + + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2388,9 +2886,13 @@ func (c *castDateIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2398,16 +2900,26 @@ func (c *castDateIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r int16 + + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2418,8 +2930,14 @@ func (c *castDateIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r int16 + + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2431,14 +2949,14 @@ func (c *castDateIntOp) Next() coldata.Batch { return batch } -type castDecimalBoolOp struct { +type castDateInt4Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalBoolOp{} -var _ colexecop.ClosableOperator = &castDecimalBoolOp{} +var _ colexecop.ResettableOperator = &castDateInt4Op{} +var _ colexecop.ClosableOperator = &castDateInt4Op{} -func (c *castDecimalBoolOp) Next() coldata.Batch { +func (c *castDateInt4Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2452,17 +2970,21 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Decimal() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bool() + outputCol := outputVec.Int32() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2470,16 +2992,26 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool - r = v.Sign() != 0 + var r int32 + + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2490,8 +3022,14 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool - r = v.Sign() != 0 + var r int32 + + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2500,9 +3038,13 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2510,16 +3052,26 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool - r = v.Sign() != 0 + var r int32 + + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2530,8 +3082,14 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool - r = v.Sign() != 0 + var r int32 + + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2543,14 +3101,14 @@ func (c *castDecimalBoolOp) Next() coldata.Batch { return batch } -type castDecimalDecimalOp struct { +type castDateIntOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalDecimalOp{} -var _ colexecop.ClosableOperator = &castDecimalDecimalOp{} +var _ colexecop.ResettableOperator = &castDateIntOp{} +var _ colexecop.ClosableOperator = &castDateIntOp{} -func (c *castDecimalDecimalOp) Next() coldata.Batch { +func (c *castDateIntOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2564,17 +3122,21 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Decimal() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Int64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2582,21 +3144,20 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.Set(&v) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } - + var r int64 + r = int64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2607,13 +3168,8 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.Set(&v) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } - + var r int64 + r = int64(v) //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2622,9 +3178,13 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2632,21 +3192,20 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.Set(&v) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } - + var r int64 + r = int64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2657,13 +3216,8 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.Set(&v) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } - + var r int64 + r = int64(v) //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2675,14 +3229,14 @@ func (c *castDecimalDecimalOp) Next() coldata.Batch { return batch } -type castDecimalFloatOp struct { +type castDateStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalFloatOp{} -var _ colexecop.ClosableOperator = &castDecimalFloatOp{} +var _ colexecop.ResettableOperator = &castDateStringOp{} +var _ colexecop.ClosableOperator = &castDateStringOp{} -func (c *castDecimalFloatOp) Next() coldata.Batch { +func (c *castDateStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2696,17 +3250,21 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Decimal() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Float64() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2714,14 +3272,33 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - { - f, err := v.Float64() - if err != nil { - colexecerror.ExpectedError(tree.ErrFloatOutOfRange) + _date := pgdate.MakeCompatibleDateFromDisk(v) + buf.Reset() + _date.Format(buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") } - r = f + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -2729,11 +3306,14 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -2742,17 +3322,35 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - { - f, err := v.Float64() - if err != nil { - colexecerror.ExpectedError(tree.ErrFloatOutOfRange) + _date := pgdate.MakeCompatibleDateFromDisk(v) + buf.Reset() + _date.Format(buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) } - r = f + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -2760,9 +3358,13 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2770,14 +3372,33 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - { - f, err := v.Float64() - if err != nil { - colexecerror.ExpectedError(tree.ErrFloatOutOfRange) + _date := pgdate.MakeCompatibleDateFromDisk(v) + buf.Reset() + _date.Format(buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") } - r = f + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -2785,11 +3406,14 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -2798,17 +3422,35 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r []byte - { - f, err := v.Float64() - if err != nil { - colexecerror.ExpectedError(tree.ErrFloatOutOfRange) + _date := pgdate.MakeCompatibleDateFromDisk(v) + buf.Reset() + _date.Format(buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) } - r = f + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -2819,14 +3461,14 @@ func (c *castDecimalFloatOp) Next() coldata.Batch { return batch } -type castDecimalInt2Op struct { +type castDecimalBoolOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalInt2Op{} -var _ colexecop.ClosableOperator = &castDecimalInt2Op{} +var _ colexecop.ResettableOperator = &castDecimalBoolOp{} +var _ colexecop.ClosableOperator = &castDecimalBoolOp{} -func (c *castDecimalInt2Op) Next() coldata.Batch { +func (c *castDecimalBoolOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -2842,15 +3484,19 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Bool() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2858,35 +3504,20 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) - - } - + var r bool + r = v.Sign() != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2897,27 +3528,8 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) - - } - + var r bool + r = v.Sign() != 0 //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -2926,9 +3538,13 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -2936,35 +3552,20 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) - - } - + var r bool + r = v.Sign() != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -2975,27 +3576,8 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) - - } - + var r bool + r = v.Sign() != 0 //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -3007,14 +3589,14 @@ func (c *castDecimalInt2Op) Next() coldata.Batch { return batch } -type castDecimalInt4Op struct { +type castDecimalDecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalInt4Op{} -var _ colexecop.ClosableOperator = &castDecimalInt4Op{} +var _ colexecop.ResettableOperator = &castDecimalDecimalOp{} +var _ colexecop.ClosableOperator = &castDecimalDecimalOp{} -func (c *castDecimalInt4Op) Next() coldata.Batch { +func (c *castDecimalDecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3030,15 +3612,19 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. - _ = evalCtx + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3046,25 +3632,11 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(_i) + var r apd.Decimal + r.Set(&v) + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } outputCol.Set(tupleIdx, r) @@ -3072,9 +3644,13 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3085,25 +3661,11 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(_i) + var r apd.Decimal + r.Set(&v) + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } //gcassert:bce @@ -3114,9 +3676,13 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3124,25 +3690,11 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(_i) + var r apd.Decimal + r.Set(&v) + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } outputCol.Set(tupleIdx, r) @@ -3150,9 +3702,13 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3163,25 +3719,11 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 - - { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() - if err != nil { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) - } - r = int32(_i) + var r apd.Decimal + r.Set(&v) + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) } //gcassert:bce @@ -3195,14 +3737,14 @@ func (c *castDecimalInt4Op) Next() coldata.Batch { return batch } -type castDecimalIntOp struct { +type castDecimalFloatOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castDecimalIntOp{} -var _ colexecop.ClosableOperator = &castDecimalIntOp{} +var _ colexecop.ResettableOperator = &castDecimalFloatOp{} +var _ colexecop.ClosableOperator = &castDecimalFloatOp{} -func (c *castDecimalIntOp) Next() coldata.Batch { +func (c *castDecimalFloatOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3218,15 +3760,19 @@ func (c *castDecimalIntOp) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Float64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3234,19 +3780,14 @@ func (c *castDecimalIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r float64 { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() + f, err := v.Float64() if err != nil { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + colexecerror.ExpectedError(tree.ErrFloatOutOfRange) } - r = int64(_i) + r = f } outputCol.Set(tupleIdx, r) @@ -3254,9 +3795,13 @@ func (c *castDecimalIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3267,19 +3812,14 @@ func (c *castDecimalIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r float64 { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() + f, err := v.Float64() if err != nil { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + colexecerror.ExpectedError(tree.ErrFloatOutOfRange) } - r = int64(_i) + r = f } //gcassert:bce @@ -3290,9 +3830,13 @@ func (c *castDecimalIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3300,19 +3844,14 @@ func (c *castDecimalIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r float64 { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() + f, err := v.Float64() if err != nil { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + colexecerror.ExpectedError(tree.ErrFloatOutOfRange) } - r = int64(_i) + r = f } outputCol.Set(tupleIdx, r) @@ -3320,9 +3859,13 @@ func (c *castDecimalIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3333,19 +3876,14 @@ func (c *castDecimalIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r float64 { - var tmpDec apd.Decimal //gcassert:noescape - _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) - if err != nil { - colexecerror.ExpectedError(err) - } - _i, err := tmpDec.Int64() + f, err := v.Float64() if err != nil { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + colexecerror.ExpectedError(tree.ErrFloatOutOfRange) } - r = int64(_i) + r = f } //gcassert:bce @@ -3359,14 +3897,14 @@ func (c *castDecimalIntOp) Next() coldata.Batch { return batch } -type castFloatBoolOp struct { +type castDecimalInt2Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castFloatBoolOp{} -var _ colexecop.ClosableOperator = &castFloatBoolOp{} +var _ colexecop.ResettableOperator = &castDecimalInt2Op{} +var _ colexecop.ClosableOperator = &castDecimalInt2Op{} -func (c *castFloatBoolOp) Next() coldata.Batch { +func (c *castDecimalInt2Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3380,17 +3918,21 @@ func (c *castFloatBoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Float64() + inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bool() + outputCol := outputVec.Int16() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3398,18 +3940,39 @@ func (c *castFloatBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r int16 - r = v != 0 + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3420,9 +3983,26 @@ func (c *castFloatBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r int16 - r = v != 0 + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -3432,9 +4012,13 @@ func (c *castFloatBoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3442,18 +4026,39 @@ func (c *castFloatBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r int16 - r = v != 0 + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } - outputCol.Set(tupleIdx, r) - } - } - } else { - { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3464,9 +4069,26 @@ func (c *castFloatBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r int16 - r = v != 0 + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -3479,14 +4101,14 @@ func (c *castFloatBoolOp) Next() coldata.Batch { return batch } -type castFloatDecimalOp struct { +type castDecimalInt4Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castFloatDecimalOp{} -var _ colexecop.ClosableOperator = &castFloatDecimalOp{} +var _ colexecop.ResettableOperator = &castDecimalInt4Op{} +var _ colexecop.ClosableOperator = &castDecimalInt4Op{} -func (c *castFloatDecimalOp) Next() coldata.Batch { +func (c *castDecimalInt4Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3500,17 +4122,21 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Float64() + inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Int32() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3518,14 +4144,25 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r int32 - if _, err := r.SetFloat64(float64(v)); err != nil { - colexecerror.ExpectedError(err) - } + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) } outputCol.Set(tupleIdx, r) @@ -3533,9 +4170,13 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3546,14 +4187,25 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r int32 - if _, err := r.SetFloat64(float64(v)); err != nil { - colexecerror.ExpectedError(err) - } + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) } //gcassert:bce @@ -3564,9 +4216,13 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3574,14 +4230,25 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r int32 - if _, err := r.SetFloat64(float64(v)); err != nil { - colexecerror.ExpectedError(err) - } + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) } outputCol.Set(tupleIdx, r) @@ -3589,9 +4256,13 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3602,14 +4273,25 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r int32 - if _, err := r.SetFloat64(float64(v)); err != nil { - colexecerror.ExpectedError(err) - } + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) } //gcassert:bce @@ -3623,14 +4305,14 @@ func (c *castFloatDecimalOp) Next() coldata.Batch { return batch } -type castFloatInt2Op struct { +type castDecimalIntOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castFloatInt2Op{} -var _ colexecop.ClosableOperator = &castFloatInt2Op{} +var _ colexecop.ResettableOperator = &castDecimalIntOp{} +var _ colexecop.ClosableOperator = &castDecimalIntOp{} -func (c *castFloatInt2Op) Next() coldata.Batch { +func (c *castDecimalIntOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3644,17 +4326,21 @@ func (c *castFloatInt2Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Float64() + inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Int64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3662,21 +4348,33 @@ func (c *castFloatInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r int64 - if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(_i) } - r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3687,12 +4385,20 @@ func (c *castFloatInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r int64 - if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(_i) } - r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -3702,9 +4408,13 @@ func (c *castFloatInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3712,21 +4422,33 @@ func (c *castFloatInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r int64 - if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(_i) } - r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3737,12 +4459,20 @@ func (c *castFloatInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r int64 - if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + { + var tmpDec apd.Decimal //gcassert:noescape + _, err := tree.DecimalCtx.RoundToIntegralValue(&tmpDec, &v) + if err != nil { + colexecerror.ExpectedError(err) + } + _i, err := tmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(_i) } - r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -3755,14 +4485,14 @@ func (c *castFloatInt2Op) Next() coldata.Batch { return batch } -type castFloatInt4Op struct { +type castDecimalStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castFloatInt4Op{} -var _ colexecop.ClosableOperator = &castFloatInt4Op{} +var _ colexecop.ResettableOperator = &castDecimalStringOp{} +var _ colexecop.ClosableOperator = &castDecimalStringOp{} -func (c *castFloatInt4Op) Next() coldata.Batch { +func (c *castDecimalStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3776,17 +4506,21 @@ func (c *castFloatInt4Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Float64() + inputCol := inputVec.Decimal() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3794,23 +4528,44 @@ func (c *castFloatInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) - } - r = int32(v) + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -3819,14 +4574,31 @@ func (c *castFloatInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = int32(v) - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -3834,9 +4606,13 @@ func (c *castFloatInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3844,23 +4620,44 @@ func (c *castFloatInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -3869,14 +4666,31 @@ func (c *castFloatInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - r = int32(v) - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -3887,14 +4701,14 @@ func (c *castFloatInt4Op) Next() coldata.Batch { return batch } -type castFloatIntOp struct { +type castFloatBoolOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castFloatIntOp{} -var _ colexecop.ClosableOperator = &castFloatIntOp{} +var _ colexecop.ResettableOperator = &castFloatBoolOp{} +var _ colexecop.ClosableOperator = &castFloatBoolOp{} -func (c *castFloatIntOp) Next() coldata.Batch { +func (c *castFloatBoolOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -3910,15 +4724,19 @@ func (c *castFloatIntOp) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Bool() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3926,21 +4744,22 @@ func (c *castFloatIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r bool - if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) - } - r = int64(v) + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -3951,12 +4770,9 @@ func (c *castFloatIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r bool - if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) - } - r = int64(v) + r = v != 0 //gcassert:bce outputCol.Set(tupleIdx, r) @@ -3966,9 +4782,13 @@ func (c *castFloatIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -3976,21 +4796,22 @@ func (c *castFloatIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r bool - if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) - } - r = int64(v) + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4001,12 +4822,9 @@ func (c *castFloatIntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r bool - if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { - colexecerror.ExpectedError(tree.ErrIntOutOfRange) - } - r = int64(v) + r = v != 0 //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4019,14 +4837,14 @@ func (c *castFloatIntOp) Next() coldata.Batch { return batch } -type castInt2BoolOp struct { +type castFloatDecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt2BoolOp{} -var _ colexecop.ClosableOperator = &castInt2BoolOp{} +var _ colexecop.ResettableOperator = &castFloatDecimalOp{} +var _ colexecop.ClosableOperator = &castFloatDecimalOp{} -func (c *castInt2BoolOp) Next() coldata.Batch { +func (c *castFloatDecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4040,17 +4858,21 @@ func (c *castInt2BoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int16() + inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bool() + outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4058,18 +4880,28 @@ func (c *castInt2BoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r apd.Decimal - r = v != 0 + if _, err := r.SetFloat64(float64(v)); err != nil { + colexecerror.ExpectedError(err) + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4080,9 +4912,15 @@ func (c *castInt2BoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r apd.Decimal - r = v != 0 + if _, err := r.SetFloat64(float64(v)); err != nil { + colexecerror.ExpectedError(err) + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4092,9 +4930,13 @@ func (c *castInt2BoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4102,18 +4944,28 @@ func (c *castInt2BoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r apd.Decimal - r = v != 0 + if _, err := r.SetFloat64(float64(v)); err != nil { + colexecerror.ExpectedError(err) + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4124,9 +4976,15 @@ func (c *castInt2BoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r apd.Decimal - r = v != 0 + if _, err := r.SetFloat64(float64(v)); err != nil { + colexecerror.ExpectedError(err) + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4139,14 +4997,14 @@ func (c *castInt2BoolOp) Next() coldata.Batch { return batch } -type castInt2DecimalOp struct { +type castFloatInt2Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt2DecimalOp{} -var _ colexecop.ClosableOperator = &castInt2DecimalOp{} +var _ colexecop.ResettableOperator = &castFloatInt2Op{} +var _ colexecop.ClosableOperator = &castFloatInt2Op{} -func (c *castInt2DecimalOp) Next() coldata.Batch { +func (c *castFloatInt2Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4160,17 +5018,21 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int16() + inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Int16() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4178,22 +5040,25 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r int16 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) } + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4204,13 +5069,12 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r int16 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) } + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4220,9 +5084,13 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4230,22 +5098,25 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r int16 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) } + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4256,13 +5127,12 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r int16 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt16) || v >= float64(math.MaxInt16) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) } + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4275,14 +5145,14 @@ func (c *castInt2DecimalOp) Next() coldata.Batch { return batch } -type castInt2FloatOp struct { +type castFloatInt4Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt2FloatOp{} -var _ colexecop.ClosableOperator = &castInt2FloatOp{} +var _ colexecop.ResettableOperator = &castFloatInt4Op{} +var _ colexecop.ClosableOperator = &castFloatInt4Op{} -func (c *castInt2FloatOp) Next() coldata.Batch { +func (c *castFloatInt4Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4296,17 +5166,21 @@ func (c *castInt2FloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int16() + inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Float64() + outputCol := outputVec.Int32() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4314,18 +5188,25 @@ func (c *castInt2FloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r int32 - r = float64(v) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4336,9 +5217,12 @@ func (c *castInt2FloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r int32 - r = float64(v) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4348,9 +5232,13 @@ func (c *castInt2FloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4358,18 +5246,25 @@ func (c *castInt2FloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r int32 - r = float64(v) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4380,9 +5275,12 @@ func (c *castInt2FloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r int32 - r = float64(v) + if math.IsNaN(float64(v)) || v <= float64(math.MinInt32) || v >= float64(math.MaxInt32) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -4395,14 +5293,14 @@ func (c *castInt2FloatOp) Next() coldata.Batch { return batch } -type castInt2Int4Op struct { +type castFloatIntOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt2Int4Op{} -var _ colexecop.ClosableOperator = &castInt2Int4Op{} +var _ colexecop.ResettableOperator = &castFloatIntOp{} +var _ colexecop.ClosableOperator = &castFloatIntOp{} -func (c *castInt2Int4Op) Next() coldata.Batch { +func (c *castFloatIntOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4416,17 +5314,21 @@ func (c *castInt2Int4Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int16() + inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Int64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4434,16 +5336,25 @@ func (c *castInt2Int4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 - r = int32(v) + var r int64 + + if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4454,8 +5365,13 @@ func (c *castInt2Int4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 - r = int32(v) + var r int64 + + if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -4464,9 +5380,13 @@ func (c *castInt2Int4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4474,16 +5394,25 @@ func (c *castInt2Int4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 - r = int32(v) + var r int64 + + if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(v) + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4494,8 +5423,13 @@ func (c *castInt2Int4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 - r = int32(v) + var r int64 + + if math.IsNaN(float64(v)) || v <= float64(math.MinInt64) || v >= float64(math.MaxInt64) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + r = int64(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -4507,14 +5441,14 @@ func (c *castInt2Int4Op) Next() coldata.Batch { return batch } -type castInt2IntOp struct { +type castFloatStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt2IntOp{} -var _ colexecop.ClosableOperator = &castInt2IntOp{} +var _ colexecop.ResettableOperator = &castFloatStringOp{} +var _ colexecop.ClosableOperator = &castFloatStringOp{} -func (c *castInt2IntOp) Next() coldata.Batch { +func (c *castFloatStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4528,17 +5462,21 @@ func (c *castInt2IntOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int16() + inputCol := inputVec.Float64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4546,18 +5484,46 @@ func (c *castInt2IntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r []byte + + dcc := evalCtx.SessionData().DataConversionConfig + r = tree.PgwireFormatFloat(nil /* buf */, v, dcc, types.Float) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -4566,9 +5532,33 @@ func (c *castInt2IntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) - //gcassert:bce + var r []byte + + dcc := evalCtx.SessionData().DataConversionConfig + r = tree.PgwireFormatFloat(nil /* buf */, v, dcc, types.Float) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + outputCol.Set(tupleIdx, r) } } @@ -4576,9 +5566,13 @@ func (c *castInt2IntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4586,18 +5580,46 @@ func (c *castInt2IntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) + var r []byte + + dcc := evalCtx.SessionData().DataConversionConfig + r = tree.PgwireFormatFloat(nil /* buf */, v, dcc, types.Float) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -4606,9 +5628,33 @@ func (c *castInt2IntOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 - r = int64(v) - //gcassert:bce + var r []byte + + dcc := evalCtx.SessionData().DataConversionConfig + r = tree.PgwireFormatFloat(nil /* buf */, v, dcc, types.Float) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + outputCol.Set(tupleIdx, r) } } @@ -4619,14 +5665,14 @@ func (c *castInt2IntOp) Next() coldata.Batch { return batch } -type castInt4BoolOp struct { +type castInt2BoolOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt4BoolOp{} -var _ colexecop.ClosableOperator = &castInt4BoolOp{} +var _ colexecop.ResettableOperator = &castInt2BoolOp{} +var _ colexecop.ClosableOperator = &castInt2BoolOp{} -func (c *castInt4BoolOp) Next() coldata.Batch { +func (c *castInt2BoolOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4640,7 +5686,7 @@ func (c *castInt4BoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int32() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() outputCol := outputVec.Bool() outputNulls := outputVec.Nulls() @@ -4648,9 +5694,13 @@ func (c *castInt4BoolOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4667,9 +5717,13 @@ func (c *castInt4BoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4692,9 +5746,13 @@ func (c *castInt4BoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4711,9 +5769,13 @@ func (c *castInt4BoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4739,14 +5801,14 @@ func (c *castInt4BoolOp) Next() coldata.Batch { return batch } -type castInt4DecimalOp struct { +type castInt2DecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt4DecimalOp{} -var _ colexecop.ClosableOperator = &castInt4DecimalOp{} +var _ colexecop.ResettableOperator = &castInt2DecimalOp{} +var _ colexecop.ClosableOperator = &castInt2DecimalOp{} -func (c *castInt4DecimalOp) Next() coldata.Batch { +func (c *castInt2DecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4760,7 +5822,7 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int32() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() @@ -4768,9 +5830,13 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4791,9 +5857,13 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4820,9 +5890,13 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4843,9 +5917,13 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4875,14 +5953,14 @@ func (c *castInt4DecimalOp) Next() coldata.Batch { return batch } -type castInt4FloatOp struct { +type castInt2FloatOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt4FloatOp{} -var _ colexecop.ClosableOperator = &castInt4FloatOp{} +var _ colexecop.ResettableOperator = &castInt2FloatOp{} +var _ colexecop.ClosableOperator = &castInt2FloatOp{} -func (c *castInt4FloatOp) Next() coldata.Batch { +func (c *castInt2FloatOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -4896,7 +5974,7 @@ func (c *castInt4FloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int32() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() outputCol := outputVec.Float64() outputNulls := outputVec.Nulls() @@ -4904,9 +5982,13 @@ func (c *castInt4FloatOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4923,9 +6005,13 @@ func (c *castInt4FloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4948,9 +6034,13 @@ func (c *castInt4FloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -4967,9 +6057,13 @@ func (c *castInt4FloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -4995,14 +6089,14 @@ func (c *castInt4FloatOp) Next() coldata.Batch { return batch } -type castInt4Int2Op struct { +type castInt2Int4Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt4Int2Op{} -var _ colexecop.ClosableOperator = &castInt4Int2Op{} +var _ colexecop.ResettableOperator = &castInt2Int4Op{} +var _ colexecop.ClosableOperator = &castInt2Int4Op{} -func (c *castInt4Int2Op) Next() coldata.Batch { +func (c *castInt2Int4Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5016,17 +6110,21 @@ func (c *castInt4Int2Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int32() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Int32() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5034,22 +6132,20 @@ func (c *castInt4Int2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) - + var r int32 + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5060,14 +6156,8 @@ func (c *castInt4Int2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) - + var r int32 + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -5076,9 +6166,13 @@ func (c *castInt4Int2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5086,22 +6180,20 @@ func (c *castInt4Int2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) - + var r int32 + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5112,14 +6204,8 @@ func (c *castInt4Int2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) - + var r int32 + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) } @@ -5131,14 +6217,14 @@ func (c *castInt4Int2Op) Next() coldata.Batch { return batch } -type castInt4IntOp struct { +type castInt2IntOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castInt4IntOp{} -var _ colexecop.ClosableOperator = &castInt4IntOp{} +var _ colexecop.ResettableOperator = &castInt2IntOp{} +var _ colexecop.ClosableOperator = &castInt2IntOp{} -func (c *castInt4IntOp) Next() coldata.Batch { +func (c *castInt2IntOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5152,7 +6238,7 @@ func (c *castInt4IntOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int32() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() outputCol := outputVec.Int64() outputNulls := outputVec.Nulls() @@ -5160,9 +6246,13 @@ func (c *castInt4IntOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5177,9 +6267,13 @@ func (c *castInt4IntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5200,9 +6294,13 @@ func (c *castInt4IntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5217,9 +6315,13 @@ func (c *castInt4IntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5243,14 +6345,14 @@ func (c *castInt4IntOp) Next() coldata.Batch { return batch } -type castIntBoolOp struct { +type castInt2StringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castIntBoolOp{} -var _ colexecop.ClosableOperator = &castIntBoolOp{} +var _ colexecop.ResettableOperator = &castInt2StringOp{} +var _ colexecop.ClosableOperator = &castInt2StringOp{} -func (c *castIntBoolOp) Next() coldata.Batch { +func (c *castInt2StringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5264,17 +6366,21 @@ func (c *castIntBoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Int16() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bool() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5282,20 +6388,57 @@ func (c *castIntBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r []byte - r = v != 0 + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -5304,11 +6447,44 @@ func (c *castIntBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r []byte - r = v != 0 + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -5316,9 +6492,13 @@ func (c *castIntBoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5326,20 +6506,57 @@ func (c *castIntBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r []byte - r = v != 0 + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) - _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -5348,11 +6565,44 @@ func (c *castIntBoolOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r []byte - r = v != 0 + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -5363,14 +6613,14 @@ func (c *castIntBoolOp) Next() coldata.Batch { return batch } -type castIntDecimalOp struct { +type castInt4BoolOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castIntDecimalOp{} -var _ colexecop.ClosableOperator = &castIntDecimalOp{} +var _ colexecop.ResettableOperator = &castInt4BoolOp{} +var _ colexecop.ClosableOperator = &castInt4BoolOp{} -func (c *castIntDecimalOp) Next() coldata.Batch { +func (c *castInt4BoolOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5384,17 +6634,21 @@ func (c *castIntDecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Bool() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5402,22 +6656,22 @@ func (c *castIntDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r bool - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5428,13 +6682,9 @@ func (c *castIntDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r bool - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5444,9 +6694,13 @@ func (c *castIntDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5454,22 +6708,22 @@ func (c *castIntDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r bool - r.SetInt64(int64(v)) - - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5480,13 +6734,9 @@ func (c *castIntDecimalOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - r.SetInt64(int64(v)) + var r bool - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5499,14 +6749,14 @@ func (c *castIntDecimalOp) Next() coldata.Batch { return batch } -type castIntFloatOp struct { +type castInt4DecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castIntFloatOp{} -var _ colexecop.ClosableOperator = &castIntFloatOp{} +var _ colexecop.ResettableOperator = &castInt4DecimalOp{} +var _ colexecop.ClosableOperator = &castInt4DecimalOp{} -func (c *castIntFloatOp) Next() coldata.Batch { +func (c *castInt4DecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5520,17 +6770,21 @@ func (c *castIntFloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Float64() + outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5538,18 +6792,26 @@ func (c *castIntFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r apd.Decimal - r = float64(v) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5560,9 +6822,13 @@ func (c *castIntFloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r apd.Decimal - r = float64(v) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5572,9 +6838,13 @@ func (c *castIntFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5582,18 +6852,26 @@ func (c *castIntFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r apd.Decimal - r = float64(v) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5604,9 +6882,13 @@ func (c *castIntFloatOp) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r apd.Decimal - r = float64(v) + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5619,14 +6901,14 @@ func (c *castIntFloatOp) Next() coldata.Batch { return batch } -type castIntInt2Op struct { +type castInt4FloatOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castIntInt2Op{} -var _ colexecop.ClosableOperator = &castIntInt2Op{} +var _ colexecop.ResettableOperator = &castInt4FloatOp{} +var _ colexecop.ClosableOperator = &castInt4FloatOp{} -func (c *castIntInt2Op) Next() coldata.Batch { +func (c *castInt4FloatOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5640,17 +6922,21 @@ func (c *castIntInt2Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Float64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5658,22 +6944,22 @@ func (c *castIntInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r float64 - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5684,13 +6970,9 @@ func (c *castIntInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r float64 - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5700,9 +6982,13 @@ func (c *castIntInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5710,22 +6996,22 @@ func (c *castIntInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 + var r float64 - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5736,13 +7022,9 @@ func (c *castIntInt2Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 + var r float64 - shifted := v >> uint(15) - if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(v) + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5755,14 +7037,14 @@ func (c *castIntInt2Op) Next() coldata.Batch { return batch } -type castIntInt4Op struct { +type castInt4Int2Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castIntInt4Op{} -var _ colexecop.ClosableOperator = &castIntInt4Op{} +var _ colexecop.ResettableOperator = &castInt4Int2Op{} +var _ colexecop.ClosableOperator = &castInt4Int2Op{} -func (c *castIntInt4Op) Next() coldata.Batch { +func (c *castInt4Int2Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5776,17 +7058,21 @@ func (c *castIntInt4Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Int64() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Int16() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5794,22 +7080,26 @@ func (c *castIntInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r int16 - shifted := v >> uint(31) + shifted := v >> uint(15) if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } - r = int32(v) + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5820,13 +7110,13 @@ func (c *castIntInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r int16 - shifted := v >> uint(31) + shifted := v >> uint(15) if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } - r = int32(v) + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5836,9 +7126,13 @@ func (c *castIntInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5846,22 +7140,26 @@ func (c *castIntInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r int16 - shifted := v >> uint(31) + shifted := v >> uint(15) if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } - r = int32(v) + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int @@ -5872,13 +7170,13 @@ func (c *castIntInt4Op) Next() coldata.Batch { } //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r int16 - shifted := v >> uint(31) + shifted := v >> uint(15) if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } - r = int32(v) + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -5891,14 +7189,14 @@ func (c *castIntInt4Op) Next() coldata.Batch { return batch } -type castJsonbStringOp struct { +type castInt4IntOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castJsonbStringOp{} -var _ colexecop.ClosableOperator = &castJsonbStringOp{} +var _ colexecop.ResettableOperator = &castInt4IntOp{} +var _ colexecop.ClosableOperator = &castInt4IntOp{} -func (c *castJsonbStringOp) Next() coldata.Batch { +func (c *castInt4IntOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -5912,17 +7210,21 @@ func (c *castJsonbStringOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.JSON() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bytes() + outputCol := outputVec.Int64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5930,47 +7232,33 @@ func (c *castJsonbStringOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r []byte - - _string := v.String() - switch toType.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values. - _string = util.TruncateString(_string, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - _string = strings.TrimRight(_string, " ") - } - r = []byte(_string) - + var r int64 + r = int64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r []byte - - _string := v.String() - switch toType.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values. - _string = util.TruncateString(_string, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - _string = strings.TrimRight(_string, " ") - } - r = []byte(_string) - + var r int64 + r = int64(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -5978,9 +7266,13 @@ func (c *castJsonbStringOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -5988,47 +7280,33 @@ func (c *castJsonbStringOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r []byte - - _string := v.String() - switch toType.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values. - _string = util.TruncateString(_string, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - _string = strings.TrimRight(_string, " ") - } - r = []byte(_string) - + var r int64 + r = int64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r []byte - - _string := v.String() - switch toType.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values. - _string = util.TruncateString(_string, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - _string = strings.TrimRight(_string, " ") - } - r = []byte(_string) - + var r int64 + r = int64(v) + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -6039,14 +7317,14 @@ func (c *castJsonbStringOp) Next() coldata.Batch { return batch } -type castStringBoolOp struct { +type castInt4StringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringBoolOp{} -var _ colexecop.ClosableOperator = &castStringBoolOp{} +var _ colexecop.ResettableOperator = &castInt4StringOp{} +var _ colexecop.ClosableOperator = &castInt4StringOp{} -func (c *castStringBoolOp) Next() coldata.Batch { +func (c *castInt4StringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6060,17 +7338,21 @@ func (c *castStringBoolOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int32() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bool() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6078,12 +7360,42 @@ func (c *castStringBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r []byte - var err error - r, err = tree.ParseBool(string(v)) - if err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -6091,26 +7403,60 @@ func (c *castStringBoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r []byte - var err error - r, err = tree.ParseBool(string(v)) - if err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -6118,9 +7464,13 @@ func (c *castStringBoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6128,12 +7478,42 @@ func (c *castStringBoolOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r bool + var r []byte - var err error - r, err = tree.ParseBool(string(v)) - if err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -6141,26 +7521,60 @@ func (c *castStringBoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r bool + var r []byte - var err error - r, err = tree.ParseBool(string(v)) - if err != nil { - colexecerror.ExpectedError(err) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} + } + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -6171,14 +7585,14 @@ func (c *castStringBoolOp) Next() coldata.Batch { return batch } -type castStringBytesOp struct { +type castIntBoolOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringBytesOp{} -var _ colexecop.ClosableOperator = &castStringBytesOp{} +var _ colexecop.ResettableOperator = &castIntBoolOp{} +var _ colexecop.ClosableOperator = &castIntBoolOp{} -func (c *castStringBytesOp) Next() coldata.Batch { +func (c *castIntBoolOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6192,17 +7606,21 @@ func (c *castStringBytesOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Bytes() + outputCol := outputVec.Bool() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6210,37 +7628,37 @@ func (c *castStringBytesOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r []byte + var r bool - var err error - r, err = lex.DecodeRawBytesToByteArrayAuto(v) - if err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r []byte + var r bool - var err error - r, err = lex.DecodeRawBytesToByteArrayAuto(v) - if err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -6248,9 +7666,13 @@ func (c *castStringBytesOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6258,37 +7680,37 @@ func (c *castStringBytesOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r []byte + var r bool - var err error - r, err = lex.DecodeRawBytesToByteArrayAuto(v) - if err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r []byte + var r bool - var err error - r, err = lex.DecodeRawBytesToByteArrayAuto(v) - if err != nil { - colexecerror.ExpectedError(err) - } + r = v != 0 + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -6299,14 +7721,14 @@ func (c *castStringBytesOp) Next() coldata.Batch { return batch } -type castStringDateOp struct { +type castIntDecimalOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringDateOp{} -var _ colexecop.ClosableOperator = &castStringDateOp{} +var _ colexecop.ResettableOperator = &castIntDecimalOp{} +var _ colexecop.ClosableOperator = &castIntDecimalOp{} -func (c *castStringDateOp) Next() coldata.Batch { +func (c *castIntDecimalOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6320,17 +7742,21 @@ func (c *castStringDateOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Decimal() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6338,24 +7764,27 @@ func (c *castStringDateOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r apd.Decimal - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) - if err != nil { + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { colexecerror.ExpectedError(err) } - r = _d.UnixEpochDays() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6363,16 +7792,15 @@ func (c *castStringDateOp) Next() coldata.Batch { if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r apd.Decimal - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) - if err != nil { + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { colexecerror.ExpectedError(err) } - r = _d.UnixEpochDays() //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6382,9 +7810,13 @@ func (c *castStringDateOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6392,24 +7824,27 @@ func (c *castStringDateOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r apd.Decimal - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) - if err != nil { + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { colexecerror.ExpectedError(err) } - r = _d.UnixEpochDays() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6417,16 +7852,15 @@ func (c *castStringDateOp) Next() coldata.Batch { if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r apd.Decimal - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) - if err != nil { + r.SetInt64(int64(v)) + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { colexecerror.ExpectedError(err) } - r = _d.UnixEpochDays() //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6439,14 +7873,14 @@ func (c *castStringDateOp) Next() coldata.Batch { return batch } -type castStringDecimalOp struct { +type castIntFloatOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringDecimalOp{} -var _ colexecop.ClosableOperator = &castStringDecimalOp{} +var _ colexecop.ResettableOperator = &castIntFloatOp{} +var _ colexecop.ClosableOperator = &castIntFloatOp{} -func (c *castStringDecimalOp) Next() coldata.Batch { +func (c *castIntFloatOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6460,17 +7894,21 @@ func (c *castStringDecimalOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Decimal() + outputCol := outputVec.Float64() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6478,37 +7916,23 @@ func (c *castStringDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal + var r float64 - _s := strings.TrimSpace(string(v)) - _, res, err := tree.ExactCtx.SetString(&r, _s) - if res != 0 || err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) - } - switch r.Form { - case apd.NaNSignaling: - r.Form = apd.NaN - r.Negative = false - case apd.NaN: - r.Negative = false - case apd.Finite: - if r.IsZero() && r.Negative { - r.Negative = false - } - } - - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6516,29 +7940,11 @@ func (c *castStringDecimalOp) Next() coldata.Batch { if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - _s := strings.TrimSpace(string(v)) - _, res, err := tree.ExactCtx.SetString(&r, _s) - if res != 0 || err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) - } - switch r.Form { - case apd.NaNSignaling: - r.Form = apd.NaN - r.Negative = false - case apd.NaN: - r.Negative = false - case apd.Finite: - if r.IsZero() && r.Negative { - r.Negative = false - } - } + var r float64 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6548,9 +7954,13 @@ func (c *castStringDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6558,37 +7968,23 @@ func (c *castStringDecimalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r apd.Decimal - - _s := strings.TrimSpace(string(v)) - _, res, err := tree.ExactCtx.SetString(&r, _s) - if res != 0 || err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) - } - switch r.Form { - case apd.NaNSignaling: - r.Form = apd.NaN - r.Negative = false - case apd.NaN: - r.Negative = false - case apd.Finite: - if r.IsZero() && r.Negative { - r.Negative = false - } - } + var r float64 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = float64(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6596,29 +7992,11 @@ func (c *castStringDecimalOp) Next() coldata.Batch { if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r apd.Decimal - - _s := strings.TrimSpace(string(v)) - _, res, err := tree.ExactCtx.SetString(&r, _s) - if res != 0 || err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) - } - switch r.Form { - case apd.NaNSignaling: - r.Form = apd.NaN - r.Negative = false - case apd.NaN: - r.Negative = false - case apd.Finite: - if r.IsZero() && r.Negative { - r.Negative = false - } - } + var r float64 - if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { - colexecerror.ExpectedError(err) - } + r = float64(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6631,14 +8009,14 @@ func (c *castStringDecimalOp) Next() coldata.Batch { return batch } -type castStringFloatOp struct { +type castIntInt2Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringFloatOp{} -var _ colexecop.ClosableOperator = &castStringFloatOp{} +var _ colexecop.ResettableOperator = &castIntInt2Op{} +var _ colexecop.ClosableOperator = &castIntInt2Op{} -func (c *castStringFloatOp) Next() coldata.Batch { +func (c *castIntInt2Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6652,17 +8030,21 @@ func (c *castStringFloatOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Float64() + outputCol := outputVec.Int16() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6670,23 +8052,27 @@ func (c *castStringFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r int16 - _s := string(v) - var _err error - r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) - if _err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6694,15 +8080,15 @@ func (c *castStringFloatOp) Next() coldata.Batch { if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r int16 - _s := string(v) - var _err error - r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) - if _err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6712,9 +8098,13 @@ func (c *castStringFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6722,23 +8112,27 @@ func (c *castStringFloatOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r float64 + var r int16 - _s := string(v) - var _err error - r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) - if _err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } + r = int16(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6746,15 +8140,15 @@ func (c *castStringFloatOp) Next() coldata.Batch { if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r float64 + var r int16 - _s := string(v) - var _err error - r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) - if _err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + shifted := v >> uint(15) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) } + r = int16(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6767,14 +8161,14 @@ func (c *castStringFloatOp) Next() coldata.Batch { return batch } -type castStringInt2Op struct { +type castIntInt4Op struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringInt2Op{} -var _ colexecop.ClosableOperator = &castStringInt2Op{} +var _ colexecop.ResettableOperator = &castIntInt4Op{} +var _ colexecop.ClosableOperator = &castIntInt4Op{} -func (c *castStringInt2Op) Next() coldata.Batch { +func (c *castIntInt4Op) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6788,17 +8182,21 @@ func (c *castStringInt2Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int16() + outputCol := outputVec.Int32() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6806,31 +8204,27 @@ func (c *castStringInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) + var r int32 + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) } + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6838,23 +8232,15 @@ func (c *castStringInt2Op) Next() coldata.Batch { if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) + var r int32 + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) } + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6864,9 +8250,13 @@ func (c *castStringInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6874,31 +8264,27 @@ func (c *castStringInt2Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int16 - - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) + var r int32 + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) } + r = int32(v) outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = inputCol.Get(n - 1) _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -6906,23 +8292,15 @@ func (c *castStringInt2Op) Next() coldata.Batch { if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int16 - - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) - } - - shifted := _i >> uint(15) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt2OutOfRange) - } - r = int16(_i) + var r int32 + shifted := v >> uint(31) + if (v >= 0 && shifted > 0) || (v < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) } + r = int32(v) //gcassert:bce outputCol.Set(tupleIdx, r) @@ -6935,14 +8313,14 @@ func (c *castStringInt2Op) Next() coldata.Batch { return batch } -type castStringInt4Op struct { +type castIntStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringInt4Op{} -var _ colexecop.ClosableOperator = &castStringInt4Op{} +var _ colexecop.ResettableOperator = &castIntStringOp{} +var _ colexecop.ClosableOperator = &castIntStringOp{} -func (c *castStringInt4Op) Next() coldata.Batch { +func (c *castIntStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -6956,17 +8334,21 @@ func (c *castStringInt4Op) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Int64() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int32() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -6974,21 +8356,42 @@ func (c *castStringInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} } - r = int32(_i) + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -6996,35 +8399,60 @@ func (c *castStringInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} } - r = int32(_i) + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7032,9 +8460,13 @@ func (c *castStringInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7042,21 +8474,42 @@ func (c *castStringInt4Op) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} } - r = int32(_i) + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7064,35 +8517,60 @@ func (c *castStringInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int32 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + if toType.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if v > math.MaxInt8 || v < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) } - - shifted := _i >> uint(31) - if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { - colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + if v == 0 { + r = []byte{} + } else { + r = []byte{byte(v)} } - r = int32(_i) + } else { + r = []byte(strconv.FormatInt(int64(v), 10)) + } + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7103,14 +8581,14 @@ func (c *castStringInt4Op) Next() coldata.Batch { return batch } -type castStringIntOp struct { +type castIntervalStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringIntOp{} -var _ colexecop.ClosableOperator = &castStringIntOp{} +var _ colexecop.ResettableOperator = &castIntervalStringOp{} +var _ colexecop.ClosableOperator = &castIntervalStringOp{} -func (c *castStringIntOp) Next() coldata.Batch { +func (c *castIntervalStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7124,17 +8602,21 @@ func (c *castStringIntOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Interval() inputNulls := inputVec.Nulls() - outputCol := outputVec.Int64() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7142,15 +8624,33 @@ func (c *castStringIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + dcc := evalCtx.SessionData().DataConversionConfig + buf.Reset() + v.FormatWithStyle(buf, dcc.IntervalStyle) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") } - r = int64(_i) + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7158,29 +8658,51 @@ func (c *castStringIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + dcc := evalCtx.SessionData().DataConversionConfig + buf.Reset() + v.FormatWithStyle(buf, dcc.IntervalStyle) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") } - r = int64(_i) + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7188,9 +8710,13 @@ func (c *castStringIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7198,15 +8724,33 @@ func (c *castStringIntOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r int64 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + dcc := evalCtx.SessionData().DataConversionConfig + buf.Reset() + v.FormatWithStyle(buf, dcc.IntervalStyle) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") } - r = int64(_i) + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7214,29 +8758,2119 @@ func (c *castStringIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r int64 + var r []byte - { - _s := string(v) - _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) - if err != nil { - colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + dcc := evalCtx.SessionData().DataConversionConfig + buf.Reset() + v.FormatWithStyle(buf, dcc.IntervalStyle) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castJsonbStringOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castJsonbStringOp{} +var _ colexecop.ClosableOperator = &castJsonbStringOp{} + +func (c *castJsonbStringOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.JSON() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Bytes() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = []byte(v.String()) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringBoolOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringBoolOp{} +var _ colexecop.ClosableOperator = &castStringBoolOp{} + +func (c *castStringBoolOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Bool() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r bool + + var err error + r, err = tree.ParseBool(string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r bool + + var err error + r, err = tree.ParseBool(string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r bool + + var err error + r, err = tree.ParseBool(string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r bool + + var err error + r, err = tree.ParseBool(string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringBytesOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringBytesOp{} +var _ colexecop.ClosableOperator = &castStringBytesOp{} + +func (c *castStringBytesOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Bytes() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + var err error + r, err = lex.DecodeRawBytesToByteArrayAuto(v) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + var err error + r, err = lex.DecodeRawBytesToByteArrayAuto(v) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + var err error + r, err = lex.DecodeRawBytesToByteArrayAuto(v) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + var err error + r, err = lex.DecodeRawBytesToByteArrayAuto(v) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringDateOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringDateOp{} +var _ colexecop.ClosableOperator = &castStringDateOp{} + +func (c *castStringDateOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Int64() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _d.UnixEpochDays() + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _d.UnixEpochDays() + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _d.UnixEpochDays() + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _d, _, err := pgdate.ParseDate(_now, _dateStyle, string(v)) + if err != nil { + colexecerror.ExpectedError(err) + } + r = _d.UnixEpochDays() + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringDecimalOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringDecimalOp{} +var _ colexecop.ClosableOperator = &castStringDecimalOp{} + +func (c *castStringDecimalOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Decimal() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r apd.Decimal + + _s := strings.TrimSpace(string(v)) + _, res, err := tree.ExactCtx.SetString(&r, _s) + if res != 0 || err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) + } + switch r.Form { + case apd.NaNSignaling: + r.Form = apd.NaN + r.Negative = false + case apd.NaN: + r.Negative = false + case apd.Finite: + if r.IsZero() && r.Negative { + r.Negative = false + } + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r apd.Decimal + + _s := strings.TrimSpace(string(v)) + _, res, err := tree.ExactCtx.SetString(&r, _s) + if res != 0 || err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) + } + switch r.Form { + case apd.NaNSignaling: + r.Form = apd.NaN + r.Negative = false + case apd.NaN: + r.Negative = false + case apd.Finite: + if r.IsZero() && r.Negative { + r.Negative = false + } + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r apd.Decimal + + _s := strings.TrimSpace(string(v)) + _, res, err := tree.ExactCtx.SetString(&r, _s) + if res != 0 || err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) + } + switch r.Form { + case apd.NaNSignaling: + r.Form = apd.NaN + r.Negative = false + case apd.NaN: + r.Negative = false + case apd.Finite: + if r.IsZero() && r.Negative { + r.Negative = false + } + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r apd.Decimal + + _s := strings.TrimSpace(string(v)) + _, res, err := tree.ExactCtx.SetString(&r, _s) + if res != 0 || err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, types.Decimal, err)) + } + switch r.Form { + case apd.NaNSignaling: + r.Form = apd.NaN + r.Negative = false + case apd.NaN: + r.Negative = false + case apd.Finite: + if r.IsZero() && r.Negative { + r.Negative = false + } + } + + if err := tree.LimitDecimalWidth(&r, int(toType.Precision()), int(toType.Scale())); err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringFloatOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringFloatOp{} +var _ colexecop.ClosableOperator = &castStringFloatOp{} + +func (c *castStringFloatOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Float64() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r float64 + + _s := string(v) + var _err error + r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) + if _err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r float64 + + _s := string(v) + var _err error + r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) + if _err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r float64 + + _s := string(v) + var _err error + r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) + if _err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r float64 + + _s := string(v) + var _err error + r, _err = strconv.ParseFloat(strings.TrimSpace(_s), 64) + if _err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, _err)) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringInt2Op struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringInt2Op{} +var _ colexecop.ClosableOperator = &castStringInt2Op{} + +func (c *castStringInt2Op) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Int16() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int16 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int16 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int16 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int16 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(15) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt2OutOfRange) + } + r = int16(_i) + + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringInt4Op struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringInt4Op{} +var _ colexecop.ClosableOperator = &castStringInt4Op{} + +func (c *castStringInt4Op) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Int32() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int32 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) + + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int32 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) + + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int32 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) + + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int32 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + + shifted := _i >> uint(31) + if (_i >= 0 && shifted > 0) || (_i < 0 && shifted < -1) { + colexecerror.ExpectedError(tree.ErrInt4OutOfRange) + } + r = int32(_i) + + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringIntOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringIntOp{} +var _ colexecop.ClosableOperator = &castStringIntOp{} + +func (c *castStringIntOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Int64() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + r = int64(_i) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + r = int64(_i) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + r = int64(_i) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r int64 + + { + _s := string(v) + _i, err := strconv.ParseInt(strings.TrimSpace(_s), 0, 64) + if err != nil { + colexecerror.ExpectedError(tree.MakeParseError(_s, toType, err)) + } + r = int64(_i) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringIntervalOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringIntervalOp{} +var _ colexecop.ClosableOperator = &castStringIntervalOp{} + +func (c *castStringIntervalOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Interval() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r duration.Duration + + _itm, err := toType.IntervalTypeMetadata() + if err != nil { + colexecerror.ExpectedError(err) + } + _intervalStyle := evalCtx.GetIntervalStyle() + r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r duration.Duration + + _itm, err := toType.IntervalTypeMetadata() + if err != nil { + colexecerror.ExpectedError(err) + } + _intervalStyle := evalCtx.GetIntervalStyle() + r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) + if err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r duration.Duration + + _itm, err := toType.IntervalTypeMetadata() + if err != nil { + colexecerror.ExpectedError(err) + } + _intervalStyle := evalCtx.GetIntervalStyle() + r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) + if err != nil { + colexecerror.ExpectedError(err) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r duration.Duration + + _itm, err := toType.IntervalTypeMetadata() + if err != nil { + colexecerror.ExpectedError(err) + } + _intervalStyle := evalCtx.GetIntervalStyle() + r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) + if err != nil { + colexecerror.ExpectedError(err) + } + + //gcassert:bce + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringJsonbOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringJsonbOp{} +var _ colexecop.ClosableOperator = &castStringJsonbOp{} + +func (c *castStringJsonbOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.JSON() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r json.JSON + + var err error + r, err = json.ParseJSON(string(v)) + if err != nil { + colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r json.JSON + + var err error + r, err = json.ParseJSON(string(v)) + if err != nil { + colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r json.JSON + + var err error + r, err = json.ParseJSON(string(v)) + if err != nil { + colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r json.JSON + + var err error + r, err = json.ParseJSON(string(v)) + if err != nil { + colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } + }, + ) + return batch +} + +type castStringStringOp struct { + castOpBase +} + +var _ colexecop.ResettableOperator = &castStringStringOp{} +var _ colexecop.ClosableOperator = &castStringStringOp{} + +func (c *castStringStringOp) Next() coldata.Batch { + batch := c.Input.Next() + n := batch.Length() + if n == 0 { + return coldata.ZeroBatch + } + sel := batch.Selection() + inputVec := batch.ColVec(c.colIdx) + outputVec := batch.ColVec(c.outputIdx) + toType := outputVec.Type() + // Remove unused warnings. + _ = toType + c.allocator.PerformOperation( + []coldata.Vec{outputVec}, func() { + inputCol := inputVec.Bytes() + inputNulls := inputVec.Nulls() + outputCol := outputVec.Bytes() + outputNulls := outputVec.Nulls() + if inputVec.MaybeHasNulls() { + outputNulls.Copy(inputNulls) + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = v + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if true && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = v + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } + } else { + if sel != nil { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = sel[i] + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = v + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } + + outputCol.Set(tupleIdx, r) + } + } + } else { + { + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. + _ = evalCtx + _ = buf + var tupleIdx int + for i := 0; i < n; i++ { + tupleIdx = i + if false && inputNulls.NullAt(tupleIdx) { + continue + } + v := inputCol.Get(tupleIdx) + var r []byte + + r = v + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) } - r = int64(_i) + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7247,14 +10881,14 @@ func (c *castStringIntOp) Next() coldata.Batch { return batch } -type castStringIntervalOp struct { +type castStringTimestampOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringIntervalOp{} -var _ colexecop.ClosableOperator = &castStringIntervalOp{} +var _ colexecop.ResettableOperator = &castStringTimestampOp{} +var _ colexecop.ClosableOperator = &castStringTimestampOp{} -func (c *castStringIntervalOp) Next() coldata.Batch { +func (c *castStringTimestampOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7270,15 +10904,19 @@ func (c *castStringIntervalOp) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Bytes() inputNulls := inputVec.Nulls() - outputCol := outputVec.Interval() + outputCol := outputVec.Timestamp() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7286,16 +10924,19 @@ func (c *castStringIntervalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r duration.Duration + var r time.Time - _itm, err := toType.IntervalTypeMetadata() + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) if err != nil { colexecerror.ExpectedError(err) } - _intervalStyle := evalCtx.GetIntervalStyle() - r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) - if err != nil { - colexecerror.ExpectedError(err) + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } outputCol.Set(tupleIdx, r) @@ -7303,9 +10944,13 @@ func (c *castStringIntervalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -7314,16 +10959,19 @@ func (c *castStringIntervalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r duration.Duration + var r time.Time - _itm, err := toType.IntervalTypeMetadata() + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) if err != nil { colexecerror.ExpectedError(err) } - _intervalStyle := evalCtx.GetIntervalStyle() - r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) - if err != nil { - colexecerror.ExpectedError(err) + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } //gcassert:bce @@ -7334,9 +10982,13 @@ func (c *castStringIntervalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7344,16 +10996,19 @@ func (c *castStringIntervalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r duration.Duration + var r time.Time - _itm, err := toType.IntervalTypeMetadata() + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) if err != nil { colexecerror.ExpectedError(err) } - _intervalStyle := evalCtx.GetIntervalStyle() - r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) - if err != nil { - colexecerror.ExpectedError(err) + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } outputCol.Set(tupleIdx, r) @@ -7361,9 +11016,13 @@ func (c *castStringIntervalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -7372,16 +11031,19 @@ func (c *castStringIntervalOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r duration.Duration + var r time.Time - _itm, err := toType.IntervalTypeMetadata() + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) if err != nil { colexecerror.ExpectedError(err) } - _intervalStyle := evalCtx.GetIntervalStyle() - r, err = tree.ParseIntervalWithTypeMetadata(_intervalStyle, string(v), _itm) - if err != nil { - colexecerror.ExpectedError(err) + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } //gcassert:bce @@ -7395,14 +11057,14 @@ func (c *castStringIntervalOp) Next() coldata.Batch { return batch } -type castStringJsonbOp struct { +type castStringTimestamptzOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringJsonbOp{} -var _ colexecop.ClosableOperator = &castStringJsonbOp{} +var _ colexecop.ResettableOperator = &castStringTimestamptzOp{} +var _ colexecop.ClosableOperator = &castStringTimestamptzOp{} -func (c *castStringJsonbOp) Next() coldata.Batch { +func (c *castStringTimestamptzOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7418,15 +11080,19 @@ func (c *castStringJsonbOp) Next() coldata.Batch { []coldata.Vec{outputVec}, func() { inputCol := inputVec.Bytes() inputNulls := inputVec.Nulls() - outputCol := outputVec.JSON() + outputCol := outputVec.Timestamp() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7434,12 +11100,19 @@ func (c *castStringJsonbOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r json.JSON + var r time.Time - var err error - r, err = json.ParseJSON(string(v)) + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) if err != nil { - colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + colexecerror.ExpectedError(err) + } + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } outputCol.Set(tupleIdx, r) @@ -7447,9 +11120,14 @@ func (c *castStringJsonbOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -7457,14 +11135,22 @@ func (c *castStringJsonbOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r json.JSON + var r time.Time - var err error - r, err = json.ParseJSON(string(v)) + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) if err != nil { - colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + colexecerror.ExpectedError(err) + } + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7472,9 +11158,13 @@ func (c *castStringJsonbOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7482,12 +11172,19 @@ func (c *castStringJsonbOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r json.JSON + var r time.Time - var err error - r, err = json.ParseJSON(string(v)) + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) if err != nil { - colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + colexecerror.ExpectedError(err) + } + + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) } outputCol.Set(tupleIdx, r) @@ -7495,9 +11192,14 @@ func (c *castStringJsonbOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf + _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -7505,14 +11207,22 @@ func (c *castStringJsonbOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r json.JSON + var r time.Time - var err error - r, err = json.ParseJSON(string(v)) + _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) + _now := evalCtx.GetRelativeParseTime() + _dateStyle := evalCtx.GetDateStyle() + _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) if err != nil { - colexecerror.ExpectedError(pgerror.Wrapf(err, pgcode.Syntax, "could not parse JSON")) + colexecerror.ExpectedError(err) } + r = _t.Round(_roundTo) + if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + } + + //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7523,14 +11233,14 @@ func (c *castStringJsonbOp) Next() coldata.Batch { return batch } -type castStringStringOp struct { +type castStringUuidOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringStringOp{} -var _ colexecop.ClosableOperator = &castStringStringOp{} +var _ colexecop.ResettableOperator = &castStringUuidOp{} +var _ colexecop.ClosableOperator = &castStringUuidOp{} -func (c *castStringStringOp) Next() coldata.Batch { +func (c *castStringUuidOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7552,9 +11262,13 @@ func (c *castStringStringOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7564,40 +11278,24 @@ func (c *castStringStringOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - if toType.Oid() == oid.T_name { - // For Names we don't perform the truncation, and there is no need - // to do anything about the Oids since those are stored in the type. - r = v - } else { - // bpchar types truncate trailing whitespace. - if toType.Oid() == oid.T_bpchar { - v = bytes.TrimRight(v, " ") - } - // If the string type specifies a limit we truncate to that limit: - // 'hello'::CHAR(2) -> 'he' - // This is true of all the string type variants. - if toType.Width() > 0 { - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), int(toType.Width()))) - } - if toType.Oid() == oid.T_char { - // "char" is supposed to truncate long values. - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), 1)) - } - r = v + _uuid, err := uuid.FromString(string(v)) + if err != nil { + colexecerror.ExpectedError(err) } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -7607,31 +11305,11 @@ func (c *castStringStringOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - if toType.Oid() == oid.T_name { - // For Names we don't perform the truncation, and there is no need - // to do anything about the Oids since those are stored in the type. - r = v - } else { - // bpchar types truncate trailing whitespace. - if toType.Oid() == oid.T_bpchar { - v = bytes.TrimRight(v, " ") - } - // If the string type specifies a limit we truncate to that limit: - // 'hello'::CHAR(2) -> 'he' - // This is true of all the string type variants. - if toType.Width() > 0 { - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), int(toType.Width()))) - } - if toType.Oid() == oid.T_char { - // "char" is supposed to truncate long values. - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), 1)) - } - r = v + _uuid, err := uuid.FromString(string(v)) + if err != nil { + colexecerror.ExpectedError(err) } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } @@ -7640,9 +11318,13 @@ func (c *castStringStringOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7652,40 +11334,24 @@ func (c *castStringStringOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - if toType.Oid() == oid.T_name { - // For Names we don't perform the truncation, and there is no need - // to do anything about the Oids since those are stored in the type. - r = v - } else { - // bpchar types truncate trailing whitespace. - if toType.Oid() == oid.T_bpchar { - v = bytes.TrimRight(v, " ") - } - // If the string type specifies a limit we truncate to that limit: - // 'hello'::CHAR(2) -> 'he' - // This is true of all the string type variants. - if toType.Width() > 0 { - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), int(toType.Width()))) - } - if toType.Oid() == oid.T_char { - // "char" is supposed to truncate long values. - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), 1)) - } - r = v + _uuid, err := uuid.FromString(string(v)) + if err != nil { + colexecerror.ExpectedError(err) } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -7695,31 +11361,11 @@ func (c *castStringStringOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - if toType.Oid() == oid.T_name { - // For Names we don't perform the truncation, and there is no need - // to do anything about the Oids since those are stored in the type. - r = v - } else { - // bpchar types truncate trailing whitespace. - if toType.Oid() == oid.T_bpchar { - v = bytes.TrimRight(v, " ") - } - // If the string type specifies a limit we truncate to that limit: - // 'hello'::CHAR(2) -> 'he' - // This is true of all the string type variants. - if toType.Width() > 0 { - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), int(toType.Width()))) - } - if toType.Oid() == oid.T_char { - // "char" is supposed to truncate long values. - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. - v = []byte(util.TruncateString(string(v), 1)) - } - r = v + _uuid, err := uuid.FromString(string(v)) + if err != nil { + colexecerror.ExpectedError(err) } + r = _uuid.GetBytes() outputCol.Set(tupleIdx, r) } @@ -7731,14 +11377,14 @@ func (c *castStringStringOp) Next() coldata.Batch { return batch } -type castStringTimestampOp struct { +type castTimestampStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringTimestampOp{} -var _ colexecop.ClosableOperator = &castStringTimestampOp{} +var _ colexecop.ResettableOperator = &castTimestampStringOp{} +var _ colexecop.ClosableOperator = &castTimestampStringOp{} -func (c *castStringTimestampOp) Next() coldata.Batch { +func (c *castTimestampStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7752,17 +11398,21 @@ func (c *castStringTimestampOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Timestamp() inputNulls := inputVec.Nulls() - outputCol := outputVec.Timestamp() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7770,18 +11420,29 @@ func (c *castStringTimestampOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(tree.FormatTimestamp(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7789,32 +11450,47 @@ func (c *castStringTimestampOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(tree.FormatTimestamp(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7822,9 +11498,13 @@ func (c *castStringTimestampOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7832,18 +11512,29 @@ func (c *castStringTimestampOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(tree.FormatTimestamp(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7851,32 +11542,47 @@ func (c *castStringTimestampOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestampWithoutTimezone(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + r = []byte(tree.FormatTimestamp(v)) + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7887,14 +11593,14 @@ func (c *castStringTimestampOp) Next() coldata.Batch { return batch } -type castStringTimestamptzOp struct { +type castTimestamptzStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringTimestamptzOp{} -var _ colexecop.ClosableOperator = &castStringTimestamptzOp{} +var _ colexecop.ResettableOperator = &castTimestamptzStringOp{} +var _ colexecop.ClosableOperator = &castTimestamptzStringOp{} -func (c *castStringTimestamptzOp) Next() coldata.Batch { +func (c *castTimestamptzStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -7908,17 +11614,21 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { _ = toType c.allocator.PerformOperation( []coldata.Vec{outputVec}, func() { - inputCol := inputVec.Bytes() + inputCol := inputVec.Timestamp() inputNulls := inputVec.Nulls() - outputCol := outputVec.Timestamp() + outputCol := outputVec.Bytes() outputNulls := outputVec.Nulls() if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7926,18 +11636,40 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + // Convert to context timezone for correct display. + _t := v.In(evalCtx.GetLocation()) + + _t = _t.Round(time.Microsecond) + if _t.After(tree.MaxSupportedTime) || _t.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(_t)) } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + + buf.Reset() + tree.FormatTimestampTZ(_t, buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -7945,32 +11677,58 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if true && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + // Convert to context timezone for correct display. + _t := v.In(evalCtx.GetLocation()) + + _t = _t.Round(time.Microsecond) + if _t.After(tree.MaxSupportedTime) || _t.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(_t)) } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + + buf.Reset() + tree.FormatTimestampTZ(_t, buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -7978,9 +11736,13 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -7988,18 +11750,40 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { continue } v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + // Convert to context timezone for correct display. + _t := v.In(evalCtx.GetLocation()) + + _t = _t.Round(time.Microsecond) + if _t.After(tree.MaxSupportedTime) || _t.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(_t)) } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + + buf.Reset() + tree.FormatTimestampTZ(_t, buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } outputCol.Set(tupleIdx, r) @@ -8007,32 +11791,58 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx - _ = outputCol.Get(n - 1) + _ = buf + _ = inputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i if false && inputNulls.NullAt(tupleIdx) { continue } + //gcassert:bce v := inputCol.Get(tupleIdx) - var r time.Time + var r []byte - _roundTo := tree.TimeFamilyPrecisionToRoundDuration(toType.Precision()) - _now := evalCtx.GetRelativeParseTime() - _dateStyle := evalCtx.GetDateStyle() - _t, _, err := pgdate.ParseTimestamp(_now, _dateStyle, string(v)) - if err != nil { - colexecerror.ExpectedError(err) + // Convert to context timezone for correct display. + _t := v.In(evalCtx.GetLocation()) + + _t = _t.Round(time.Microsecond) + if _t.After(tree.MaxSupportedTime) || _t.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(_t)) } - r = _t.Round(_roundTo) - if r.After(tree.MaxSupportedTime) || r.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(r)) + + buf.Reset() + tree.FormatTimestampTZ(_t, buf) + r = []byte(buf.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) } - //gcassert:bce outputCol.Set(tupleIdx, r) } } @@ -8043,14 +11853,14 @@ func (c *castStringTimestamptzOp) Next() coldata.Batch { return batch } -type castStringUuidOp struct { +type castUuidStringOp struct { castOpBase } -var _ colexecop.ResettableOperator = &castStringUuidOp{} -var _ colexecop.ClosableOperator = &castStringUuidOp{} +var _ colexecop.ResettableOperator = &castUuidStringOp{} +var _ colexecop.ClosableOperator = &castUuidStringOp{} -func (c *castStringUuidOp) Next() coldata.Batch { +func (c *castUuidStringOp) Next() coldata.Batch { batch := c.Input.Next() n := batch.Length() if n == 0 { @@ -8072,9 +11882,13 @@ func (c *castStringUuidOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8084,20 +11898,46 @@ func (c *castStringUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromString(string(v)) + _uuid, err := uuid.FromBytes(v) if err != nil { colexecerror.ExpectedError(err) } - r = _uuid.GetBytes() + r = []byte(_uuid.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -8107,11 +11947,33 @@ func (c *castStringUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromString(string(v)) + _uuid, err := uuid.FromBytes(v) if err != nil { colexecerror.ExpectedError(err) } - r = _uuid.GetBytes() + r = []byte(_uuid.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } @@ -8120,9 +11982,13 @@ func (c *castStringUuidOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8132,20 +11998,46 @@ func (c *castStringUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromString(string(v)) + _uuid, err := uuid.FromBytes(v) if err != nil { colexecerror.ExpectedError(err) } - r = _uuid.GetBytes() + r = []byte(_uuid.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -8155,11 +12047,33 @@ func (c *castStringUuidOp) Next() coldata.Batch { v := inputCol.Get(tupleIdx) var r []byte - _uuid, err := uuid.FromString(string(v)) + _uuid, err := uuid.FromBytes(v) if err != nil { colexecerror.ExpectedError(err) } - r = _uuid.GetBytes() + r = []byte(_uuid.String()) + + if toType.Oid() != oid.T_name { + // bpchar types truncate trailing whitespace. + if toType.Oid() == oid.T_bpchar { + r = bytes.TrimRight(r, " ") + } + // If the string type specifies a limit we truncate to that limit: + // 'hello'::CHAR(2) -> 'he' + // This is true of all the string type variants. + if toType.Width() > 0 { + r = []byte(util.TruncateString(string(r), int(toType.Width()))) + } + if toType.Oid() == oid.T_char { + // "char" is supposed to truncate long values. + r = []byte(util.TruncateString(string(r), 1)) + } + } + if toType.Width() > 0 && utf8.RuneCountInString(string(r)) > int(toType.Width()) { + _typeString := toType.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type "+_typeString)) + } outputCol.Set(tupleIdx, r) } @@ -8201,9 +12115,13 @@ func (c *castDatumBoolOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8226,9 +12144,13 @@ func (c *castDatumBoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8255,9 +12177,13 @@ func (c *castDatumBoolOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8280,9 +12206,13 @@ func (c *castDatumBoolOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8342,9 +12272,13 @@ func (c *castDatumInt2Op) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8367,9 +12301,13 @@ func (c *castDatumInt2Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8396,9 +12334,13 @@ func (c *castDatumInt2Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8421,9 +12363,13 @@ func (c *castDatumInt2Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8483,9 +12429,13 @@ func (c *castDatumInt4Op) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8508,9 +12458,13 @@ func (c *castDatumInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8537,9 +12491,13 @@ func (c *castDatumInt4Op) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8562,9 +12520,13 @@ func (c *castDatumInt4Op) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8624,9 +12586,13 @@ func (c *castDatumIntOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8649,9 +12615,13 @@ func (c *castDatumIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8678,9 +12648,13 @@ func (c *castDatumIntOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8703,9 +12677,13 @@ func (c *castDatumIntOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8765,9 +12743,13 @@ func (c *castDatumFloatOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8790,9 +12772,13 @@ func (c *castDatumFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8819,9 +12805,13 @@ func (c *castDatumFloatOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8844,9 +12834,13 @@ func (c *castDatumFloatOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8906,9 +12900,13 @@ func (c *castDatumDecimalOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8931,9 +12929,13 @@ func (c *castDatumDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -8960,9 +12962,13 @@ func (c *castDatumDecimalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -8985,9 +12991,13 @@ func (c *castDatumDecimalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9047,9 +13057,13 @@ func (c *castDatumDateOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9072,9 +13086,13 @@ func (c *castDatumDateOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9101,9 +13119,13 @@ func (c *castDatumDateOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9126,9 +13148,13 @@ func (c *castDatumDateOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9188,9 +13214,13 @@ func (c *castDatumTimestampOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9213,9 +13243,13 @@ func (c *castDatumTimestampOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9242,9 +13276,13 @@ func (c *castDatumTimestampOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9267,9 +13305,13 @@ func (c *castDatumTimestampOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9329,9 +13371,13 @@ func (c *castDatumIntervalOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9354,9 +13400,13 @@ func (c *castDatumIntervalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9383,9 +13433,13 @@ func (c *castDatumIntervalOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9408,9 +13462,13 @@ func (c *castDatumIntervalOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9470,9 +13528,13 @@ func (c *castDatumStringOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9495,9 +13557,13 @@ func (c *castDatumStringOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -9522,9 +13588,13 @@ func (c *castDatumStringOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9547,9 +13617,13 @@ func (c *castDatumStringOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -9607,9 +13681,13 @@ func (c *castDatumBytesOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9632,9 +13710,13 @@ func (c *castDatumBytesOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -9659,9 +13741,13 @@ func (c *castDatumBytesOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9684,9 +13770,13 @@ func (c *castDatumBytesOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -9744,9 +13834,13 @@ func (c *castDatumTimestamptzOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9769,9 +13863,13 @@ func (c *castDatumTimestamptzOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9798,9 +13896,13 @@ func (c *castDatumTimestamptzOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9823,9 +13925,13 @@ func (c *castDatumTimestamptzOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf _ = outputCol.Get(n - 1) var tupleIdx int for i := 0; i < n; i++ { @@ -9885,9 +13991,13 @@ func (c *castDatumUuidOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9910,9 +14020,13 @@ func (c *castDatumUuidOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -9937,9 +14051,13 @@ func (c *castDatumUuidOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -9962,9 +14080,13 @@ func (c *castDatumUuidOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -10022,9 +14144,13 @@ func (c *castDatumJsonbOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -10047,9 +14173,13 @@ func (c *castDatumJsonbOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -10074,9 +14204,13 @@ func (c *castDatumJsonbOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -10099,9 +14233,13 @@ func (c *castDatumJsonbOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -10158,9 +14296,13 @@ func (c *castDatumDatumOp) Next() coldata.Batch { outputNulls.Copy(inputNulls) if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -10189,9 +14331,13 @@ func (c *castDatumDatumOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i @@ -10222,9 +14368,13 @@ func (c *castDatumDatumOp) Next() coldata.Batch { } else { if sel != nil { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = sel[i] @@ -10253,9 +14403,13 @@ func (c *castDatumDatumOp) Next() coldata.Batch { } } else { { - var evalCtx *eval.Context = c.evalCtx - // Silence unused warning. + var ( + evalCtx *eval.Context = c.evalCtx + buf *bytes.Buffer = &c.buf + ) + // Silence unused warnings. _ = evalCtx + _ = buf var tupleIdx int for i := 0; i < n; i++ { tupleIdx = i diff --git a/pkg/sql/colexec/colexecbase/cast_test.go b/pkg/sql/colexec/colexecbase/cast_test.go index 1c13cc734393..412f9dbbe655 100644 --- a/pkg/sql/colexec/colexecbase/cast_test.go +++ b/pkg/sql/colexec/colexecbase/cast_test.go @@ -61,7 +61,7 @@ func TestRandomizedCast(t *testing.T) { } } } - const numTypePairs = 5 + var numTypePairs = rng.Intn(10) + 1 numRows := 1 + rng.Intn(coldata.BatchSize()) + rng.Intn(3)*coldata.BatchSize() log.Infof(ctx, "num rows = %d", numRows) for run := 0; run < numTypePairs; run++ { diff --git a/pkg/sql/colexec/colexecbase/cast_tmpl.go b/pkg/sql/colexec/colexecbase/cast_tmpl.go index aac8c39b058e..861ab85a8ce9 100644 --- a/pkg/sql/colexec/colexecbase/cast_tmpl.go +++ b/pkg/sql/colexec/colexecbase/cast_tmpl.go @@ -22,6 +22,7 @@ package colexecbase import ( + "bytes" "context" "fmt" "math" @@ -81,7 +82,7 @@ const _TYPE_WIDTH = 0 // "castOp" template in the scope of this value's "callsite". const _GENERATE_CAST_OP = 0 -func _CAST(to, from, evalCtx, toType interface{}) { +func _CAST(to, from, evalCtx, toType, buf interface{}) { colexecerror.InternalError(errors.AssertionFailedf("")) } @@ -235,6 +236,7 @@ type castOpBase struct { colIdx int outputIdx int evalCtx *eval.Context + buf bytes.Buffer } func (c *castOpBase) Reset(ctx context.Context) { @@ -448,15 +450,15 @@ func (c *cast_NAMEOp) Next() coldata.Batch { if inputVec.MaybeHasNulls() { outputNulls.Copy(inputNulls) if sel != nil { - castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, true, true) + castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, &c.buf, true, true) } else { - castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, true, false) + castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, &c.buf, true, false) } } else { if sel != nil { - castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, false, true) + castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, &c.buf, false, true) } else { - castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, false, false) + castTuples(inputCol, inputNulls, outputCol, outputNulls, toType, n, sel, c.evalCtx, &c.buf, false, false) } } }, @@ -516,11 +518,13 @@ func castTuples( n int, sel []int, evalCtx *eval.Context, + buf *bytes.Buffer, hasNulls bool, hasSel bool, ) { - // Silence unused warning. + // Silence unused warnings. _ = evalCtx + _ = buf if !hasSel { // {{if $fromInfo.Sliceable}} _ = inputCol.Get(n - 1) @@ -546,7 +550,7 @@ func castTuples( } v := inputCol.Get(tupleIdx) var r _TO_GO_TYPE - _CAST(r, v, evalCtx, toType) + _CAST(r, v, evalCtx, toType, buf) if !hasSel { // {{if .Sliceable}} //gcassert:bce diff --git a/pkg/sql/colexec/execgen/cmd/execgen/avg_agg_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/avg_agg_gen.go index 8b6d1fe5a25a..a5ccf35d4179 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/avg_agg_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/avg_agg_gen.go @@ -145,7 +145,7 @@ func genAvgAgg(inputFileContents string, wr io.Writer) error { // canonical representatives, so we can operate with their type family // directly. for _, inputTypeFamily := range []types.Family{types.IntFamily, types.DecimalFamily, types.FloatFamily, types.IntervalFamily} { - tmplInfo := avgAggTypeTmplInfo{TypeFamily: toString(inputTypeFamily)} + tmplInfo := avgAggTypeTmplInfo{TypeFamily: familyToString(inputTypeFamily)} for _, inputTypeWidth := range supportedWidthsByCanonicalTypeFamily[inputTypeFamily] { // Note that we don't use execinfrapb.GetAggregateInfo because we don't // want to bring in a dependency on that package to reduce the burden diff --git a/pkg/sql/colexec/execgen/cmd/execgen/cast_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/cast_gen.go index 7e5532e639c9..8384089e5f64 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/cast_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/cast_gen.go @@ -32,8 +32,8 @@ func genCastOperators(inputFileContents string, wr io.Writer) error { ) s := r.Replace(inputFileContents) - castRe := makeFunctionRegex("_CAST", 4) - s = castRe.ReplaceAllString(s, makeTemplateFunctionCall("Cast", 4)) + castRe := makeFunctionRegex("_CAST", 5) + s = castRe.ReplaceAllString(s, makeTemplateFunctionCall("Cast", 5)) tmpl, err := template.New("cast").Funcs(template.FuncMap{"buildDict": buildDict}).Parse(s) if err != nil { diff --git a/pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go b/pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go index 5a4a587ad69c..e247eef28e03 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/cast_gen_util.go @@ -41,7 +41,9 @@ var nativeCastInfos = []supportedNativeCastInfo{ {types.Bool, types.Int2, boolToIntOrFloat}, {types.Bool, types.Int4, boolToIntOrFloat}, {types.Bool, types.Int, boolToIntOrFloat}, + {types.Bool, types.String, boolToString}, + {types.Bytes, types.String, bytesToString}, {types.Bytes, types.Uuid, bytesToUUID}, {types.Date, types.Decimal, intToDecimal}, @@ -53,6 +55,7 @@ var nativeCastInfos = []supportedNativeCastInfo{ {types.Date, types.Int2, getIntToIntCastFunc(64 /* fromWidth */, 16 /* toWidth */)}, {types.Date, types.Int4, getIntToIntCastFunc(64 /* fromWidth */, 32 /* toWidth */)}, {types.Date, types.Int, getIntToIntCastFunc(64 /* fromWidth */, anyWidth)}, + {types.Date, types.String, dateToString}, {types.Decimal, types.Bool, decimalToBool}, {types.Decimal, types.Decimal, decimalToDecimal}, @@ -60,28 +63,35 @@ var nativeCastInfos = []supportedNativeCastInfo{ {types.Decimal, types.Int2, getDecimalToIntCastFunc(16)}, {types.Decimal, types.Int4, getDecimalToIntCastFunc(32)}, {types.Decimal, types.Int, getDecimalToIntCastFunc(anyWidth)}, + {types.Decimal, types.String, decimalToString}, {types.Float, types.Bool, numToBool}, {types.Float, types.Decimal, floatToDecimal}, {types.Float, types.Int2, floatToInt(16, 64 /* floatWidth */)}, {types.Float, types.Int4, floatToInt(32, 64 /* floatWidth */)}, {types.Float, types.Int, floatToInt(anyWidth, 64 /* floatWidth */)}, + {types.Float, types.String, floatToString}, {types.Int2, types.Bool, numToBool}, {types.Int2, types.Decimal, intToDecimal}, {types.Int2, types.Float, intToFloat}, {types.Int2, types.Int4, getIntToIntCastFunc(16, 32)}, {types.Int2, types.Int, getIntToIntCastFunc(16, anyWidth)}, + {types.Int2, types.String, intToString}, {types.Int4, types.Bool, numToBool}, {types.Int4, types.Decimal, intToDecimal}, {types.Int4, types.Float, intToFloat}, {types.Int4, types.Int2, getIntToIntCastFunc(32, 16)}, {types.Int4, types.Int, getIntToIntCastFunc(32, anyWidth)}, + {types.Int4, types.String, intToString}, {types.Int, types.Bool, numToBool}, {types.Int, types.Decimal, intToDecimal}, {types.Int, types.Float, intToFloat}, {types.Int, types.Int2, getIntToIntCastFunc(anyWidth, 16)}, {types.Int, types.Int4, getIntToIntCastFunc(anyWidth, 32)}, + {types.Int, types.String, intToString}, + + {types.Interval, types.String, intervalToString}, {types.Jsonb, types.String, jsonToString}, @@ -99,6 +109,12 @@ var nativeCastInfos = []supportedNativeCastInfo{ {types.String, types.Timestamp, getStringToTimestampCastFunc(true /* withoutTimezone */)}, {types.String, types.TimestampTZ, getStringToTimestampCastFunc(false /* withoutTimezone */)}, {types.String, types.Uuid, stringToUUID}, + + {types.Timestamp, types.String, timestampToString}, + + {types.TimestampTZ, types.String, timestampTZToString}, + + {types.Uuid, types.String, uuidToString}, } type supportedNativeCastInfo struct { @@ -107,7 +123,7 @@ type supportedNativeCastInfo struct { cast castFunc } -func boolToIntOrFloat(to, from, _, _ string) string { +func boolToIntOrFloat(to, from, _, _, _ string) string { convStr := ` %[1]s = 0 if %[2]s { @@ -117,7 +133,19 @@ func boolToIntOrFloat(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } -func bytesToUUID(to, from, _, _ string) string { +func boolToString(to, from, _, toType, _ string) string { + return toString(fmt.Sprintf("%s = []byte(strconv.FormatBool(%s))", to, from), to, toType) +} + +func bytesToString(to, from, evalCtx, toType, _ string) string { + convStr := ` + _format := %[3]s.SessionData().DataConversionConfig.BytesEncodeFormat + %[1]s = []byte(lex.EncodeByteArrayToRawBytes(string(%[2]s), _format, false /* skipHexPrefix */)) +` + return toString(fmt.Sprintf(convStr, to, from, evalCtx), to, toType) +} + +func bytesToUUID(to, from, _, _, _ string) string { convStr := ` _uuid, err := uuid.FromBytes(%[2]s) if err != nil { @@ -128,15 +156,25 @@ func bytesToUUID(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } -func decimalToBool(to, from, _, _ string) string { +func dateToString(to, from, _, toType, buf string) string { + convStr := ` + _date := pgdate.MakeCompatibleDateFromDisk(%[2]s) + %[3]s.Reset() + _date.Format(%[3]s) + %[1]s = []byte(%[3]s.String()) + ` + return toString(fmt.Sprintf(convStr, to, from, buf), to, toType) +} + +func decimalToBool(to, from, _, _, _ string) string { return fmt.Sprintf("%[1]s = %[2]s.Sign() != 0", to, from) } -func decimalToDecimal(to, from, _, toType string) string { +func decimalToDecimal(to, from, _, toType, _ string) string { return toDecimal(fmt.Sprintf(`%[1]s.Set(&%[2]s)`, to, from), to, toType) } -func decimalToFloat(to, from, _, _ string) string { +func decimalToFloat(to, from, _, _, _ string) string { convStr := ` { f, err := %[2]s.Float64() @@ -153,7 +191,7 @@ func getDecimalToIntCastFunc(toIntWidth int32) castFunc { if toIntWidth == anyWidth { toIntWidth = 64 } - return func(to, from, evalCtx, toType string) string { + return func(to, from, evalCtx, toType, buf string) string { // convStr is a format string expecting three arguments: // 1. the code snippet that performs an assigment of int64 local // variable named '_i' to the result, possibly performing the bounds @@ -184,13 +222,17 @@ func getDecimalToIntCastFunc(toIntWidth int32) castFunc { } return fmt.Sprintf( convStr, - getIntToIntCastFunc(64 /* fromWidth */, toIntWidth)(to, "_i" /* from */, evalCtx, toType), + getIntToIntCastFunc(64 /* fromWidth */, toIntWidth)(to, "_i" /* from */, evalCtx, toType, buf), from, errOutOfRange, ) } } +func decimalToString(to, from, _, toType, _ string) string { + return toString(fmt.Sprintf("%s = []byte(%s.String())", to, from), to, toType) +} + // toDecimal returns the templated code that performs the cast to a decimal. It // first will execute whatever is passed in 'conv' (the main conversion) and // then will perform the rounding of 'to' variable according to 'toType'. @@ -204,14 +246,14 @@ func toDecimal(conv, to, toType string) string { return fmt.Sprintf(convStr, conv, to, toType) } -func numToBool(to, from, _, _ string) string { +func numToBool(to, from, _, _, _ string) string { convStr := ` %[1]s = %[2]s != 0 ` return fmt.Sprintf(convStr, to, from) } -func floatToDecimal(to, from, _, toType string) string { +func floatToDecimal(to, from, _, toType, _ string) string { convStr := ` if _, err := %[1]s.SetFloat64(float64(%[2]s)); err != nil { colexecerror.ExpectedError(err) @@ -220,8 +262,8 @@ func floatToDecimal(to, from, _, toType string) string { return toDecimal(fmt.Sprintf(convStr, to, from), to, toType) } -func floatToInt(intWidth, floatWidth int32) func(string, string, string, string) string { - return func(to, from, _, _ string) string { +func floatToInt(intWidth, floatWidth int32) castFunc { + return func(to, from, _, _, _ string) string { convStr := ` if math.IsNaN(float64(%[2]s)) || %[2]s <= float%[4]d(math.MinInt%[3]d) || %[2]s >= float%[4]d(math.MaxInt%[3]d) { colexecerror.ExpectedError(tree.ErrIntOutOfRange) @@ -235,14 +277,22 @@ func floatToInt(intWidth, floatWidth int32) func(string, string, string, string) } } -func intToDecimal(to, from, _, toType string) string { +func floatToString(to, from, evalCtx, toType, _ string) string { + convStr := ` + dcc := %[3]s.SessionData().DataConversionConfig + %[1]s = tree.PgwireFormatFloat(nil /* buf */, %[2]s, dcc, types.Float) +` + return toString(fmt.Sprintf(convStr, to, from, evalCtx), to, toType) +} + +func intToDecimal(to, from, _, toType, _ string) string { conv := ` %[1]s.SetInt64(int64(%[2]s)) ` return toDecimal(fmt.Sprintf(conv, to, from), to, toType) } -func intToFloat(to, from, _, _ string) string { +func intToFloat(to, from, _, _, _ string) string { convStr := ` %[1]s = float64(%[2]s) ` @@ -257,7 +307,7 @@ func getIntToIntCastFunc(fromWidth, toWidth int32) castFunc { if toWidth == anyWidth { toWidth = 64 } - return func(to, from, _, _ string) string { + return func(to, from, _, _, _ string) string { if fromWidth <= toWidth { // If we're not reducing the width, there is no need to perform the // integer range check. @@ -286,23 +336,40 @@ func getIntToIntCastFunc(fromWidth, toWidth int32) castFunc { } } -func jsonToString(to, from, _, toType string) string { +func intToString(to, from, _, toType, _ string) string { convStr := ` - _string := %[2]s.String() - switch %[3]s.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values. - _string = util.TruncateString(_string, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - _string = strings.TrimRight(_string, " ") + if %[3]s.Oid() == oid.T_char { + // int to "char" casts just return the corresponding ASCII byte. + if %[2]s > math.MaxInt8 || %[2]s < math.MinInt8 { + colexecerror.ExpectedError(tree.ErrCharOutOfRange) + } + if %[2]s == 0 { + %[1]s = []byte{} + } else { + %[1]s = []byte{byte(%[2]s)} + } + } else { + %[1]s = []byte(strconv.FormatInt(int64(%[2]s), 10)) } - %[1]s = []byte(_string) - ` - return fmt.Sprintf(convStr, to, from, toType) +` + return toString(fmt.Sprintf(convStr, to, from, toType), to, toType) +} + +func intervalToString(to, from, evalCtx, toType, buf string) string { + convStr := ` + dcc := %[3]s.SessionData().DataConversionConfig + %[4]s.Reset() + %[2]s.FormatWithStyle(%[4]s, dcc.IntervalStyle) + %[1]s = []byte(%[4]s.String()) +` + return toString(fmt.Sprintf(convStr, to, from, evalCtx, buf), to, toType) +} + +func jsonToString(to, from, _, toType, _ string) string { + return toString(fmt.Sprintf("%s = []byte(%s.String())", to, from), to, toType) } -func stringToBool(to, from, _, _ string) string { +func stringToBool(to, from, _, _, _ string) string { convStr := ` var err error %[1]s, err = tree.ParseBool(string(%[2]s)) @@ -313,7 +380,7 @@ func stringToBool(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } -func stringToBytes(to, from, _, _ string) string { +func stringToBytes(to, from, _, _, _ string) string { convStr := ` var err error %[1]s, err = lex.DecodeRawBytesToByteArrayAuto(%[2]s) @@ -324,7 +391,7 @@ func stringToBytes(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } -func stringToDate(to, from, evalCtx, _ string) string { +func stringToDate(to, from, evalCtx, _, _ string) string { convStr := ` _now := %[3]s.GetRelativeParseTime() _dateStyle := %[3]s.GetDateStyle() @@ -337,7 +404,7 @@ func stringToDate(to, from, evalCtx, _ string) string { return fmt.Sprintf(convStr, to, from, evalCtx) } -func stringToDecimal(to, from, _, toType string) string { +func stringToDecimal(to, from, _, toType, _ string) string { convStr := ` _s := strings.TrimSpace(string(%[2]s)) _, res, err := tree.ExactCtx.SetString(&%[1]s, _s) @@ -359,7 +426,7 @@ func stringToDecimal(to, from, _, toType string) string { return toDecimal(fmt.Sprintf(convStr, to, from), to, toType) } -func stringToFloat(to, from, _, toType string) string { +func stringToFloat(to, from, _, toType, _ string) string { convStr := ` _s := string(%[2]s) var _err error @@ -375,7 +442,7 @@ func getStringToIntCastFunc(toIntWidth int32) castFunc { if toIntWidth == anyWidth { toIntWidth = 64 } - return func(to, from, evalCtx, toType string) string { + return func(to, from, evalCtx, toType, buf string) string { // convStr is a format string expecting three arguments: // 1. the code snippet that performs an assigment of int64 local // variable named '_i' to the result, possibly performing the bounds @@ -394,14 +461,14 @@ func getStringToIntCastFunc(toIntWidth int32) castFunc { ` return fmt.Sprintf( convStr, - getIntToIntCastFunc(64 /* fromWidth */, toIntWidth)(to, "_i" /* from */, evalCtx, toType), + getIntToIntCastFunc(64 /* fromWidth */, toIntWidth)(to, "_i" /* from */, evalCtx, toType, buf), from, toType, ) } } -func stringToInterval(to, from, evalCtx, toType string) string { +func stringToInterval(to, from, evalCtx, toType, _ string) string { convStr := ` _itm, err := %[4]s.IntervalTypeMetadata() if err != nil { @@ -416,7 +483,7 @@ func stringToInterval(to, from, evalCtx, toType string) string { return fmt.Sprintf(convStr, to, from, evalCtx, toType) } -func stringToJSON(to, from, _, _ string) string { +func stringToJSON(to, from, _, _, _ string) string { convStr := ` var err error %[1]s, err = json.ParseJSON(string(%[2]s)) @@ -427,13 +494,19 @@ func stringToJSON(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } -func stringToString(to, from, _, toType string) string { +// TODO(yuzefovich): figure out whether we can avoid converting to a string in +// the template below. + +// toString returns the templated code that performs the cast to a string. It +// first will execute whatever is passed in 'conv' (the main conversion) and +// then will perform the truncation of 'to' variable according to 'toType'. +func toString(conv, to, toType string) string { + // The logic here is a combination of the relevant pieces from + // eval.performCastWithoutPrecisionTruncation as well as from + // tree.AdjustValueToType. convStr := ` - if %[3]s.Oid() == oid.T_name { - // For Names we don't perform the truncation, and there is no need - // to do anything about the Oids since those are stored in the type. - %[1]s = %[2]s - } else { + %[1]s + if %[3]s.Oid() != oid.T_name { // bpchar types truncate trailing whitespace. if %[3]s.Oid() == oid.T_bpchar { %[2]s = bytes.TrimRight(%[2]s, " ") @@ -442,24 +515,41 @@ func stringToString(to, from, _, toType string) string { // 'hello'::CHAR(2) -> 'he' // This is true of all the string type variants. if %[3]s.Width() > 0 { - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. %[2]s = []byte(util.TruncateString(string(%[2]s), int(%[3]s.Width()))) } if %[3]s.Oid() == oid.T_char { // "char" is supposed to truncate long values. - // TODO(yuzefovich): figure out whether we can avoid converting - // to a string. %[2]s = []byte(util.TruncateString(string(%[2]s), 1)) } - %[1]s = %[2]s + } + if %[3]s.Width() > 0 && utf8.RuneCountInString(string(%[2]s)) > int(%[3]s.Width()) { + _typeString := %[3]s.SQLString() + colexecerror.ExpectedError( + pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type " + _typeString, + )) } ` - return fmt.Sprintf(convStr, to, from, toType) + return fmt.Sprintf(convStr, conv, to, toType) +} + +func stringToString(to, from, _, toType, _ string) string { + return toString(fmt.Sprintf("%s = %s", to, from), to, toType) } -func getStringToTimestampCastFunc(withoutTimezone bool) func(_, _, _, _ string) string { - return func(to, from, evalCtx, toType string) string { +// roundTimestamp is a template that takes a timestamp specified by 'from', +// rounds it according to 'precision', and assigns the result to 'to' timestamp. +func roundTimestamp(to, from, precision string) string { + roundStr := ` + %[1]s = %[2]s.Round(%[3]s) + if %[1]s.After(tree.MaxSupportedTime) || %[1]s.Before(tree.MinSupportedTime) { + colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(%[1]s)) + } +` + return fmt.Sprintf(roundStr, to, from, precision) +} + +func getStringToTimestampCastFunc(withoutTimezone bool) castFunc { + return func(to, from, evalCtx, toType, _ string) string { var parseTimestampKind string if withoutTimezone { parseTimestampKind = "WithoutTimezone" @@ -475,16 +565,14 @@ func getStringToTimestampCastFunc(withoutTimezone bool) func(_, _, _, _ string) if err != nil { colexecerror.ExpectedError(err) } - %[1]s = _t.Round(_roundTo) - if %[1]s.After(tree.MaxSupportedTime) || %[1]s.Before(tree.MinSupportedTime) { - colexecerror.ExpectedError(tree.NewTimestampExceedsBoundsError(%[1]s)) - } + %[1]s ` - return fmt.Sprintf(convStr, to, from, evalCtx, toType, parseTimestampKind) + roundAndAssign := roundTimestamp(to, "_t", "_roundTo") + return fmt.Sprintf(convStr, roundAndAssign, from, evalCtx, toType, parseTimestampKind) } } -func stringToUUID(to, from, _, _ string) string { +func stringToUUID(to, from, _, _, _ string) string { convStr := ` _uuid, err := uuid.FromString(string(%[2]s)) if err != nil { @@ -495,14 +583,40 @@ func stringToUUID(to, from, _, _ string) string { return fmt.Sprintf(convStr, to, from) } +func timestampToString(to, from, _, toType, _ string) string { + return toString(fmt.Sprintf("%s = []byte(tree.FormatTimestamp(%s))", to, from), to, toType) +} + +func timestampTZToString(to, from, evalCtx, toType, buf string) string { + convStr := ` + // Convert to context timezone for correct display. + _t := %[2]s.In(%[3]s.GetLocation()) + %[5]s + %[4]s.Reset() + tree.FormatTimestampTZ(_t, %[4]s) + %[1]s = []byte(%[4]s.String()) +` + roundT := roundTimestamp("_t", "_t", "time.Microsecond") + return toString(fmt.Sprintf(convStr, to, from, evalCtx, buf, roundT), to, toType) +} + +func uuidToString(to, from, _, toType, _ string) string { + convStr := ` + _uuid, err := uuid.FromBytes(%[2]s) + if err != nil { + colexecerror.ExpectedError(err) + } + %[1]s = []byte(_uuid.String()) + ` + return toString(fmt.Sprintf(convStr, to, from), to, toType) +} + // getDatumToNativeCastFunc returns a castFunc for casting datum-backed value // to a value of the specified physical representation (i.e. to natively // supported type). The returned castFunc assumes that there is a converter // function named "converter" in scope. -func getDatumToNativeCastFunc( - nonDatumPhysicalRepresentation string, -) func(string, string, string, string) string { - return func(to, from, evalCtx, toType string) string { +func getDatumToNativeCastFunc(nonDatumPhysicalRepresentation string) castFunc { + return func(to, from, evalCtx, toType, _ string) string { convStr := ` { _castedDatum, err := eval.PerformCast(%[3]s, %[2]s.(tree.Datum), %[4]s) @@ -516,7 +630,7 @@ func getDatumToNativeCastFunc( } } -func datumToDatum(to, from, evalCtx, toType string) string { +func datumToDatum(to, from, evalCtx, toType, _ string) string { convStr := ` { _castedDatum, err := eval.PerformCast(%[3]s, %[2]s.(tree.Datum), %[4]s) @@ -638,8 +752,8 @@ func (i castToWidthTmplInfo) TypeName() string { return getTypeName(i.toType) } -func (i castToWidthTmplInfo) Cast(to, from, evalCtx, toType string) string { - return i.CastFn(to, from, evalCtx, toType) +func (i castToWidthTmplInfo) Cast(to, from, evalCtx, toType, buf string) string { + return i.CastFn(to, from, evalCtx, toType, buf) } func (i castToWidthTmplInfo) Sliceable() bool { @@ -662,8 +776,8 @@ func (i castDatumToWidthTmplInfo) TypeName() string { return getTypeName(i.toType) } -func (i castDatumToWidthTmplInfo) Cast(to, from, evalCtx, toType string) string { - return i.CastFn(to, from, evalCtx, toType) +func (i castDatumToWidthTmplInfo) Cast(to, from, evalCtx, toType, buf string) string { + return i.CastFn(to, from, evalCtx, toType, buf) } func (i castDatumToWidthTmplInfo) Sliceable() bool { @@ -674,8 +788,8 @@ func (i castBetweenDatumsTmplInfo) TypeName() string { return datumVecTypeName } -func (i castBetweenDatumsTmplInfo) Cast(to, from, evalCtx, toType string) string { - return datumToDatum(to, from, evalCtx, toType) +func (i castBetweenDatumsTmplInfo) Cast(to, from, evalCtx, toType, buf string) string { + return datumToDatum(to, from, evalCtx, toType, buf) } func (i castBetweenDatumsTmplInfo) Sliceable() bool { diff --git a/pkg/sql/colexec/execgen/cmd/execgen/overloads_base.go b/pkg/sql/colexec/execgen/cmd/execgen/overloads_base.go index 21f067226667..74438060106b 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/overloads_base.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/overloads_base.go @@ -123,7 +123,7 @@ func (b *overloadBase) String() string { return fmt.Sprintf("%s: %s", b.Name, b.OpStr) } -func toString(family types.Family) string { +func familyToString(family types.Family) string { switch family { case typeconv.DatumVecCanonicalTypeFamily: return "typeconv.DatumVecCanonicalTypeFamily" @@ -140,7 +140,7 @@ type argTypeOverloadBase struct { func newArgTypeOverloadBase(canonicalTypeFamily types.Family) *argTypeOverloadBase { return &argTypeOverloadBase{ CanonicalTypeFamily: canonicalTypeFamily, - CanonicalTypeFamilyStr: toString(canonicalTypeFamily), + CanonicalTypeFamilyStr: familyToString(canonicalTypeFamily), } } @@ -359,7 +359,7 @@ type twoArgsResolvedOverloadRightWidthInfo struct { type assignFunc func(op *lastArgWidthOverload, targetElem, leftElem, rightElem, targetCol, leftCol, rightCol string) string type compareFunc func(targetElem, leftElem, rightElem, leftCol, rightCol string) string -type castFunc func(to, from, evalCtx, toType string) string +type castFunc func(to, from, evalCtx, toType, buf string) string type hashFunc func(targetElem, vElem, vVec, vIdx string) string // Assign produces a Go source string that assigns the "targetElem" variable to diff --git a/pkg/sql/colexec/execgen/cmd/execgen/overloads_gen_util.go b/pkg/sql/colexec/execgen/cmd/execgen/overloads_gen_util.go index bfe96534ab77..8ba86057b752 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/overloads_gen_util.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/overloads_gen_util.go @@ -49,13 +49,13 @@ func populateTwoArgsOverloads( if !found { colexecerror.InternalError(errors.AssertionFailedf("didn't find supported widths for %s", leftFamily)) } - leftFamilyStr := toString(leftFamily) + leftFamilyStr := familyToString(leftFamily) for _, rightFamily := range combinableCanonicalTypeFamilies[leftFamily] { rightWidths, found := supportedWidthsByCanonicalTypeFamily[rightFamily] if !found { colexecerror.InternalError(errors.AssertionFailedf("didn't find supported widths for %s", rightFamily)) } - rightFamilyStr := toString(rightFamily) + rightFamilyStr := familyToString(rightFamily) for _, leftWidth := range leftWidths { for _, rightWidth := range rightWidths { customizer, ok := customizers[typePair{leftFamily, leftWidth, rightFamily, rightWidth}] diff --git a/pkg/sql/colexec/execgen/cmd/execgen/range_offset_handler_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/range_offset_handler_gen.go index 4c3bb9932452..feaad76bebf4 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/range_offset_handler_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/range_offset_handler_gen.go @@ -76,7 +76,7 @@ func rangeOffsetHandlerGenerator(inputFileContents string, wr io.Writer) error { ordColDirInfo := windowFrameOrdDirInfo{IsOrdColAsc: isOrdColAsc} for _, typeFamily := range rangeOrderColTypeFamilies { canonicalTypeFamily := typeconv.TypeFamilyToCanonicalTypeFamily(typeFamily) - typeFamilyStr := toString(typeFamily) + typeFamilyStr := familyToString(typeFamily) typeFamilyInfo := windowFrameOrderTypeFamilyInfo{ TypeFamily: typeFamilyStr, } diff --git a/pkg/sql/colexec/execgen/cmd/execgen/span_encoder_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/span_encoder_gen.go index b0f7e238b384..bd390c673dd3 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/span_encoder_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/span_encoder_gen.go @@ -48,7 +48,7 @@ func genSpanEncoder(inputFileContents string, wr io.Writer) error { // We are currently unable to encode JSON as a table key. continue } - familyInfo := spanEncoderTypeFamilyInfo{TypeFamily: toString(family)} + familyInfo := spanEncoderTypeFamilyInfo{TypeFamily: familyToString(family)} for _, width := range supportedWidthsByCanonicalTypeFamily[family] { overload := spanEncoderTmplInfo{ Asc: asc, diff --git a/pkg/sql/colexec/execgen/cmd/execgen/sum_agg_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/sum_agg_gen.go index 3b7583e56f60..64cede0e6950 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/sum_agg_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/sum_agg_gen.go @@ -161,7 +161,7 @@ func genSumAgg(inputFileContents string, wr io.Writer, isSumInt bool) error { var tmplInfos []sumAggTypeTmplInfo for _, inputTypeFamily := range supportedTypeFamilies { tmplInfo := sumAggTypeTmplInfo{ - TypeFamily: toString(inputTypeFamily), + TypeFamily: familyToString(inputTypeFamily), } for _, inputTypeWidth := range supportedWidthsByCanonicalTypeFamily[inputTypeFamily] { // Note that we don't use execinfrapb.GetAggregateInfo because we don't diff --git a/pkg/sql/sem/eval/cast.go b/pkg/sql/sem/eval/cast.go index 7fedc6246598..094e15780cc3 100644 --- a/pkg/sql/sem/eval/cast.go +++ b/pkg/sql/sem/eval/cast.go @@ -399,7 +399,7 @@ func performCastWithoutPrecisionTruncation( s = string(b) case *tree.DInt: if typ.Oid() == oid.T_char { - // int to "char" casts just return the correspondong ASCII byte. + // int to "char" casts just return the corresponding ASCII byte. if *t > math.MaxInt8 || *t < math.MinInt8 { return nil, tree.ErrCharOutOfRange } else if *t == 0 { diff --git a/pkg/sql/sem/tree/datum.go b/pkg/sql/sem/tree/datum.go index 60cd0a61800c..2fa33c4d758e 100644 --- a/pkg/sql/sem/tree/datum.go +++ b/pkg/sql/sem/tree/datum.go @@ -2807,6 +2807,11 @@ func (d *DTimestamp) Max(ctx CompareContext) (Datum, bool) { // AmbiguousFormat implements the Datum interface. func (*DTimestamp) AmbiguousFormat() bool { return true } +// FormatTimestamp outputs a timestamp in the UTC timezone. +func FormatTimestamp(t time.Time) string { + return t.UTC().Format(timestampOutputFormat) +} + // Format implements the NodeFormatter interface. func (d *DTimestamp) Format(ctx *FmtCtx) { f := ctx.flags @@ -2814,7 +2819,7 @@ func (d *DTimestamp) Format(ctx *FmtCtx) { if !bareStrings { ctx.WriteByte('\'') } - ctx.WriteString(d.UTC().Format(timestampOutputFormat)) + ctx.WriteString(FormatTimestamp(d.Time)) if !bareStrings { ctx.WriteByte('\'') } @@ -2974,15 +2979,11 @@ func (d *DTimestampTZ) Max(ctx CompareContext) (Datum, bool) { // AmbiguousFormat implements the Datum interface. func (*DTimestampTZ) AmbiguousFormat() bool { return true } -// Format implements the NodeFormatter interface. -func (d *DTimestampTZ) Format(ctx *FmtCtx) { - f := ctx.flags - bareStrings := f.HasFlags(FmtFlags(lexbase.EncBareStrings)) - if !bareStrings { - ctx.WriteByte('\'') - } - ctx.WriteString(d.Time.Format(timestampTZOutputFormat)) - _, offsetSecs := d.Time.Zone() +// FormatTimestampTZ formats the given timestamp with timezone into the provided +// buffer. +func FormatTimestampTZ(t time.Time, buf *bytes.Buffer) { + buf.WriteString(t.Format(timestampTZOutputFormat)) + _, offsetSecs := t.Zone() // Only output remaining seconds offsets if it is available. // This is to maintain backward compatibility with older CRDB versions, // where we only output HH:MM. @@ -2990,9 +2991,19 @@ func (d *DTimestampTZ) Format(ctx *FmtCtx) { if secondOffset < 0 { secondOffset = 60 + secondOffset } - ctx.WriteByte(':') - ctx.WriteString(fmt.Sprintf("%02d", secondOffset)) + buf.WriteByte(':') + buf.WriteString(fmt.Sprintf("%02d", secondOffset)) + } +} + +// Format implements the NodeFormatter interface. +func (d *DTimestampTZ) Format(ctx *FmtCtx) { + f := ctx.flags + bareStrings := f.HasFlags(FmtFlags(lexbase.EncBareStrings)) + if !bareStrings { + ctx.WriteByte('\'') } + FormatTimestampTZ(d.Time, &ctx.Buffer) if !bareStrings { ctx.WriteByte('\'') } @@ -5640,7 +5651,14 @@ func AdjustValueToType(typ *types.T, inVal Datum) (outVal Datum, err error) { } else if v, ok := inVal.(*DCollatedString); ok { sv = v.Contents } - sv = adjustStringValueToType(typ, sv) + switch typ.Oid() { + case oid.T_char: + // "char" is supposed to truncate long values. + sv = util.TruncateString(sv, 1) + case oid.T_bpchar: + // bpchar types truncate trailing whitespace. + sv = strings.TrimRight(sv, " ") + } if typ.Width() > 0 && utf8.RuneCountInString(sv) > int(typ.Width()) { return nil, pgerror.Newf(pgcode.StringDataRightTruncation, "value too long for type %s", @@ -5783,17 +5801,3 @@ func AdjustValueToType(typ *types.T, inVal Datum) (outVal Datum, err error) { } return inVal, nil } - -// adjustStringToType checks that the width for strings fits the -// specified column type. -func adjustStringValueToType(typ *types.T, sv string) string { - switch typ.Oid() { - case oid.T_char: - // "char" is supposed to truncate long values - return util.TruncateString(sv, 1) - case oid.T_bpchar: - // bpchar types truncate trailing whitespace. - return strings.TrimRight(sv, " ") - } - return sv -}