Skip to content

Commit

Permalink
解决clickhouse表名大小写敏感问题 (#2637)
Browse files Browse the repository at this point in the history
* 解决clickhouse表名大小写敏感问题

解决clickhouse表名大小写敏感问题

* 单元测试
  • Loading branch information
nick2wang authored May 10, 2024
1 parent b61bdf0 commit f81fb45
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
30 changes: 18 additions & 12 deletions sql/engines/clickhouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def execute_check(self, db_name=None, sql=""):
for statement in sql_list:
statement = statement.rstrip(";")
# 禁用语句
if re.match(r"^select|^show", statement.lower()):
if re.match(r"^select|^show", statement, re.M | re.IGNORECASE):
result = ReviewResult(
id=line,
errlevel=2,
Expand All @@ -273,11 +273,13 @@ def execute_check(self, db_name=None, sql=""):
sql=statement,
)
# alter语句
elif re.match(r"^alter", statement.lower()):
elif re.match(r"^alter", statement, re.M | re.IGNORECASE):
# alter table语句
if re.match(r"^alter\s+table\s+(.+?)\s+", statement.lower()):
if re.match(
r"^alter\s+table\s+(.+?)\s+", statement, re.M | re.IGNORECASE
):
table_name = re.match(
r"^alter\s+table\s+(.+?)\s+", statement.lower(), re.M
r"^alter\s+table\s+(.+?)\s+", statement, re.M | re.IGNORECASE
).group(1)
if "." not in table_name:
table_name = f"{db_name}.{table_name}"
Expand All @@ -298,7 +300,8 @@ def execute_check(self, db_name=None, sql=""):
# delete与update语句,实际是alter语句的变种
if re.match(
r"^alter\s+table\s+(.+?)\s+(delete|update)\s+",
statement.lower(),
statement,
re.M | re.IGNORECASE,
):
if not table_engine.endswith("MergeTree"):
result = ReviewResult(
Expand Down Expand Up @@ -328,16 +331,18 @@ def execute_check(self, db_name=None, sql=""):
else:
result = self.explain_check(check_result, db_name, line, statement)
# truncate语句
elif re.match(r"^truncate\s+table\s+(.+?)(\s|$)", statement.lower()):
elif re.match(
r"^truncate\s+table\s+(.+?)(\s|$)", statement, re.M | re.IGNORECASE
):
table_name = re.match(
r"^truncate\s+table\s+(.+?)(\s|$)", statement.lower(), re.M
r"^truncate\s+table\s+(.+?)(\s|$)", statement, re.M | re.IGNORECASE
).group(1)
if "." not in table_name:
table_name = f"{db_name}.{table_name}"
table_engine = self.get_table_engine(table_name)["engine"]
table_exist = self.get_table_engine(table_name)["status"]
if table_exist == 1:
if table_engine in ("View", "File,", "URL", "Buffer", "Null"):
if table_engine in ("View", "File", "URL", "Buffer", "Null"):
result = ReviewResult(
id=line,
errlevel=2,
Expand All @@ -358,15 +363,16 @@ def execute_check(self, db_name=None, sql=""):
sql=statement,
)
# insert语句,explain无法正确判断,暂时只做表存在性检查与简单关键字匹配
elif re.match(r"^insert", statement.lower()):
elif re.match(r"^insert", statement, re.M | re.IGNORECASE):
if re.match(
r"^insert\s+into\s+([a-zA-Z_][0-9a-zA-Z_.]+)([\w\W]*?)(values|format|select)(\s+|\()",
statement.lower(),
statement,
re.M | re.IGNORECASE,
):
table_name = re.match(
r"^insert\s+into\s+([a-zA-Z_][0-9a-zA-Z_.]+)([\w\W]*?)(values|format|select)(\s+|\()",
statement.lower(),
re.M,
statement,
re.M | re.IGNORECASE,
).group(1)
if "." not in table_name:
table_name = f"{db_name}.{table_name}"
Expand Down
32 changes: 31 additions & 1 deletion sql/engines/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2106,13 +2106,43 @@ def test_execute_check_alter_sql(self, mock_query):
mock_query.return_value = result
new_engine = ClickHouseEngine(instance=self.ins1)
table_engine = new_engine.get_table_engine(table_name)
alter_sql = "alter table default.tb_test add column remark String"
alter_sql = "alter table tb_test add column remark String"
check_result = new_engine.execute_check(db_name="some_db", sql=alter_sql)
self.assertEqual(
check_result.rows[0].errormessage,
"ALTER TABLE仅支持*MergeTree,Merge以及Distributed等引擎表!",
)

@patch.object(ClickHouseEngine, "query")
def test_execute_check_truncate_sql(self, mock_query):
table_name = "default.tb_test"
result = ResultSet()
result.rows = [("File",)]
mock_query.return_value = result
new_engine = ClickHouseEngine(instance=self.ins1)
table_engine = new_engine.get_table_engine(table_name)
alter_sql = "truncate table tb_test"
check_result = new_engine.execute_check(db_name="some_db", sql=alter_sql)
self.assertEqual(
check_result.rows[0].errormessage,
"TRUNCATE不支持View,File,URL,Buffer和Null表引擎!",
)

@patch.object(ClickHouseEngine, "query")
def test_execute_check_insert_sql(self, mock_query):
table_name = "default.tb_test"
result = ResultSet()
result.rows = [("Log",)]
mock_query.return_value = result
new_engine = ClickHouseEngine(instance=self.ins1)
table_engine = new_engine.get_table_engine(table_name)
alter_sql = "insert into tb_test(name) values('nick');"
check_result = new_engine.execute_check(db_name="some_db", sql=alter_sql)
self.assertEqual(
check_result.rows[0].errlevel,
0,
)

def test_filter_sql_with_delimiter(self):
new_engine = ClickHouseEngine(instance=self.ins1)
sql_without_limit = "select user from usertable;"
Expand Down

0 comments on commit f81fb45

Please sign in to comment.