Skip to content

Commit

Permalink
Merge pull request #85895 from yuzefovich/backport22.1-85869
Browse files Browse the repository at this point in the history
release-22.1: colexecbase: fix bpchar to bpchar cast
  • Loading branch information
yuzefovich authored Aug 10, 2022
2 parents 4f1b6a3 + 9d195ea commit be21fa9
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 31 deletions.
1 change: 0 additions & 1 deletion pkg/sql/colexec/colexecbase/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ go_test(
"//pkg/util/log",
"//pkg/util/mon",
"//pkg/util/randutil",
"@com_github_lib_pq//oid",
"@com_github_stretchr_testify//require",
],
)
Expand Down
54 changes: 53 additions & 1 deletion pkg/sql/colexec/colexecbase/cast.eg.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 4 additions & 28 deletions pkg/sql/colexec/colexecbase/cast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/randutil"
"github.com/lib/pq/oid"
"github.com/stretchr/testify/require"
)

Expand All @@ -46,12 +45,6 @@ func TestRandomizedCast(t *testing.T) {
getValidSupportedCast := func() (from, to *types.T) {
for {
from, to = randgen.RandType(rng), randgen.RandType(rng)
if from.Oid() == oid.T_void && to.Oid() == oid.T_bpchar {
// Skip the cast from void to char because such setup would get
// stuck forever in the datum generation (due to the TODO
// below).
continue
}
if _, ok := tree.LookupCastVolatility(from, to, nil /* sessiondata */); ok {
if colexecbase.IsCastSupported(from, to) {
return from, to
Expand All @@ -71,27 +64,10 @@ func TestRandomizedCast(t *testing.T) {
toConverter := colconv.GetDatumToPhysicalFn(to)
errorExpected := false
for i := 0; i < numRows; i++ {
var (
fromDatum, toDatum tree.Datum
err error
)
// Datum generation. The loop exists only because of the TODO below.
for {
// We don't allow any NULL datums to be generated, so disable
// this ability in the RandDatum function.
fromDatum = randgen.RandDatum(rng, from, false)
toDatum, err = tree.PerformCast(&evalCtx, fromDatum, to)
if to.Oid() == oid.T_bpchar && string(*toDatum.(*tree.DString)) == "" {
// There is currently a problem when converting an empty
// string datum to a physical representation, so we skip
// such a datum and retry generation.
// TODO(yuzefovich): figure it out. When removing this
// check, remove the special casing for 'void -> char' cast
// above.
continue
}
break
}
// We don't allow any NULL datums to be generated, so disable
// this ability in the RandDatum function.
fromDatum := randgen.RandDatum(rng, from, false)
toDatum, err := tree.PerformCast(&evalCtx, fromDatum, to)
var toPhys interface{}
if err != nil {
errorExpected = true
Expand Down
54 changes: 53 additions & 1 deletion pkg/sql/colexec/colexecbase/cast_tmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,15 @@ func GetCastOperator(
return &castOpNullAny{castOpBase: base}, nil
}
if isIdentityCast(fromType, toType) {
return &castIdentityOp{castOpBase: base}, nil
// bpchars require special handling.
if toType.Oid() == oid.T_bpchar {
return &castBPCharIdentityOp{castOpBase: base}, nil
}
// If we don't have an array of bpchars, then we use the identity,
// otherwise we'll fallback to datum-datum cast below.
if toType.Oid() != oid.T__bpchar {
return &castIdentityOp{castOpBase: base}, nil
}
}
isFromDatum := typeconv.TypeFamilyToCanonicalTypeFamily(fromType.Family()) == typeconv.DatumVecCanonicalTypeFamily
isToDatum := typeconv.TypeFamilyToCanonicalTypeFamily(toType.Family()) == typeconv.DatumVecCanonicalTypeFamily
Expand Down Expand Up @@ -319,6 +327,50 @@ func (c *castIdentityOp) Next() coldata.Batch {
return batch
}

// castBPCharIdentityOp is a specialization of castIdentityOp which handles
// casts to the bpchar type (which trims trailing whitespaces).
type castBPCharIdentityOp struct {
castOpBase
}

var _ colexecop.ClosableOperator = &castBPCharIdentityOp{}

func (c *castBPCharIdentityOp) Next() coldata.Batch {
batch := c.Input.Next()
n := batch.Length()
if n == 0 {
return coldata.ZeroBatch
}
inputVec := batch.ColVec(c.colIdx)
inputCol := inputVec.Bytes()
inputNulls := inputVec.Nulls()
outputVec := batch.ColVec(c.outputIdx)
outputCol := outputVec.Bytes()
outputNulls := outputVec.Nulls()
// Note that the loops below are not as optimized as in other cast operators
// since this operator should only be planned in tests.
c.allocator.PerformOperation([]coldata.Vec{outputVec}, func() {
if sel := batch.Selection(); sel != nil {
for _, i := range sel[:n] {
if inputNulls.NullAt(i) {
outputNulls.SetNull(i)
} else {
outputCol.Set(i, bytes.TrimRight(inputCol.Get(i), " "))
}
}
} else {
for i := 0; i < n; i++ {
if inputNulls.NullAt(i) {
outputNulls.SetNull(i)
} else {
outputCol.Set(i, bytes.TrimRight(inputCol.Get(i), " "))
}
}
}
})
return batch
}

type castNativeToDatumOp struct {
castOpBase

Expand Down

0 comments on commit be21fa9

Please sign in to comment.