-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
feat: Capture expression name part delimiters #2001
feat: Capture expression name part delimiters #2001
Conversation
|
||
import java.util.List; | ||
|
||
public class ObjectNames { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is only used by the parser - it's the return value of the RelObjectNames
production. I wasn't sure where to put it, as I don't think there are any other similar examples. Is it OK here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put it into the parser grammar then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK I'll add it as a static class in the parser
} { | ||
token = RelObjectNameExt() { data.add(token); } | ||
( LOOKAHEAD (2) ("." | ":") ("." { data.add(null); })* token = RelObjectNameExt2() { data.add(token); } ) * | ||
( | ||
LOOKAHEAD (2) ( delimiter = "." | delimiter = ":" ) { delimiters.add(delimiter.image); } ( delimiter = "." { data.add(null); delimiters.add(delimiter.image); })* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add the colon to the optional part here as well, but it wasn't there before I made the change (("." { data.add(null); })*
), so just wanted to double check that's OK? If it's OK, the line will read
LOOKAHEAD (2) ( delimiter = "." | delimiter = ":" ) { delimiters.add(delimiter.image); } ((delimiter = "." | delimiter = ":") { data.add(null); delimiters.add(delimiter.image); })*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks consistent to me, I would do the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
4db1a41
to
8d57096
Compare
Thank you for your contribution and interest in JSQLParser. |
I am sorry, I am old school and lost on JSON: In my understanding, this should not be even parsed as a Colum, but as a
At the same time a |
Honestly, this is a tough one:
What's the way forward? Do we want to take the "hack" right now, document it with a lot |
Idea! Why don't we parse What do you think? |
Hi @manticore-projects, thanks for the speedy responses! 😁
Not sure I understand sorry - what would the key be and what would the value be? Note that the bit of the expression that references the json can be any length e.g.
The problem is, we can't actually know if it's a Json expression or not just by looking at the colon, because I think certain databases (e.g. informix? - the one in #1134) use colons for all delimiters - like normal column expressions. So how would we know to parse it into a JsonColumn or a normal Column?
Not sure I understand sorry 🤔 so we'd have a new field on |
I guess it is me, who does not understand it correctly. I came from the perspective that Map entries like
Very strong argument, I totally get your point. I think we can just go with your improvements and see what will happen. |
No problem at all, sorry, I probably should have given some example json to illustrate it...
So say for example you load some json into the // row 1
{
"rocket": {
"engine": {
"power": "loads of power"
}
}
}
// row 2
{
"rocket": {
"engine": {
"power": "even more power"
}
}
} If you execute SELECT mycolumn:rocket.engine.power AS rocket_power FROM mytable; It'll return 2 rows like:
|
Thank you very much for the explanation, very helpful. I have been too stuck in my current maps and key/value pairs. I think you implementation is good and fixes the problem. Thank you again for your contribution and time, well done! |
No worries at all 😁
Yeah exactly - on Snowflake, the bit after the colon is similar to a jsonpath expression 👍
OK great! I've got to head off now but will sort it out first thing tomorrow. Thanks again for your lightning fast review! 😁 |
Good job @mountaincrab and I would merge immediately when the Q/A test ran though. |
Thanks again for the review @manticore-projects 👍 |
Context
A lot of databases (e.g. Snowflake, Databricks, Redshift) support querying nested data. For example, a query like this
on Snowflake:
queries the
json_data
column of themytable
table, extracting therocket_name
field from the JSON data thatexists in the column. Note the colon used between
json_data
androcket_name
.We would like to know if a column expression is referring to nested data or not. Examining the delimiters (e.g.
.
,:
) can help determine this.Problem
Currently, statements like the above (which contain colons as delimiters) can be parsed (as of #1134). However, the delimiters are not captured, which means they're not available in any of the model objects like
Column
andTable
. It also means if you parse:and then deparse it, you get:
Solution
This PR introduces a change to the grammar so that the delimiters are captured. Furthermore, the model classes have been
updated:
Column
: newtableDelimiter
field - the delimiter used to delimit the column name from the table nameTable
: newdelimiterParts
field - the delimiters used to delimit each table name part