Add support for generated virtual columns with expression#1051
Add support for generated virtual columns with expression#1051alamb merged 6 commits intoapache:mainfrom
Conversation
|
LGTM. |
|
There's one test covering the same But I can add this for SQLite & MySQL too. 👍 If SQLite & MySQL have the same syntax for this, do you prefer me to copy & paste the test into their respective modules, or set up one test to run with both of them? I'll copy-paste for now. |
Pull Request Test Coverage Report for Build 6961152498Warning: This coverage report may be inaccurate.We've detected an issue with your CI configuration that might affect the accuracy of this pull request's coverage report.
💛 - Coveralls |
alamb
left a comment
There was a problem hiding this comment.
Thank you for this contribution @takluyver (and the review @tobyhede ). I left some comments -- let me know what you think
|
|
||
| fn sqlite_and_generic() -> TestedDialects { | ||
| TestedDialects { | ||
| // we don't have a separate SQLite dialect, so test only the generic dialect for now |
| #[test] | ||
| fn parse_create_table_gencol() { | ||
| let sql_default = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2))"; | ||
| let sql_virt = "CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a * 2) VIRTUAL)"; |
There was a problem hiding this comment.
What do you think about adding additional support to the AST so you can recover the original SQL --- as implemented now this change will not permit people to know when the original query had VIRTUAL or not
There was a problem hiding this comment.
Virtual is the default, so adding the marker doesn't make a logical difference (at least in the databases I found that support this). Elsewhere in the tests, it looks like you don't preserve differences like this - e.g. SHOW COLUMNS vs SHOW FIELDS in the MySQL tests. But if you'd like to preserve this one, I'm happy to do that. 🙂
If so, I would probably introduce an enum called something like GenExpressionQualifier (though that's an ugly name...), which could be None, Virtual or Stored. The Stored option would then be redundant with GeneratedAs::ExpStored.
(For my next PR, I'm planning to make the GENERATED ALWAYS keywords optional - as they are in MySQL and SQLite. Let me know if you want the presence or absence of those to be preserved too.)
There was a problem hiding this comment.
Elsewhere in the tests, it looks like you don't preserve differences like this - e.g. SHOW COLUMNS vs SHOW FIELDS in the MySQL tests. But if you'd like to preserve this one, I'm happy to do that. 🙂
Yes, it is true that this crate is not always consistent. However, for newly added code let's try and preserve the ability to round trip the AST (though I see there is no note describing that detail on https://github.com/sqlparser-rs/sqlparser-rs -- I will try and add a note when I have time)
Let me know if you want the presence or absence of those to be preserved too.)
yes, please
There was a problem hiding this comment.
OK, the latest commit (6d69a43) preserves the distinction between VIRTUAL, STORED and no qualifier. As I mentioned, that does mean there are two fields which both record if STORED was used. That's not so tidy, but it preserves compatibility for any code that's checking for GeneratedAs::ExpStored.
I've called the new field & enum generation_expr_mode & GeneratedExpressionMode, which are both quite a mouthful. Let me know if you have a better name for this. 🙂
alamb
left a comment
There was a problem hiding this comment.
Thank you @takluyver -- looks good to me
| #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] | ||
| #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | ||
| #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] | ||
| pub enum GeneratedExpressionMode { |
There was a problem hiding this comment.
👍 looks good to me -- I don't have a better name for this
|
Ooops, I left some debugging bits in the tests. I've removed them now - do you prefer me to squash that into the previous commit and force-push the branch? |
On merge all the commits will be squashed into a single commit, so I would prefer that you just push new commits to your branch / PR as it makes reviewing the deltas easier |
|
Thanks again @takluyver |
This allows the SQLite & MySQL syntax for generated virtual columns, addressing the second part of #1050.
I've done a partial survey of what different databases support for generated columns:
GENERATED ASsyntax, but it doesn't seem to overlap with the other DBs above at all - it's something to do with versioning records, with no space for arbitrary expressions - docs. I haven't tried to cover this in this PR.It looks like the generated-column code before this PR is based on Postgres.
I've expanded the meaning of
GeneratedAs::ExpStored, which the docs previously described as Postgres specific, to any column generated from an expressions and stored.GeneratedAs::Alwayswithgeneration_exprpresent now represents a VIRTUAL column in SQLite or MySQL. It might be neater to make stored/virtual separate from always/by-default, but that would be an API break.