diff --git a/sql/engines/odps.py b/sql/engines/odps.py index 4c0e0c6de0..b1c20d7138 100644 --- a/sql/engines/odps.py +++ b/sql/engines/odps.py @@ -2,9 +2,10 @@ import re import logging +import sqlparse from . import EngineBase -from .models import ResultSet, ReviewSet, ReviewResult +from .models import ResultSet from odps import ODPS @@ -37,16 +38,24 @@ def info(self): def get_all_databases(self): """获取数据库列表, 返回一个ResultSet - ODPS只有project概念, 直接返回project名称 + ODPS只有project概念, 直接返回project名称 + TODO: 目前ODPS获取所有项目接口比较慢, 暂时支持返回一个project,后续再优化 """ result = ResultSet() try: - conn = self.get_connection(self.get_connection()) + conn = self.get_connection() + + # 判断project是否存在 + db_exist = conn.exist_project(self.instance.db_name) + + if db_exist is False: + raise ValueError(f"[{self.instance.db_name}]项目不存在") + result.rows = [conn.project] except Exception as e: logger.warning(f"ODPS执行异常, {e}") - result.rows = [self.instance.db_name] + result.error = str(e) return result def get_all_tables(self, db_name, **kwargs): @@ -126,3 +135,27 @@ def query(self, db_name=None, sql='', limit_num=0, close_conn=True, **kwargs): result_set.error = str(e) return result_set + def query_check(self, db_name=None, sql=''): + # 查询语句的检查、注释去除、切分 + result = {'msg': '', 'bad_query': False, 'filtered_sql': sql, 'has_star': False} + keyword_warning = '' + sql_whitelist = ['select'] + # 根据白名单list拼接pattern语句 + whitelist_pattern = re.compile("^" + "|^".join(sql_whitelist), re.IGNORECASE) + # 删除注释语句,进行语法判断,执行第一条有效sql + try: + sql = sqlparse.format(sql, strip_comments=True) + sql = sqlparse.split(sql)[0] + result['filtered_sql'] = sql.strip() + # sql_lower = sql.lower() + except IndexError: + result['bad_query'] = True + result['msg'] = '没有有效的SQL语句' + return result + if whitelist_pattern.match(sql) is None: + result['bad_query'] = True + result['msg'] = '仅支持{}语法!'.format(','.join(sql_whitelist)) + return result + if result.get('bad_query'): + result['msg'] = keyword_warning + return result