-
Notifications
You must be signed in to change notification settings - Fork 14.4k
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
fix: Allow "EXPLAIN" queries when "Allow DML" setting is False #11348
Conversation
Codecov Report
@@ Coverage Diff @@
## master #11348 +/- ##
==========================================
- Coverage 65.75% 61.08% -4.68%
==========================================
Files 838 838
Lines 39714 39714
Branches 3613 3613
==========================================
- Hits 26115 24260 -1855
- Misses 13498 15273 +1775
- Partials 101 181 +80
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
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.
Please format your PR title to match: ^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|other)((.+))?:\s.+
!
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.
Please format your PR title to match: ^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|other)((.+))?:\s.+
!
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.
Please format your PR title to match: ^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|other)((.+))?:\s.+
!
superset/sql_parse.py
Outdated
@@ -111,7 +111,11 @@ def is_select(self) -> bool: | |||
return self._parsed[0].get_type() == "SELECT" | |||
|
|||
def is_explain(self) -> bool: | |||
return self.stripped().upper().startswith("EXPLAIN") | |||
# Parsing SQL statement for EXPLAIN and filtering out comments |
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.
Thinking about whether the right logic here is first()
, any()
or all()
and I think it's either
-
- it works only if the SQL is a single statement, and raises otherwise
-
- all of the statements are
EXPLAIN
(which is not typical)
- all of the statements are
superset/sql_parse.py
Outdated
if statements_without_comments[0].startswith("EXPLAIN"): | ||
return True | ||
|
||
return False |
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.
You can simplify this:
return statements_without_comments[0].startswith("EXPLAIN")
superset/sql_parse.py
Outdated
statement.strip(" \t\n;") | ||
for statement in self.stripped().upper().splitlines() | ||
if not statement.startswith("--") | ||
] |
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 will miss some edge cases like:
-- This is a comment
-- this is another comment but with a space in the front
EXPLAIN SELECT * FROM TABLE
You need to lstrip()
each line as well before testing if it startswith()
:
statements_without_comments = [
statement.strip(" \t\n;")
for statement in self.stripped().upper().splitlines()
if not statement.lstrip().startswith("--")
]
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 find it simpler to just use regular expression:
queries = re.sub(r'\s*--.*', '', queries)
queries = [x.strip(' \t\n\r') for x in queries.split(';')]
queries = [x for x in queries if x] # query must be non-empty
superset/sql_parse.py
Outdated
if statement.upper().startswith("EXPLAIN"): | ||
return True | ||
# Remove comments | ||
statements_without_comments = [statement.strip(" \t\n;") for statement in self.stripped().upper().splitlines() if not statement.startswith("--")] |
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.
sqlparse.format
offers a strip_comments
option that will also take care of /*this*/
and probably more.
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
…e#11348) Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
SUMMARY
Fixing
is_explain
function in sql_parse to properly catch EXPLAIN statements. sqlparse out of the box doesn't handle comments well, so we have to parse the query ourselves.Closes #8827
Before
After
TEST PLAN
Goto Sqllab
Run the following query:
ADDITIONAL INFORMATION