Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlsmith: add window frames #36896

Merged
merged 1 commit into from
Apr 17, 2019
Merged

Conversation

yuzefovich
Copy link
Member

Adds window frames to window functions. RANGE mode of framing is not
supported with offset-type bounds.

Release note: None

@yuzefovich yuzefovich requested review from maddyblue and a team April 17, 2019 00:51
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@yuzefovich
Copy link
Member Author

I wasn't sure whether we want to generate frames that would result in an error (for example, rank() OVER (ROWS UNBOUNDED FOLLOWING) is "illegal" and will result in an error at the parsing stage). There are logic tests for all such cases, so I didn't want to spend execution time on these.

Copy link
Contributor

@maddyblue maddyblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! I had no idea it was this complicated. I thought (because obviously I haven't ever done it) that you just passed two expressions. Who knew it was this deep?

func makeWindowFrame() *tree.WindowFrame {
// Window frame mode and start bound must always be present whereas end
// bound can be omitted.
frameMode := tree.WindowFrameMode(rand.Intn(3))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the pattern similar to randDirection for this. You'll have to pass this func a s *scope argument. I guess BoundType is fine because of how you need to do the slicing for endBounds.

@@ -373,6 +379,76 @@ func makeFunc(s *scope, ctx Context, typ types.T, refs colRefs) (tree.TypedExpr,
), typ), true
}

const maxWindowFrameOffset = 10

func makeWindowFrame() *tree.WindowFrame {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass a s *scope here and use s.schema.rnd.Intn instead of the rand.Intn uses.

// We will set offsets regardless of the bound type, but they will only be
// used when a bound is either OffsetPreceding or OffsetFollowing. Both
// ROWS and GROUPS mode need non-negative integers as bounds.
startBound.OffsetExpr = tree.NewDInt(tree.DInt(rand.Intn(maxWindowFrameOffset)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is where sqlsmith gets cool. Instead of hard coding an integer, use makeScalar(s, types.Int, refs), and take a refs colRefs argument to this func. It'll produce some funky thing that spits out on int based on the currently available column names, or make some constants.

@maddyblue
Copy link
Contributor

And to answer your question: if it's not too much work I try to make sqlsmith smart so that it doesn't get caught at errors like "you can't do blergh because you are using feezbop", because we want it to get beyond that step and actually execute. However that's hard to do in all cases, so it's fine to leave frames that generate known errors for now. We can clean them up later. I go through from time to time and address those.

Adds window frames to window functions. RANGE mode of framing is not
supported with offset-type bounds.

Release note: None
Copy link
Member Author

@yuzefovich yuzefovich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that was my thinking as well. I think you might've misunderstood what I meant: this PR is setting up the frames in a such way that would not produce any parsing-time errors, so my question was whether such setup was desirable (I thought it was, and you confirmed it).

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @mjibson)


pkg/internal/sqlsmith/scalar.go, line 384 at r1 (raw file):

Previously, mjibson (Matt Jibson) wrote…

pass a s *scope here and use s.schema.rnd.Intn instead of the rand.Intn uses.

Done.


pkg/internal/sqlsmith/scalar.go, line 387 at r1 (raw file):

Previously, mjibson (Matt Jibson) wrote…

Use the pattern similar to randDirection for this. You'll have to pass this func a s *scope argument. I guess BoundType is fine because of how you need to do the slicing for endBounds.

Done. Yeah, we need to be more careful with bounds in order to not produce frames that will result in a parsing-time error.


pkg/internal/sqlsmith/scalar.go, line 438 at r1 (raw file):

Previously, mjibson (Matt Jibson) wrote…

So this is where sqlsmith gets cool. Instead of hard coding an integer, use makeScalar(s, types.Int, refs), and take a refs colRefs argument to this func. It'll produce some funky thing that spits out on int based on the currently available column names, or make some constants.

Done.

However I wonder if we can restrict the types of scalar expressions produced there. That OffsetExpr "must be an integer expression not containing any variables, aggregate functions, or window functions. The value must not be null or negative," and to the best of my understanding we need a non-negative non-null integer constant there.

Copy link
Contributor

@maddyblue maddyblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @mjibson and @yuzefovich)


pkg/internal/sqlsmith/scalar.go, line 438 at r1 (raw file):

Previously, yuzefovich wrote…

Done.

However I wonder if we can restrict the types of scalar expressions produced there. That OffsetExpr "must be an integer expression not containing any variables, aggregate functions, or window functions. The value must not be null or negative," and to the best of my understanding we need a non-negative non-null integer constant there.

Interesting. I looked over the code but didn't immediately see those requirements. Let's merge this as is and if it produces too many errors we can make it smarter.

@yuzefovich
Copy link
Member Author

Interesting. I looked over the code but didn't immediately see those requirements. Let's merge this as is and if it produces too many errors we can make it smarter.

I copied that quote in my previous response from Postgres docs since I was trying to emulate their behavior, and here is where the offsets are checked https://github.com/cockroachdb/cockroach/blob/master/pkg/sql/sem/tree/type_check.go#L923.

But I also agree that we can merge it as is and tweak it later if necessary, so thanks for the review!

bors r+

craig bot pushed a commit that referenced this pull request Apr 17, 2019
36896: sqlsmith: add window frames r=yuzefovich a=yuzefovich

Adds window frames to window functions. RANGE mode of framing is not
supported with offset-type bounds.

Release note: None

Co-authored-by: Yahor Yuzefovich <[email protected]>
@craig
Copy link
Contributor

craig bot commented Apr 17, 2019

Build succeeded

@craig craig bot merged commit fe7c5a0 into cockroachdb:master Apr 17, 2019
@yuzefovich yuzefovich deleted the smith_frame branch April 28, 2019 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants