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

[RFC] SQL Type Annotations #6895

Conversation

nvanbenschoten
Copy link
Member

@nvanbenschoten nvanbenschoten commented May 25, 2016

[ci skip]


This change is Reviewable

@nvanbenschoten nvanbenschoten force-pushed the nvanbenschoten/typeAssertRFC branch 2 times, most recently from 5d6c570 to 80479e9 Compare May 25, 2016 18:39
@bdarnell
Copy link
Contributor

Review status: 0 of 1 files reviewed at latest revision, 4 unresolved discussions, all commit checks successful.


docs/RFCS/type_annotations.md, line 222 [r1] (raw file):

portability of SQL statements and create a higher learning curve for
moving to Cockroach. However, we concluded that this was ok, because 
these annotations are fully op-in, and are not a requirement of the 

s/op/opt/


docs/RFCS/type_annotations.md, line 240 [r1] (raw file):

`E : T`
- [+] has parallels to Postgres' cast extension `E :: T`
- [-] may look too similar to Postgres' cast extension

: is also used for placeholders in oracle.


docs/RFCS/type_annotations.md, line 250 [r1] (raw file):

- [+] a mix between the previous two proposals
- [+] unconventional (wont be mistaken)
- [-] unconventional (stands out)

May also be confused with unary !, which means logical negation in many languages including mysql, and factorial in postgresql. Postgres even has a unary !! (which also means factorial - single ! is a postfix operator; !! is prefix).


docs/RFCS/type_annotations.md, line 261 [r1] (raw file):

desired that we adopt a more standard keyword style syntax.

For instance: `ANNOTATE(E AS T)` or `(E ANNOTATE AS T)`.

It's also worth considering something that looks like a plain function: ANNOTATE(E, T). This is easier to plumb through interfaces like SQLAlchemy's query builder (which has a special case for CAST, but it's difficult to add other things with similar treatment. For that matter, it's also difficult to use non-standard operators). There is some precedent for using a type as an ordinary function parameter in mysql's CONVERT(E, T) function, although I'm not sure how happy our grammar would be with that.

My preference is for the plain function syntax because that's going to be easiest to pass through client layers. I'd rather not introduce multiple syntaxes for type annotations unless they turn out to be common enough to warrant a short operator form.


Comments from Reviewable

`...::...`) is not appropriate for this, because although it
guarantees a type to the surrounding expression it does not constrain
its argument. For example `sign(1.2)::int` does not disambiguate which
overload of `sign` to use.
Copy link
Member

Choose a reason for hiding this comment

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

is sign($1::int) valid, and would it do what you want here?

@RaduBerinde
Copy link
Member

This sounds great to me. I especially like that it can be used to force a placeholder to have a certain type - with the power of that and casts, one should always be able to get around any deficiency in the typing system.

I like the "x : type" syntax, and I agree that just like :: has a more explicit CAST(.. AS ..) syntax this should also have an explicit alias, e.g. SETTYPE(... , ...)

Previously, nvanbenschoten (Nathan VanBenschoten) wrote…

[RFC] SQL Type Annotations

[ci skip]


Review status: 0 of 1 files reviewed at latest revision, 6 unresolved discussions, all commit checks successful.


docs/RFCS/type_annotations.md, line 114 [r1] (raw file):

        -> no preference for the return type of `1.2`
        -> `1.2` defaults to a DECIMAL
        -> overload resolution choses the DECIMAL implementation

chooses (and two more below)


docs/RFCS/type_annotations.md, line 261 [r1] (raw file):

Previously, bdarnell (Ben Darnell) wrote…

It's also worth considering something that looks like a plain function: ANNOTATE(E, T). This is easier to plumb through interfaces like SQLAlchemy's query builder (which has a special case for CAST, but it's difficult to add other things with similar treatment. For that matter, it's also difficult to use non-standard operators). There is some precedent for using a type as an ordinary function parameter in mysql's CONVERT(E, T) function, although I'm not sure how happy our grammar would be with that.

My preference is for the plain function syntax because that's going to be easiest to pass through client layers. I'd rather not introduce multiple syntaxes for type annotations unless they turn out to be common enough to warrant a short operator form.

I like the function-style syntax. But `ANNOTATE` is pretty obtuse, how about `SETTYPE(E, T)` or `SET_TYPE()` or `WITH_TYPE()`

Comments from Reviewable

@knz
Copy link
Contributor

knz commented May 31, 2016

Reviewed 1 of 1 files at r1.
Review status: all files reviewed at latest revision, 7 unresolved discussions, all commit checks successful.


docs/RFCS/type_annotations.md, line 27 [r1] (raw file):

Previously, tschottdorf (Tobias Schottdorf) wrote…

is sign($1::int) valid, and would it do what you want here?

Yes in that particular case there is a way to solve the problem. Perhaps the more general statement would be "in the case where there are multiple overloads of a function all with the same return type, a cast on the return type has no effect on overload resolution". Or something to that effect.

docs/RFCS/type_annotations.md, line 156 [r1] (raw file):

The initial Summer RFC defined a set of rules for determining the type of
placeholders based on type casts and type annotations. These rules were:

Perhaps put this in present tense (or say "the proposed rules are")


docs/RFCS/type_annotations.md, line 261 [r1] (raw file):

Previously, RaduBerinde wrote…

I like the function-style syntax. But ANNOTATE is pretty obtuse, how about SETTYPE(E, T) or SET_TYPE() or WITH_TYPE()

+1 on a function-like syntax. I don't like "set type" much though. "with_type" is ok, also consider "typed_as(E, T)", perhaps even "typed(E, T)" .

Btw I think we should have both a function like syntax and also an operator for conciseness in docs. I still like the single ":" best, visual ambiguity with "::" notwithstanding (and actually the closeness with "::" might be an advantage).


Comments from Reviewable

@nvanbenschoten
Copy link
Member Author

Review status: 0 of 1 files reviewed at latest revision, 7 unresolved discussions, some commit checks pending.


docs/RFCS/type_annotations.md, line 114 [r1] (raw file):

Previously, RaduBerinde wrote…

chooses (and two more below)

Done.

docs/RFCS/type_annotations.md, line 156 [r1] (raw file):

Previously, knz (kena) wrote…

Perhaps put this in present tense (or say "the proposed rules are")

Done.

docs/RFCS/type_annotations.md, line 222 [r1] (raw file):

Previously, bdarnell (Ben Darnell) wrote…

s/op/opt/

Done.

docs/RFCS/type_annotations.md, line 240 [r1] (raw file):

Previously, bdarnell (Ben Darnell) wrote…

: is also used for placeholders in oracle.

Done.

docs/RFCS/type_annotations.md, line 250 [r1] (raw file):

Previously, bdarnell (Ben Darnell) wrote…

May also be confused with unary !, which means logical negation in many languages including mysql, and factorial in postgresql. Postgres even has a unary !! (which also means factorial - single ! is a postfix operator; !! is prefix).

Good point, noted in the cons lists.

docs/RFCS/type_annotations.md, line 261 [r1] (raw file):

Previously, knz (kena) wrote…

+1 on a function-like syntax. I don't like "set type" much though. "with_type" is ok, also consider "typed_as(E, T)", perhaps even "typed(E, T)" .

Btw I think we should have both a function like syntax and also an operator for conciseness in docs. I still like the single ":" best, visual ambiguity with "::" notwithstanding (and actually the closeness with "::" might be an advantage).

Syntax that looks like a function is a good idea. With regards to interfaces like SQLAlchemy's query builder, is it possible to provide a type name as an argument? If not, we may need to accept strings for the `T` arg instead/as well.

I think I like WITH_TYPE(E, T) the best out of all of the proposed names. I also agree with @knz's proposal to have a function like syntax and an operator for conciseness. I'd rather not mix the logical concepts of what function's role is is vs. what an operator's role is, and if we only have a function, I think it might cause some confusion. If we follow this route, the name of the function should probably be somewhat consistent with what we call the operator. Because of this, either TYPE_ANNOTATE or ANNOTATE_TYPE might also be good choices for the function name.

