Skip to content

Commit

Permalink
Merge #37251
Browse files Browse the repository at this point in the history
37251: sql: fix semantic analysis and type checking of window functions r=yuzefovich a=yuzefovich

Previously, performing semantic analysis and type checking of
related to window functions expressions was performed as a part
of analysis of FuncExpr. However, this is not sufficient in all
cases: for example, on the query like
SELECT rank() OVER (w RANGE 1 PRECEDING) FROM t WINDOW w
AS (ORDER BY a),
in order to correctly analyze 1, we need to have information about
ORDER BY clause coming from window definition w. This information
is only available after we constructed window definitions in
window.go.

Additionally, this commit now requires an ORDER BY clause with
GROUPS mode of framing (which is exactly what PostgreSQL does).
Actually, without the ordering clause, GROUPS mode doesn't make
sense since all rows will be a part of the same peer group which
probably indicates a user error, so we will return an error in
such cases.

Release note: None

Co-authored-by: Yahor Yuzefovich <yahor@cockroachlabs.com>
  • Loading branch information
craig[bot] and yuzefovich committed Jun 19, 2019
2 parents ed08d81 + 95ec639 commit b715f9f
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 240 deletions.
78 changes: 49 additions & 29 deletions pkg/sql/logictest/testdata/logic_test/window
Original file line number Diff line number Diff line change
Expand Up @@ -1977,22 +1977,22 @@ SELECT price, avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITIO
statement error frame ending offset must not be negative
SELECT product_name, price, min(price) OVER (PARTITION BY group_name ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS min_over_three, max(price) OVER (PARTITION BY group_name ROWS BETWEEN UNBOUNDED PRECEDING AND -1 FOLLOWING) AS max_over_partition FROM products ORDER BY group_id

statement error incompatible window frame start type: decimal
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ROWS 1.5 PRECEDING) AS avg_price FROM products

statement error incompatible window frame start type: decimal
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ROWS 1.5 PRECEDING)

statement error incompatible window frame start type: decimal
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ROWS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING) AS avg_price FROM products

statement error incompatible window frame start type: decimal
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ROWS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING)

statement error incompatible window frame end type: decimal
statement error argument of WINDOW FRAME END must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ROWS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) AS avg_price FROM products

statement error incompatible window frame end type: decimal
statement error argument of WINDOW FRAME END must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ROWS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING)

query TRT
Expand Down Expand Up @@ -2340,10 +2340,10 @@ SELECT sum(price) OVER (ORDER BY ptime RANGE BETWEEN '-1 hours' PRECEDING AND '1
statement error invalid preceding or following size in window function
SELECT sum(price) OVER (ORDER BY ptime RANGE BETWEEN '1 hours' PRECEDING AND '-1 hours' FOLLOWING) FROM products

statement error incompatible window frame start type: decimal
statement error argument of WINDOW FRAME START must be type interval, not type decimal
SELECT sum(price) OVER (ORDER BY ptimestamp RANGE 123.4 PRECEDING) FROM products

statement error incompatible window frame start type: int
statement error argument of WINDOW FRAME START must be type interval, not type int
SELECT sum(price) OVER (ORDER BY ptimestamptz RANGE BETWEEN 123 PRECEDING AND CURRENT ROW) FROM products

statement error could not parse "1 days" as type decimal
Expand Down Expand Up @@ -2835,47 +2835,50 @@ Samsung {"Microsoft Lumia","HTC One",Nexus,iPhone,"HP Elite","Lenovo Th
statement error GROUPS offset cannot contain variables
SELECT avg(price) OVER (GROUPS group_id PRECEDING) FROM products

statement error GROUPS mode requires an ORDER BY clause
SELECT avg(price) OVER (GROUPS 1 PRECEDING) FROM products

statement error frame starting offset must not be null
SELECT avg(price) OVER (GROUPS NULL PRECEDING) FROM products
SELECT avg(price) OVER (ORDER BY group_id GROUPS NULL PRECEDING) FROM products

statement error frame starting offset must not be null
SELECT avg(price) OVER (GROUPS BETWEEN NULL PRECEDING AND 1 FOLLOWING) FROM products
SELECT avg(price) OVER (ORDER BY group_id GROUPS BETWEEN NULL PRECEDING AND 1 FOLLOWING) FROM products

statement error frame starting offset must not be negative
SELECT price, avg(price) OVER (PARTITION BY price GROUPS -1 PRECEDING) AS avg_price FROM products
SELECT price, avg(price) OVER (PARTITION BY price ORDER BY group_id GROUPS -1 PRECEDING) AS avg_price FROM products

statement error frame starting offset must not be negative
SELECT price, avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY price GROUPS -1 PRECEDING)
SELECT price, avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY price ORDER BY group_id GROUPS -1 PRECEDING)

statement error frame ending offset must not be null
SELECT avg(price) OVER (GROUPS BETWEEN 1 PRECEDING AND NULL FOLLOWING) FROM products
SELECT avg(price) OVER (ORDER BY group_id GROUPS BETWEEN 1 PRECEDING AND NULL FOLLOWING) FROM products

