diff --git a/pkg/sql/opt/norm/testdata/rules/decorrelate b/pkg/sql/opt/norm/testdata/rules/decorrelate index 515930be7189..6184c785ff5e 100644 --- a/pkg/sql/opt/norm/testdata/rules/decorrelate +++ b/pkg/sql/opt/norm/testdata/rules/decorrelate @@ -610,90 +610,6 @@ project └── windows └── row-number [type=int] -norm expect=TryDecorrelateWindow -SELECT - * -FROM - uv, - LATERAL ( - SELECT - row_number() OVER ( - PARTITION BY - s - ORDER BY - f - RANGE - BETWEEN u::FLOAT PRECEDING AND UNBOUNDED FOLLOWING - ), - i - FROM - a - ) ----- -project - ├── columns: u:1(int!null) v:2(int) row_number:8(int) i:4(int) - ├── fd: (1)-->(2) - └── window partition=(1,6) ordering=+5 opt(1,2,6) - ├── columns: u:1(int!null) v:2(int) i:4(int) f:5(float) s:6(string) row_number:8(int) - ├── fd: (1)-->(2) - ├── inner-join (hash) - │ ├── columns: u:1(int!null) v:2(int) i:4(int) f:5(float) s:6(string) - │ ├── fd: (1)-->(2) - │ ├── scan uv - │ │ ├── columns: u:1(int!null) v:2(int) - │ │ ├── key: (1) - │ │ └── fd: (1)-->(2) - │ ├── scan a - │ │ └── columns: i:4(int) f:5(float) s:6(string) - │ └── filters (true) - └── windows - └── windows-item: range from offset to unbounded [type=int, outer=(1)] - └── window-from-offset [type=int] - ├── row-number [type=int] - └── u::FLOAT8 [type=float] - -norm expect=TryDecorrelateWindow -SELECT - * -FROM - uv, - LATERAL ( - SELECT - row_number() OVER ( - PARTITION BY - s - ORDER BY - f - RANGE - BETWEEN UNBOUNDED PRECEDING AND u::FLOAT FOLLOWING - ), - i - FROM - a - ) ----- -project - ├── columns: u:1(int!null) v:2(int) row_number:8(int) i:4(int) - ├── fd: (1)-->(2) - └── window partition=(1,6) ordering=+5 opt(1,2,6) - ├── columns: u:1(int!null) v:2(int) i:4(int) f:5(float) s:6(string) row_number:8(int) - ├── fd: (1)-->(2) - ├── inner-join (hash) - │ ├── columns: u:1(int!null) v:2(int) i:4(int) f:5(float) s:6(string) - │ ├── fd: (1)-->(2) - │ ├── scan uv - │ │ ├── columns: u:1(int!null) v:2(int) - │ │ ├── key: (1) - │ │ └── fd: (1)-->(2) - │ ├── scan a - │ │ └── columns: i:4(int) f:5(float) s:6(string) - │ └── filters (true) - └── windows - └── windows-item: range from unbounded to offset [type=int, outer=(1)] - └── window-to-offset [type=int] - ├── row-number [type=int] - └── u::FLOAT8 [type=float] - norm expect=TryDecorrelateWindow SELECT * FROM uv, LATERAL (SELECT avg(f) FILTER (WHERE u = 3) OVER (), i FROM a) ---- diff --git a/pkg/sql/opt/norm/testdata/rules/prune_cols b/pkg/sql/opt/norm/testdata/rules/prune_cols index 6ff5c862ee63..9f227e8dd3c1 100644 --- a/pkg/sql/opt/norm/testdata/rules/prune_cols +++ b/pkg/sql/opt/norm/testdata/rules/prune_cols @@ -1657,23 +1657,6 @@ project └── ntile [type=int, outer=(2)] └── variable: t.public.a.i [type=int] -# Ensure OFFSET expressions don't get pruned. -norm -SELECT ntile(i) OVER (ORDER BY i RANGE BETWEEN f::INT PRECEDING AND CURRENT ROW) FROM a ----- -project - ├── columns: ntile:5(int) - └── window partition=() ordering=+2 - ├── columns: i:2(int) f:3(float) ntile:5(int) - ├── scan a - │ └── columns: i:2(int) f:3(float) - └── windows - └── windows-item: range from offset to current-row [type=int, outer=(2,3)] - └── window-from-offset [type=int] - ├── ntile [type=int] - │ └── variable: i [type=int] - └── f::INT8 [type=int] - # Ensure filter cols don't get pruned. norm SELECT diff --git a/pkg/sql/opt/optbuilder/testdata/window b/pkg/sql/opt/optbuilder/testdata/window index cd11585710ee..1e7c85a4daf4 100644 --- a/pkg/sql/opt/optbuilder/testdata/window +++ b/pkg/sql/opt/optbuilder/testdata/window @@ -942,20 +942,7 @@ project build SELECT avg(k) OVER (ORDER BY v RANGE BETWEEN k - 10 PRECEDING AND CURRENT ROW) FROM kv ---- -project - ├── columns: avg:8(decimal) - └── window partition=() ordering=+2 - ├── columns: k:1(int!null) v:2(int) w:3(int) f:4(float) d:5(decimal) s:6(string) b:7(bool) avg:8(decimal) - ├── scan kv - │ └── columns: k:1(int!null) v:2(int) w:3(int) f:4(float) d:5(decimal) s:6(string) b:7(bool) - └── windows - └── windows-item: range from offset to current-row [type=decimal] - └── window-from-offset [type=decimal] - ├── avg [type=decimal] - │ └── variable: k [type=int] - └── minus [type=int] - ├── variable: k [type=int] - └── const: 10 [type=int] +error (42P10): ROWS or RANGE cannot contain variables build SELECT avg(k) OVER (ORDER BY v RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING) FROM kv @@ -1061,35 +1048,7 @@ SELECT FROM kv outer_table ---- -project - ├── columns: avg:16(decimal) - └── window partition=(3) - ├── columns: outer_table.k:1(int!null) outer_table.v:2(int) outer_table.w:3(int) outer_table.f:4(float) outer_table.d:5(decimal) outer_table.s:6(string) outer_table.b:7(bool) avg:16(decimal) - ├── scan outer_table - │ └── columns: outer_table.k:1(int!null) outer_table.v:2(int) outer_table.w:3(int) outer_table.f:4(float) outer_table.d:5(decimal) outer_table.s:6(string) outer_table.b:7(bool) - └── windows - └── windows-item: rows from offset to offset [type=decimal] - └── window-to-offset [type=decimal] - ├── window-from-offset [type=decimal] - │ ├── avg [type=decimal] - │ │ └── variable: outer_table.v [type=int] - │ └── subquery [type=int] - │ └── max1-row - │ ├── columns: count_rows:15(int) - │ └── scalar-group-by - │ ├── columns: count_rows:15(int) - │ ├── project - │ │ └── select - │ │ ├── columns: inner_table.k:8(int!null) inner_table.v:9(int) inner_table.w:10(int) inner_table.f:11(float) inner_table.d:12(decimal) inner_table.s:13(string) inner_table.b:14(bool) - │ │ ├── scan inner_table - │ │ │ └── columns: inner_table.k:8(int!null) inner_table.v:9(int) inner_table.w:10(int) inner_table.f:11(float) inner_table.d:12(decimal) inner_table.s:13(string) inner_table.b:14(bool) - │ │ └── filters - │ │ └── eq [type=bool] - │ │ ├── variable: inner_table.k [type=int] - │ │ └── variable: outer_table.v [type=int] - │ └── aggregations - │ └── count-rows [type=int] - └── const: 1 [type=int] +error (42P10): ROWS or RANGE cannot contain variables build SELECT @@ -1579,3 +1538,19 @@ project ├── windows-item: range from unbounded to current-row exclude ties [type=int] │ └── rank [type=int] └── rank [type=int] + +exec-ddl +CREATE TABLE table1 (col5 CHAR, col8 INT2); +---- + +build +SELECT + min(tab_536191.col5) OVER ( + ROWS BETWEEN tab_536191.col8 FOLLOWING AND 1 FOLLOWING + ) +FROM + table1 AS tab_536191 +GROUP BY + tab_536191.col8, tab_536191.col5 +---- +error (42P10): ROWS or RANGE cannot contain variables diff --git a/pkg/sql/opt/optbuilder/window.go b/pkg/sql/opt/optbuilder/window.go index 715b557d2067..9d5d44dd9dec 100644 --- a/pkg/sql/opt/optbuilder/window.go +++ b/pkg/sql/opt/optbuilder/window.go @@ -16,6 +16,8 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/opt" "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" "github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/errors" @@ -126,6 +128,7 @@ func (b *Builder) buildWindow(outScope *scope, inScope *scope) { b.constructProjectForScope(outScope, argScope) outScope.expr = argScope.expr + var referencedCols opt.ColSet // frames accumulates the set of distinct window frames we're computing over // so that we can group functions over the same partition and ordering. frames := make([]memo.WindowExpr, 0, len(inScope.windows)) @@ -142,7 +145,9 @@ func (b *Builder) buildWindow(outScope *scope, inScope *scope) { b.buildScalar( w.WindowDef.Frame.Bounds.StartBound.OffsetExpr.(tree.TypedExpr), inScope, - nil, nil, nil, + nil, + nil, + &referencedCols, ), ) } @@ -153,7 +158,18 @@ func (b *Builder) buildWindow(outScope *scope, inScope *scope) { b.buildScalar( w.WindowDef.Frame.Bounds.EndBound.OffsetExpr.(tree.TypedExpr), inScope, - nil, nil, nil, + nil, + nil, + &referencedCols, + ), + ) + } + + if !referencedCols.Empty() { + panic( + pgerror.Newf( + pgcode.InvalidColumnReference, + "ROWS or RANGE cannot contain variables", ), ) }