On a side note @bdarnell, you mentioned that "it's also difficult to use non-standard operators". Does SQLAlchemy expose floor division? I would assume it needs some way to access MySQL's DIV operator. If so, I'll look into how we can customize our plugin to work with our new // operator.


Comments from Reviewable

@bdarnell
Copy link
Contributor

Review status: 0 of 1 files reviewed at latest revision, 7 unresolved discussions, all commit checks successful.


docs/RFCS/type_annotations.md, line 261 [r1] (raw file):

Previously, nvanbenschoten (Nathan VanBenschoten) wrote…

Syntax that looks like a function is a good idea. With regards to interfaces like SQLAlchemy's query builder, is it possible to provide a type name as an argument? If not, we may need to accept strings for the T arg instead/as well.

I think I like WITH_TYPE(E, T) the best out of all of the proposed names. I also agree with @knz's proposal to have a function like syntax and an operator for conciseness. I'd rather not mix the logical concepts of what function's role is is vs. what an operator's role is, and if we only have a function, I think it might cause some confusion. If we follow this route, the name of the function should probably be somewhat consistent with what we call the operator. Because of this, either TYPE_ANNOTATE or ANNOTATE_TYPE might also be good choices for the function name.

On a side note @bdarnell, you mentioned that "it's also difficult to use non-standard operators". Does SQLAlchemy expose floor division? I would assume it needs some way to access MySQL's DIV operator. If so, I'll look into how we can customize our plugin to work with our new // operator.

I don't think sqlalchemy makes it easy to provide a type name as an argument, although I haven't explored this in detail. It does provide the ability to pass unquoted strings (by wrapping them in its `literal()` function) , so that's available as a last resort.

I was wrong about custom operators - there is a method for this. The syntax is ugly, though (x.op('//')(y) for floor division), so function-style syntax is still preferable to custom operators. For floor division, since Python happens to have // as well, it would be possible to hook up the python operator to our // and mysql's DIV, but this would require changes to sqlalchemy proper; it's not something a plugin can do as far as I can tell.


Comments from Reviewable

@nvanbenschoten
Copy link
Member Author

I'm still working on a shorthand syntax for this functionality, because : collides with array slicing. One other idea was Expr @: Type. This is kind of a crazy syntax, but would be a somewhat natural fit for the name "type annotation". Any opinions?

For now though, I'm going to try to move along the first iteration of the type annotation code through without an accompanying shorthand notation. See #7083.

@nvanbenschoten
Copy link
Member Author

@knz Updated the RFC to include the operator syntax implemented in #9086.

@knz
Copy link
Contributor

knz commented Sep 5, 2016

LGTM

Any work remaining to be done before we can merge this one?

@nvanbenschoten nvanbenschoten changed the base branch from master to develop September 5, 2016 19:16
@nvanbenschoten nvanbenschoten changed the base branch from develop to master September 5, 2016 19:17
@nvanbenschoten nvanbenschoten changed the base branch from master to develop September 5, 2016 20:24
@nvanbenschoten nvanbenschoten changed the base branch from develop to master September 5, 2016 20:25
@nvanbenschoten
Copy link
Member Author

I think it's ready to merge!

@nvanbenschoten nvanbenschoten merged commit 5586670 into cockroachdb:master Sep 5, 2016
@nvanbenschoten nvanbenschoten deleted the nvanbenschoten/typeAssertRFC branch September 5, 2016 20:25
pav-kv pushed a commit to pav-kv/cockroach that referenced this pull request Mar 5, 2024
The "logs converge" case in TestLeaderElectionPreVote was incorrectly
passing because some nodes were not actually using the preVoteConfig.
This test case was more complex than its siblings and it was not
verifying what it wanted to verify, so pull it out into a separate test
where everything can be tested more explicitly.

Fixes cockroachdb#6895
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants