From 9b77fda0d4171f68760c070895dc5700cb6d1e0f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 6 Sep 2021 06:17:12 +0200 Subject: Merging upstream version 3.2.0. Signed-off-by: Daniel Baumann --- pgcli/packages/parseutils/__init__.py | 32 +++++++++++++++++++++---------- pgcli/packages/parseutils/meta.py | 2 +- pgcli/packages/parseutils/tables.py | 3 +-- pgcli/packages/pgliterals/pgliterals.json | 1 + pgcli/packages/prioritization.py | 4 ++-- pgcli/packages/prompt_utils.py | 4 ++-- pgcli/packages/sqlcompletion.py | 2 +- 7 files changed, 30 insertions(+), 18 deletions(-) (limited to 'pgcli/packages') diff --git a/pgcli/packages/parseutils/__init__.py b/pgcli/packages/parseutils/__init__.py index a11e7bf..1acc008 100644 --- a/pgcli/packages/parseutils/__init__.py +++ b/pgcli/packages/parseutils/__init__.py @@ -1,22 +1,34 @@ import sqlparse -def query_starts_with(query, prefixes): +def query_starts_with(formatted_sql, prefixes): """Check if the query starts with any item from *prefixes*.""" prefixes = [prefix.lower() for prefix in prefixes] - formatted_sql = sqlparse.format(query.lower(), strip_comments=True).strip() return bool(formatted_sql) and formatted_sql.split()[0] in prefixes -def queries_start_with(queries, prefixes): - """Check if any queries start with any item from *prefixes*.""" - for query in sqlparse.split(queries): - if query and query_starts_with(query, prefixes) is True: - return True - return False +def query_is_unconditional_update(formatted_sql): + """Check if the query starts with UPDATE and contains no WHERE.""" + tokens = formatted_sql.split() + return bool(tokens) and tokens[0] == "update" and "where" not in tokens + +def query_is_simple_update(formatted_sql): + """Check if the query starts with UPDATE.""" + tokens = formatted_sql.split() + return bool(tokens) and tokens[0] == "update" -def is_destructive(queries): + +def is_destructive(queries, warning_level="all"): """Returns if any of the queries in *queries* is destructive.""" keywords = ("drop", "shutdown", "delete", "truncate", "alter") - return queries_start_with(queries, keywords) + for query in sqlparse.split(queries): + if query: + formatted_sql = sqlparse.format(query.lower(), strip_comments=True).strip() + if query_starts_with(formatted_sql, keywords): + return True + if query_is_unconditional_update(formatted_sql): + return True + if warning_level == "all" and query_is_simple_update(formatted_sql): + return True + return False diff --git a/pgcli/packages/parseutils/meta.py b/pgcli/packages/parseutils/meta.py index 108c01a..333cab5 100644 --- a/pgcli/packages/parseutils/meta.py +++ b/pgcli/packages/parseutils/meta.py @@ -50,7 +50,7 @@ def parse_defaults(defaults_string): yield current -class FunctionMetadata(object): +class FunctionMetadata: def __init__( self, schema_name, diff --git a/pgcli/packages/parseutils/tables.py b/pgcli/packages/parseutils/tables.py index 0ec3e69..aaa676c 100644 --- a/pgcli/packages/parseutils/tables.py +++ b/pgcli/packages/parseutils/tables.py @@ -42,8 +42,7 @@ def extract_from_part(parsed, stop_at_punctuation=True): for item in parsed.tokens: if tbl_prefix_seen: if is_subselect(item): - for x in extract_from_part(item, stop_at_punctuation): - yield x + yield from extract_from_part(item, stop_at_punctuation) elif stop_at_punctuation and item.ttype is Punctuation: return # An incomplete nested select won't be recognized correctly as a diff --git a/pgcli/packages/pgliterals/pgliterals.json b/pgcli/packages/pgliterals/pgliterals.json index c7b74b5..df00817 100644 --- a/pgcli/packages/pgliterals/pgliterals.json +++ b/pgcli/packages/pgliterals/pgliterals.json @@ -392,6 +392,7 @@ "QUOTE_NULLABLE", "RADIANS", "RADIUS", + "RANDOM", "RANK", "REGEXP_MATCH", "REGEXP_MATCHES", diff --git a/pgcli/packages/prioritization.py b/pgcli/packages/prioritization.py index e92dcbb..f5a9cb5 100644 --- a/pgcli/packages/prioritization.py +++ b/pgcli/packages/prioritization.py @@ -16,10 +16,10 @@ def _compile_regex(keyword): keywords = get_literals("keywords") -keyword_regexs = dict((kw, _compile_regex(kw)) for kw in keywords) +keyword_regexs = {kw: _compile_regex(kw) for kw in keywords} -class PrevalenceCounter(object): +class PrevalenceCounter: def __init__(self): self.keyword_counts = defaultdict(int) self.name_counts = defaultdict(int) diff --git a/pgcli/packages/prompt_utils.py b/pgcli/packages/prompt_utils.py index 3c58490..e8589de 100644 --- a/pgcli/packages/prompt_utils.py +++ b/pgcli/packages/prompt_utils.py @@ -3,7 +3,7 @@ import click from .parseutils import is_destructive -def confirm_destructive_query(queries): +def confirm_destructive_query(queries, warning_level): """Check if the query is destructive and prompts the user to confirm. Returns: @@ -15,7 +15,7 @@ def confirm_destructive_query(queries): prompt_text = ( "You're about to run a destructive command.\n" "Do you want to proceed? (y/n)" ) - if is_destructive(queries) and sys.stdin.isatty(): + if is_destructive(queries, warning_level) and sys.stdin.isatty(): return prompt(prompt_text, type=bool) diff --git a/pgcli/packages/sqlcompletion.py b/pgcli/packages/sqlcompletion.py index 6ef8859..6305301 100644 --- a/pgcli/packages/sqlcompletion.py +++ b/pgcli/packages/sqlcompletion.py @@ -47,7 +47,7 @@ Alias = namedtuple("Alias", ["aliases"]) Path = namedtuple("Path", []) -class SqlStatement(object): +class SqlStatement: def __init__(self, full_text, text_before_cursor): self.identifier = None self.word_before_cursor = word_before_cursor = last_word( -- cgit v1.2.3