mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-10 07:26:01 -06:00
- Extract SQLEditor.execute and SQLEditor._poll into their own files and add test around them - Extract SQLEditor backend functions that start executing query to their own files and add tests around it - Move the Explain SQL from the front-end and now pass the Explain plan parameters as a JSON object in the start query call. - Extract the compile_template_name into a function that can be used by the different places that try to select the version of the template and the server type
170 lines
5.6 KiB
Python
170 lines
5.6 KiB
Python
##########################################################################
|
|
#
|
|
# pgAdmin 4 - PostgreSQL Tools
|
|
#
|
|
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
|
# This software is released under the PostgreSQL Licence
|
|
#
|
|
##########################################################################
|
|
|
|
"""Check if requires BEGIN in the current query."""
|
|
|
|
|
|
def is_begin_required(query):
|
|
word_len = 0
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
|
|
# Check word length (since "beginx" is not "begin").
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
# Transaction control commands. These should include every keyword that
|
|
# gives rise to a TransactionStmt in the backend grammar, except for the
|
|
# savepoint-related commands.
|
|
#
|
|
# (We assume that START must be START TRANSACTION, since there is
|
|
# presently no other "START foo" command.)
|
|
|
|
keyword = query[0:word_len]
|
|
|
|
if word_len == 5 and keyword.lower() == "abort":
|
|
return False
|
|
if word_len == 5 and keyword.lower() == "begin":
|
|
return False
|
|
if word_len == 5 and keyword.lower() == "start":
|
|
return False
|
|
if word_len == 6:
|
|
# SELECT is protected from dirty reads hence don't require transaction
|
|
if keyword.lower() in ["select", "commit"]:
|
|
return False
|
|
if word_len == 3 and keyword.lower() == "end":
|
|
return False
|
|
if word_len == 8 and keyword.lower() == "rollback":
|
|
return False
|
|
if word_len == 7 and keyword.lower() == "prepare":
|
|
# PREPARE TRANSACTION is a TC command, PREPARE foo is not
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
if word_len == 11 and keyword.lower() == "transaction":
|
|
return False
|
|
return True
|
|
|
|
# Commands not allowed within transactions. The statements checked for
|
|
# here should be exactly those that call PreventTransactionChain() in the
|
|
# backend.
|
|
if word_len == 6 and keyword.lower() == "vacuum":
|
|
return False
|
|
|
|
if word_len == 7 and keyword.lower() == "cluster":
|
|
# CLUSTER with any arguments is allowed in transactions
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
|
|
if query[0].isalpha():
|
|
return True # has additional words
|
|
return False # it's CLUSTER without arguments
|
|
|
|
if word_len == 6 and keyword.lower() == "create":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
if word_len == 8 and keyword.lower() == "database":
|
|
return False
|
|
if word_len == 10 and keyword.lower() == "tablespace":
|
|
return False
|
|
|
|
# CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts
|
|
if word_len == 7 and keyword.lower() == "cluster":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
|
|
if word_len == 5 and keyword.lower() == "index":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
if word_len == 12 and keyword.lower() == "concurrently":
|
|
return False
|
|
return True
|
|
|
|
if word_len == 5 and keyword.lower() == "alter":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
|
|
# ALTER SYSTEM isn't allowed in xacts
|
|
if word_len == 6 and keyword.lower() == "system":
|
|
return False
|
|
return True
|
|
|
|
# Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
|
|
# aren't really valid commands so we don't care much. The other four
|
|
# possible matches are correct.
|
|
if word_len == 4 and keyword.lower() == "drop" \
|
|
or word_len == 7 and keyword.lower() == "reindex":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
if word_len == 8 and keyword.lower() == "database":
|
|
return False
|
|
if word_len == 6 and keyword.lower() == "system":
|
|
return False
|
|
if word_len == 10 and keyword.lower() == "tablespace":
|
|
return False
|
|
return True
|
|
|
|
# DISCARD ALL isn't allowed in xacts, but other variants are allowed.
|
|
if word_len == 7 and keyword.lower() == "discard":
|
|
query = query[word_len:query_len]
|
|
query = query.strip()
|
|
query_len = len(query)
|
|
word_len = 0
|
|
|
|
while (word_len < query_len) and query[word_len].isalpha():
|
|
word_len += 1
|
|
|
|
keyword = query[0:word_len]
|
|
if word_len == 3 and keyword.lower() == "all":
|
|
return False
|
|
return True
|
|
|
|
return True
|