statement error frame ending offset must not be negative
SELECT price, avg(price) OVER (PARTITION BY price GROUPS BETWEEN 1 FOLLOWING AND -1 FOLLOWING) AS avg_price FROM products
SELECT price, avg(price) OVER (PARTITION BY price ORDER BY group_id GROUPS BETWEEN 1 FOLLOWING AND -1 FOLLOWING) AS avg_price FROM products

statement error frame ending offset must not be negative
SELECT price, avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY price GROUPS BETWEEN 1 FOLLOWING AND -1 FOLLOWING)
SELECT price, avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY price ORDER BY group_id GROUPS BETWEEN 1 FOLLOWING AND -1 FOLLOWING)

statement error frame ending offset must not be negative
SELECT product_name, price, min(price) OVER (PARTITION BY group_name GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS min_over_three, max(price) OVER (PARTITION BY group_name GROUPS BETWEEN UNBOUNDED PRECEDING AND -1 FOLLOWING) AS max_over_partition FROM products ORDER BY group_id
SELECT product_name, price, min(price) OVER (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS min_over_three, max(price) OVER (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN UNBOUNDED PRECEDING AND -1 FOLLOWING) AS max_over_partition FROM products ORDER BY group_id

statement error incompatible window frame start type: decimal
SELECT avg(price) OVER (PARTITION BY group_name GROUPS 1.5 PRECEDING) AS avg_price FROM products
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ORDER BY group_id GROUPS 1.5 PRECEDING) AS avg_price FROM products

statement error incompatible window frame start type: decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name GROUPS 1.5 PRECEDING)
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ORDER BY group_id GROUPS 1.5 PRECEDING)

statement error incompatible window frame start type: decimal
SELECT avg(price) OVER (PARTITION BY group_name GROUPS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING) AS avg_price FROM products
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING) AS avg_price FROM products

statement error incompatible window frame start type: decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name GROUPS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING)
statement error argument of WINDOW FRAME START must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN 1.5 PRECEDING AND UNBOUNDED FOLLOWING)

statement error incompatible window frame end type: decimal
SELECT avg(price) OVER (PARTITION BY group_name GROUPS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) AS avg_price FROM products
statement error argument of WINDOW FRAME END must be type int, not type decimal
SELECT avg(price) OVER (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING) AS avg_price FROM products

statement error incompatible window frame end type: decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name GROUPS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING)
statement error argument of WINDOW FRAME END must be type int, not type decimal
SELECT avg(price) OVER w AS avg_price FROM products WINDOW w AS (PARTITION BY group_name ORDER BY group_id GROUPS BETWEEN UNBOUNDED PRECEDING AND 1.5 FOLLOWING)

query RRRRR
SELECT price, sum(price) OVER (ORDER BY price GROUPS UNBOUNDED PRECEDING), sum(price) OVER (ORDER BY price GROUPS 100 PRECEDING), sum(price) OVER (ORDER BY price GROUPS 1 PRECEDING), sum(price) OVER (ORDER BY group_name GROUPS CURRENT ROW) FROM products ORDER BY price, group_id
Expand Down Expand Up @@ -2968,7 +2971,7 @@ Tablet Kindle Fire 150.00 350.00 586.36363636363636364
Tablet Samsung 200.00 450.00 586.36363636363636364

query TTRRR
SELECT group_name, product_name, price, avg(price) OVER (GROUPS BETWEEN 1 PRECEDING AND 2 PRECEDING), avg(price) OVER (ORDER BY price GROUPS BETWEEN CURRENT ROW AND CURRENT ROW) FROM products ORDER BY group_id
SELECT group_name, product_name, price, avg(price) OVER (ORDER BY group_id GROUPS BETWEEN 1 PRECEDING AND 2 PRECEDING), avg(price) OVER (ORDER BY price GROUPS BETWEEN CURRENT ROW AND CURRENT ROW) FROM products ORDER BY group_id
----
Smartphone Microsoft Lumia 200.00 NULL 200.00
Smartphone HTC One 400.00 NULL 400.00
Expand Down Expand Up @@ -3124,3 +3127,20 @@ FROM abc
3.5 3.5 3.5 3.5 10 10 10 10 25 25 25 25
3.5 3.5 3.5 3.5 10 10 10 10 25 25 25 25
3.5 3.5 3.5 3.5 10 10 10 10 25 25 25 25

query T
SELECT array_agg(a) OVER (w RANGE 1 PRECEDING) FROM x WINDOW w AS (ORDER BY a DESC) ORDER BY a
----
{2,1}
{3,2}
{3}

statement error GROUPS mode requires an ORDER BY clause
SELECT array_agg(a) OVER (w GROUPS 1 PRECEDING) FROM x WINDOW w AS (PARTITION BY a)

query T
SELECT array_agg(a) OVER (w GROUPS 1 PRECEDING) FROM x WINDOW w AS (PARTITION BY a ORDER BY a DESC) ORDER BY a
----
{1}
{2}
{3}
Loading

0 comments on commit b715f9f

Please sign in to comment.