Commit 5725ea04 authored by Radu Berinde's avatar Radu Berinde

sql: use volatility in normalization / IsConst

Release note: None
parent 66094721
......@@ -379,6 +379,11 @@ CREATE TABLE t (a TIMESTAMP PRIMARY KEY) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN (uuid_v4() || 'foo')
)
statement error PARTITION p1: 'now'::TIMESTAMP: partition values must be constant
CREATE TABLE t (a TIMESTAMP PRIMARY KEY) PARTITION BY LIST (a) (
PARTITION p1 VALUES IN ('now')
)
statement ok
CREATE TABLE ok1 (
a INT, b INT, c INT,
......
......@@ -141,6 +141,11 @@ func verifyColOperator(args verifyColOperatorArgs) error {
StreamingMemAccount: &acc,
DiskQueueCfg: colcontainer.DiskQueueCfg{FS: tempFS},
FDSemaphore: colexecbase.NewTestingSemaphore(256),
// TODO(yuzefovich): adjust expression generator to not produce
// mixed-type timestamp-related expressions and then disallow the
// fallback again.
ProcessorConstructor: rowexec.NewProcessor,
}
var spilled bool
if args.forceDiskSpill {
......
......@@ -30,7 +30,7 @@ import (
"github.com/stretchr/testify/require"
)
func prepareExpr(t *testing.T, datumExpr string) tree.TypedExpr {
func prepareExpr(t *testing.T, datumExpr string) tree.Datum {
expr, err := parser.ParseExpr(datumExpr)
if err != nil {
t.Fatalf("%s: %v", datumExpr, err)
......@@ -50,7 +50,11 @@ func prepareExpr(t *testing.T, datumExpr string) tree.TypedExpr {
if err != nil {
t.Fatalf("%s: %v", datumExpr, err)
}
return typedExpr
d, err := typedExpr.Eval(evalCtx)
if err != nil {
t.Fatalf("%s: %v", datumExpr, err)
}
return d
}
func TestDatumOrdering(t *testing.T) {
......@@ -229,9 +233,8 @@ func TestDatumOrdering(t *testing.T) {
}
ctx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
for _, td := range testData {
expr := prepareExpr(t, td.datumExpr)
d := prepareExpr(t, td.datumExpr)
d := expr.(tree.Datum)
prevVal, hasPrev := d.Prev(ctx)
nextVal, hasNext := d.Next(ctx)
if td.prev == noPrev {
......
......@@ -816,22 +816,37 @@ var _ Visitor = &isConstVisitor{}
func (v *isConstVisitor) VisitPre(expr Expr) (recurse bool, newExpr Expr) {
if v.isConst {
if isVar(v.ctx, expr, true /*allowConstPlaceholders*/) {
if !operatorIsImmutable(expr) || isVar(v.ctx, expr, true /*allowConstPlaceholders*/) {
v.isConst = false
return false, expr
}
switch t := expr.(type) {
case *FuncExpr:
if t.IsImpure() {
v.isConst = false
return false, expr
}
}
}
return true, expr
}
func operatorIsImmutable(expr Expr) bool {
switch t := expr.(type) {
case *FuncExpr:
return t.fnProps.Class == NormalClass && t.fn.Volatility <= VolatilityImmutable
case *CastExpr:
volatility, ok := LookupCastVolatility(t.Expr.(TypedExpr).ResolvedType(), t.typ)
return ok && volatility <= VolatilityImmutable
case *UnaryExpr:
return t.fn.Volatility <= VolatilityImmutable
case *BinaryExpr:
return t.Fn.Volatility <= VolatilityImmutable
case *ComparisonExpr:
return t.fn.Volatility <= VolatilityImmutable
default:
return true
}
}
func (*isConstVisitor) VisitPost(expr Expr) Expr { return expr }
func (v *isConstVisitor) run(expr Expr) bool {
......@@ -842,7 +857,7 @@ func (v *isConstVisitor) run(expr Expr) bool {
// IsConst returns whether the expression is constant. A constant expression
// does not contain variables, as defined by ContainsVars, nor impure functions.
func IsConst(evalCtx *EvalContext, expr Expr) bool {
func IsConst(evalCtx *EvalContext, expr TypedExpr) bool {
v := isConstVisitor{ctx: evalCtx}
return v.run(expr)
}
......@@ -885,22 +900,14 @@ func (v *fastIsConstVisitor) VisitPre(expr Expr) (recurse bool, newExpr Expr) {
}
v.visited = true
// If the parent expression is a variable or impure function, we know that it
// is not constant.
// If the parent expression is a variable or non-immutable operator, we know
// that it is not constant.
if isVar(v.ctx, expr, true /*allowConstPlaceholders*/) {
if !operatorIsImmutable(expr) || isVar(v.ctx, expr, true /*allowConstPlaceholders*/) {
v.isConst = false
return false, expr
}
switch t := expr.(type) {
case *FuncExpr:
if t.IsImpure() {
v.isConst = false
return false, expr
}
}
return true, expr
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment