Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def _match(self, sqls):
"""对查询进行规则检测"""
default_rows = 100
max_rows = 200
# 检查配置的值
if QUERY_LIMIT['enable'] is True:
default_rows = int(QUERY_LIMIT['default_limit'])
max_rows = int(QUERY_LIMIT['max_limit'])
# 对limit进行处理
for sql in sqls:
stmt = sqlparse.parse(sql)[0]
limit_match = ''
seen = False
# 匹配sql语句中的limit
for token in stmt.tokens:
if seen:
limit_match += token.value
else:
if token.ttype is Keyword and token.value.upper() == 'LIMIT':
seen = True
limit_match += token.value.upper()
# 匹配 limit N
limit_n = re.compile('limit([\s]*\d+[\s]*)$', re.I | re.S)
# 匹配limit N, N 或limit N offset N
limit_offset = re.compile('limit([\s]*\d+[\s]*)(,|offset)([\s]*\d+[\s]*)$',
re.I | re.S)
def _reorder_types(self, types_script):
"""
Takes type scripts and reorders them to avoid Type doesn't exist exception
"""
self._logger.debug('Running types definitions scripts')
self._logger.debug('Reordering types definitions scripts to avoid "type does not exist" exceptions')
_type_statements = sqlparse.split(types_script)
# TODO: move up to classes
_type_statements_dict = {} # dictionary that store statements with type and order.
type_unordered_scripts = [] # scripts to execute without order
type_drop_scripts = [] # drop scripts to execute first
for _type_statement in _type_statements:
_type_statement_parsed = sqlparse.parse(_type_statement)
if len(_type_statement_parsed) > 0: # can be empty parsed object so need to check
# we need only type declarations to be ordered
if _type_statement_parsed[0].get_type() == 'CREATE':
_type_body_r = r'\bcreate\s+\b(?:type|domain)\s+\b(\w+\.\w+|\w+)\b'
_type_name = re.compile(_type_body_r, flags=re.IGNORECASE).findall(_type_statement)[0]
_type_statements_dict[str(_type_name)] = \
{'script': _type_statement, 'deps': []}
elif _type_statement_parsed[0].get_type() == 'DROP':
type_drop_scripts.append(_type_statement)
else:
type_unordered_scripts.append(_type_statement)
# now let's add dependant types to dictionary with types
# _type_statements_list = [] # list of statements to be ordered
for _type_key in _type_statements_dict.keys():
for _type_key_sub, _type_value in _type_statements_dict.items():
if _type_key != _type_key_sub:
identifier = None
# here should be removed once sqlparse has been fixed
try:
# If we've partially typed a word then word_before_cursor won't be an empty
# string. In that case we want to remove the partially typed string before
# sending it to the sqlparser. Otherwise the last token will always be the
# partially typed string which renders the smart completion useless because
# it will always return the list of keywords as completion.
if word_before_cursor:
if word_before_cursor.endswith(
'(') or word_before_cursor.startswith('\\'):
parsed = sqlparse.parse(text_before_cursor)
else:
parsed = sqlparse.parse(
text_before_cursor[:-len(word_before_cursor)])
# word_before_cursor may include a schema qualification, like
# "schema_name.partial_name" or "schema_name.", so parse it
# separately
p = sqlparse.parse(word_before_cursor)[0]
if p.tokens and isinstance(p.tokens[0], Identifier):
identifier = p.tokens[0]
else:
parsed = sqlparse.parse(text_before_cursor)
except (TypeError, AttributeError):
return [{'type': 'keyword'}]
if len(parsed) > 1:
# Multiple statements being edited -- isolate the current one by
def is_dropping_database(queries, dbname):
"""Determine if the query is dropping a specific database."""
if dbname is None:
return False
def normalize_db_name(db):
return db.lower().strip('`"')
dbname = normalize_db_name(dbname)
for query in sqlparse.parse(queries):
if query.get_name() is None:
continue
first_token = query.token_first(skip_cm=True)
_, second_token = query.token_next(0, skip_cm=True)
database_name = normalize_db_name(query.get_name())
if (
first_token.value.lower() == "drop"
and second_token.value.lower() in ("database", "schema")
and database_name == dbname
):
return True
# sqlparse groups all tokens from the where clause into a single token
# list. This means that token.value may be something like
# 'where foo > 5 and '. We need to look "inside" token.tokens to handle
# suggestions in complicated where clauses correctly
prev_keyword, text_before_cursor = find_prev_keyword(text_before_cursor)
return suggest_based_on_last_token(prev_keyword, text_before_cursor,
full_text, identifier)
else:
token_v = token.value.lower()
is_operand = lambda x: x and any([x.endswith(op) for op in ['+', '-', '*', '/']])
if not token:
return (Keyword(), Special())
elif token_v.endswith('('):
p = sqlparse.parse(text_before_cursor)[0]
if p.tokens and isinstance(p.tokens[-1], Where):
# Four possibilities:
# 1 - Parenthesized clause like "WHERE foo AND ("
# Suggest columns/functions
# 2 - Function call like "WHERE foo("
# Suggest columns/functions
# 3 - Subquery expression like "WHERE EXISTS ("
# Suggest keywords, in order to do a subquery
# 4 - Subquery OR array comparison like "WHERE foo = ANY("
# Suggest columns/functions AND keywords. (If we wanted to be
# really fancy, we could suggest only array-typed columns)
column_suggestions = suggest_based_on_last_token('where',
text_before_cursor, full_text, identifier)
def collect_mysql_metrics(context, trace, instance, args):
connection = instance.connection_proxy
db = connection.extract_db
hostname = connection.extract_hostname
port = connection.extract_port
command, table = None, None
query = sqlparse.parse(args[0])
if query:
query = query[0]
command = query.get_type()
table = query.get_name()
request = Request(
command=ensure_utf8(command),
key=None,
hostname=ensure_utf8(hostname),
port=ensure_utf8(port),
connectionName=None,
db=ensure_utf8(db),
table=ensure_utf8(table),
)
request = request._asdict()
context.iopipe.mark.db_trace(trace, "mysql", request)
def extract_tables(sql):
"""Extract the table names from an SQL statment.
Returns a list of TableReference namedtuples
"""
parsed = sqlparse.parse(sql)
if not parsed:
return ()
# INSERT statements must stop looking for tables at the sign of first
# Punctuation. eg: INSERT INTO abc (col1, col2) VALUES (1, 2)
# abc is the table name, but if we don't stop at the first lparen, then
# we'll identify abc, col1 and col2 as table names.
insert_stmt = parsed[0].token_first().value.lower() == "insert"
stream = extract_from_part(parsed[0], stop_at_punctuation=insert_stmt)
# Kludge: sqlparse mistakenly identifies insert statements as
# function calls due to the parenthesized column list, e.g. interprets
# "insert into foo (bar, baz)" as a function call to foo with arguments
# (bar, baz). So don't allow any identifiers in insert statements
# to have is_function=True
identifiers = extract_table_identifiers(stream, allow_functions=not insert_stmt)
def _parse_constraint_columns(self, check_clause, columns):
check_columns = OrderedSet()
statement = sqlparse.parse(check_clause)[0]
tokens = (token for token in statement.flatten() if not token.is_whitespace)
for token in tokens:
if (
token.ttype == sqlparse.tokens.Name and
self.connection.ops.quote_name(token.value) == token.value and
token.value[1:-1] in columns
):
check_columns.add(token.value[1:-1])
return check_columns
text_before_cursor = _strip_named_query(text_before_cursor)
full_text, text_before_cursor, self.local_tables = \
isolate_query_ctes(full_text, text_before_cursor)
self.text_before_cursor_including_last_word = text_before_cursor
# If we've partially typed a word then word_before_cursor won't be an
# empty string. In that case we want to remove the partially typed
# string before sending it to the sqlparser. Otherwise the last token
# will always be the partially typed string which renders the smart
# completion useless because it will always return the list of
# keywords as completion.
if self.word_before_cursor:
if word_before_cursor[-1] == '(' or word_before_cursor[0] == '\\':
parsed = sqlparse.parse(text_before_cursor)
else:
text_before_cursor = text_before_cursor[:-len(word_before_cursor)]
parsed = sqlparse.parse(text_before_cursor)
self.identifier = parse_partial_identifier(word_before_cursor)
else:
parsed = sqlparse.parse(text_before_cursor)
full_text, text_before_cursor, parsed = \
_split_multiple_statements(full_text, text_before_cursor, parsed)
self.full_text = full_text
self.text_before_cursor = text_before_cursor
self.parsed = parsed
self.last_token = parsed and parsed.token_prev(len(parsed.tokens))[1] or ''
def read_glob_stmts(glob_pattern):
"return wrapped stmts for files matching glob"
stmts = []
for fname in glob.glob(glob_pattern):
stmts.extend(map(wrappers.wrap, sqlparse.parse(open(fname).read())))
return stmts