Skip to content

Commit

Permalink
colbuilder: pre-evaluate casts of constants in projection exprs
Browse files Browse the repository at this point in the history
During the planning of the projection expressions we have certain
optimized operators if either left or right expressions are constants.
Previously, we would simply check whether expression is a datum to see
whether it is a constant. Another simple case that this commit adds is
if we have a cast expression of a datum - this commit adds
pre-evaluation of such expressions allowing us to plan optimized
operators more often. Notably, this handles a case of a cast from NULL
which the optimizer creates in order to propagate the type of NULL.

Release note: None
  • Loading branch information
yuzefovich committed Apr 17, 2021
1 parent e29d694 commit d09246f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
25 changes: 25 additions & 0 deletions pkg/sql/colexec/colbuilder/execplan.go
Original file line number Diff line number Diff line change
Expand Up @@ -2101,6 +2101,19 @@ func checkSupportedBinaryExpr(left, right tree.TypedExpr, outputType *types.T) e
return nil
}

// preEvaluateConstCast checks whether t is a cast expression from a constant
// datum and evaluates the cast if so.
func preEvaluateConstCast(evalCtx *tree.EvalContext, t tree.TypedExpr) (tree.TypedExpr, error) {
cast, ok := t.(*tree.CastExpr)
if !ok {
return t, nil
}
if _, isConst := cast.Expr.(tree.Datum); !isConst {
return t, nil
}
return cast.Eval(evalCtx)
}

func planProjectionExpr(
ctx context.Context,
evalCtx *tree.EvalContext,
Expand All @@ -2117,6 +2130,18 @@ func planProjectionExpr(
if err := checkSupportedProjectionExpr(left, right); err != nil {
return nil, resultIdx, typs, err
}
// Normally, the optimizer folds all constants; however, for nulls it
// creates a cast expression from tree.DNull to the desired type in order to
// propagate the type of the null. Pre-evaluate constant casts so that the
// optimized projection operators below could be planned.
left, err = preEvaluateConstCast(evalCtx, left)
if err != nil {
return nil, resultIdx, typs, err
}
right, err = preEvaluateConstCast(evalCtx, right)
if err != nil {
return nil, resultIdx, typs, err
}
allocator := colmem.NewAllocator(ctx, acc, factory)
resultIdx = -1
// There are 3 cases. Either the left is constant, the right is constant,
Expand Down
16 changes: 16 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/vectorize_local
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,19 @@ EXPLAIN (VEC) SELECT concat_agg(_bytes), concat_agg(_string) FROM bytes_string
└ *colexec.orderedAggregator
└ *colexecbase.distinctChainOps
└ *colfetcher.ColBatchScan

statement ok
CREATE TABLE t63792 (c INT)

# Check that casts of constants are pre-evaluated (which allows us to use
# colexec.isNullProjOp instead of colexecproj.defaultCmpProjOp).
query T
EXPLAIN (VEC) SELECT c = c FROM t63792
----
└ Node 1
└ *colexec.orProjOp
├ *colfetcher.ColBatchScan
├ *colexec.isNullProjOp
└ *colexecbase.castOpNullAny
└ *colexecbase.constNullOp

0 comments on commit d09246f

Please sign in to comment.