Skip to content

Commit

Permalink
exec: bail out on mixed type expressions
Browse files Browse the repository at this point in the history
Since our vectorized projection and selection operators currently only
handle homogeneous types, I added logic to the planner which detects
mixed types and errors out.

Fixes #38798

Release note: None
  • Loading branch information
solongordon committed Jul 11, 2019
1 parent 73b2f22 commit 908fe7b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
44 changes: 32 additions & 12 deletions pkg/sql/distsqlrun/column_exec_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,9 @@ func newColOperator(
func planSelectionOperators(
ctx *tree.EvalContext, expr tree.TypedExpr, columnTypes []semtypes.T, input exec.Operator,
) (op exec.Operator, resultIdx int, ct []semtypes.T, err error) {
if err := assertHomogeneousTypes(expr); err != nil {
return op, resultIdx, ct, err
}
switch t := expr.(type) {
case *tree.IndexedVar:
return exec.NewBoolVecToSelOp(input, t.Idx), -1, columnTypes, nil
Expand Down Expand Up @@ -583,12 +586,6 @@ func planSelectionOperators(
if err != nil {
return nil, resultIdx, ct, err
}
if !ct[leftIdx].Identical(&ct[rightIdx]) {
err = errors.Errorf(
"comparison between %s and %s is unhandled", ct[leftIdx].Family(),
ct[rightIdx].Family())
return nil, resultIdx, ct, err
}
op, err := exec.GetSelectionOperator(typ, cmpOp, rightOp, leftIdx, rightIdx)
return op, resultIdx, ct, err
default:
Expand All @@ -603,6 +600,9 @@ func planSelectionOperators(
func planProjectionOperators(
ctx *tree.EvalContext, expr tree.TypedExpr, columnTypes []semtypes.T, input exec.Operator,
) (op exec.Operator, resultIdx int, ct []semtypes.T, err error) {
if err := assertHomogeneousTypes(expr); err != nil {
return op, resultIdx, ct, err
}
resultIdx = -1
switch t := expr.(type) {
case *tree.IndexedVar:
Expand Down Expand Up @@ -693,18 +693,38 @@ func planProjectionExpr(
if err != nil {
return nil, resultIdx, nil, err
}
if !ct[leftIdx].Identical(&ct[rightIdx]) {
err = errors.Errorf(
"projection on %s and %s is unhandled", ct[leftIdx].Family(),
ct[rightIdx].Family())
return nil, resultIdx, ct, err
}
resultIdx = len(ct)
op, err = exec.GetProjectionOperator(typ, binOp, rightOp, leftIdx, rightIdx, resultIdx)
ct = append(ct, *typ)
return op, resultIdx, ct, err
}

// assertHomogeneousTypes checks that the left and right sides of an expression
// have identical types. (Vectorized execution does not yet handle mixed types.)
// For BinaryExprs, it also checks that the result type matches, since this is
// not the case for certain operations like integer division.
func assertHomogeneousTypes(expr tree.TypedExpr) error {
switch t := expr.(type) {
case *tree.BinaryExpr:
left := t.TypedLeft().ResolvedType()
right := t.TypedRight().ResolvedType()
result := t.ResolvedType()
if !left.Identical(right) {
return errors.Errorf("BinaryExpr on %s and %s is unhandled", left, right)
}
if !left.Identical(result) {
return errors.Errorf("BinaryExpr on %s with %s result is unhandled", left, result)
}
case *tree.ComparisonExpr:
left := t.TypedLeft().ResolvedType()
right := t.TypedRight().ResolvedType()
if !left.Identical(right) {
return errors.Errorf("ComparisonExpr on %s and %s is unhandled", left, right)
}
}
return nil
}

// wrapWithVectorizedStatsCollector creates a new exec.VectorizedStatsCollector
// that wraps op and connects the newly created wrapper with those
// corresponding to operators in inputs (the latter must have already been
Expand Down
12 changes: 12 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/vectorize
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,15 @@ query O
SELECT * FROM t38754
----
1

# Test integer division. (Should fall back due to decimal result.)
query T
SELECT a/b FROM a WHERE b = 2
----
0.5

# Test mixed types comparison. (Should also fall back.)
query I
SELECT b FROM a WHERE b < 0.5
----
0

0 comments on commit 908fe7b

Please sign in to comment.