From 48a61bacc581b1e585453f8181af9d76ef557e86 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 21 Sep 2021 16:23:54 -0700 Subject: [PATCH] fix: handle CTEs with comments on is_select (#16769) --- superset/sql_parse.py | 10 +++++-- tests/unit_tests/sql_parse_tests.py | 46 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 tests/unit_tests/sql_parse_tests.py diff --git a/superset/sql_parse.py b/superset/sql_parse.py index a5394c15c3..8b173d9b82 100644 --- a/superset/sql_parse.py +++ b/superset/sql_parse.py @@ -131,13 +131,17 @@ class ParsedQuery: return self._limit def is_select(self) -> bool: - return self._parsed[0].get_type() == "SELECT" + # make sure we strip comments; prevents a bug with coments in the CTE + parsed = sqlparse.parse(self.strip_comments()) + return parsed[0].get_type() == "SELECT" def is_valid_ctas(self) -> bool: - return self._parsed[-1].get_type() == "SELECT" + parsed = sqlparse.parse(self.strip_comments()) + return parsed[-1].get_type() == "SELECT" def is_valid_cvas(self) -> bool: - return len(self._parsed) == 1 and self._parsed[0].get_type() == "SELECT" + parsed = sqlparse.parse(self.strip_comments()) + return len(parsed) == 1 and parsed[0].get_type() == "SELECT" def is_explain(self) -> bool: # Remove comments diff --git a/tests/unit_tests/sql_parse_tests.py b/tests/unit_tests/sql_parse_tests.py new file mode 100644 index 0000000000..a6e41e131c --- /dev/null +++ b/tests/unit_tests/sql_parse_tests.py @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from superset.sql_parse import ParsedQuery + + +def test_cte_with_comments(): + sql = ParsedQuery( + """WITH blah AS + (SELECT * FROM core_dev.manager_team), + +blah2 AS + (SELECT * FROM core_dev.manager_workspace) + +SELECT * FROM blah +INNER JOIN blah2 ON blah2.team_id = blah.team_id""" + ) + assert sql.is_select() + + sql = ParsedQuery( + """WITH blah AS +/*blahblahbalh*/ + (SELECT * FROM core_dev.manager_team), +--blahblahbalh + +blah2 AS + (SELECT * FROM core_dev.manager_workspace) + +SELECT * FROM blah +INNER JOIN blah2 ON blah2.team_id = blah.team_id""" + ) + assert sql.is_select()