Skip to content

Commit

Permalink
Ensure "before" and "after" runs on all commands
Browse files Browse the repository at this point in the history
Make sure that `before` and newly introduced `after` sql in `cli_options`
settings is added to each command (if configured on top level) as well as
introduce optional per command `before` and "after` which are run
in addition main `before` and `after`.
  • Loading branch information
tkopets committed Dec 15, 2017
1 parent 439732a commit 1324fbf
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 63 deletions.
8 changes: 8 additions & 0 deletions SQLTools.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"pgsql": {
"options": ["--no-password"],
"before": [],
"after": [],
"args": "-h {host} -p {port} -U {username} -d {database}",
"env_optional": {
"PGPASSWORD": "{password}"
Expand Down Expand Up @@ -126,6 +127,7 @@
"SET VERIFY OFF ",
"SET WRAP OFF"
],
"after": [],
"args": "{username}/{password}@\"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={host})(PORT={port})))(CONNECT_DATA=(SERVICE_NAME={service})))\"",
"queries": {
"desc" : {
Expand Down Expand Up @@ -153,6 +155,7 @@
"mysql": {
"options": ["-f", "--table", "--default-character-set=utf8"],
"before": [],
"after": [],
"args": "-h{host} -P{port} -u\"{username}\" -D\"{database}\"",
"args_optional": ["--login-path=\"{login-path}\"", "--defaults-extra-file=\"{defaults-extra-file}\"", "-p\"{password}\""],
"queries": {
Expand Down Expand Up @@ -189,6 +192,7 @@
"mssql": {
"options": [],
"before": [],
"after": ["GO", "QUIT"],
"args": "-d \"{database}\"",
"args_optional": ["-S \"{host},{port}\"", "-S \"{host}\\{instance}\"", "-U \"{username}\"", "-P \"{password}\""],
"queries": {
Expand All @@ -213,6 +217,7 @@
"vertica": {
"options": [],
"before" : [],
"after": [],
"args": "-h {host} -p {port} -U \"{username}\" -w \"{password}\" -d \"{database}\"",
"queries": {
"desc" : {
Expand Down Expand Up @@ -240,6 +245,7 @@
"sqsh": {
"options": [],
"before": ["\\set semicolon_cmd=\"\\go -mpretty -l\""],
"after": [],
"args": "-S {host}:{port} -U\"{username}\" -P\"{password}\" -D{database}",
"queries": {
"desc": {
Expand Down Expand Up @@ -267,6 +273,7 @@
"sqlite": {
"options": ["-column", "-header"],
"before": [],
"after": [],
"args": "\"{database}\"",
"queries": {
"desc" : {
Expand All @@ -290,6 +297,7 @@
"firebird": {
"options": [],
"before": [],
"after": [],
"args": "-u \"{username}\" -p \"{password}\" \"{host}/{port}:{database}\"",
"queries": {
"desc" : {
Expand Down
176 changes: 113 additions & 63 deletions SQLToolsAPI/Connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,92 +71,87 @@ def info(self):
return 'DB: {0}, Connection: {1}@{2}:{3}'.format(
self.database, self.username, self.host, self.port)

def getTables(self, callback):
query = self.getOptionsForSgdbCli()['queries']['desc']['query']
def runInternalNamedQueryCommand(self, queryName, callback):
query = self.getNamedQuery(queryName)
if not query:
return

args = self.buildArgs(queryName)
env = self.buildEnv()

def cb(result):
callback(U.getResultAsList(result))

args = self.buildArgs('desc')
env = self.buildEnv()
self.Command.createAndRun(args, env,
query, cb, silenceErrors=True)

def getColumns(self, callback):
query, cb,
silenceErrors=True)

def cb(result):
callback(U.getResultAsList(result))
def getTables(self, callback):
self.runInternalNamedQueryCommand('desc', callback)

try:
query = self.getOptionsForSgdbCli()['queries']['columns']['query']
args = self.buildArgs('columns')
env = self.buildEnv()
self.Command.createAndRun(args, env,
query, cb, silenceErrors=True)
except Exception:
pass
def getColumns(self, callback):
self.runInternalNamedQueryCommand('columns', callback)

def getFunctions(self, callback):
self.runInternalNamedQueryCommand('functions', callback)

def cb(result):
callback(U.getResultAsList(result))
def runFormattedNamedQueryCommand(self, queryName, formatValues, callback):
query = self.getNamedQuery(queryName)
if not query:
return

try:
query = self.getOptionsForSgdbCli()['queries']['functions']['query']
args = self.buildArgs('functions')
env = self.buildEnv()
self.Command.createAndRun(args, env,
query, cb, silenceErrors=True)
except Exception:
pass
# added for compatibility with older format string
query = query.replace("%s", "{0}", 1)
query = query.replace("%s", "{1}", 1)

def getTableRecords(self, tableName, callback):
query = self.getOptionsForSgdbCli()['queries']['show records']['query'].format(tableName, self.rowsLimit)
queryToRun = '\n'.join(self.getOptionsForSgdbCli()['before'] + [query])
args = self.buildArgs('show records')
if isinstance(formatValues, tuple):
query = query.format(*formatValues) # unpack the tuple
else:
query = query.format(formatValues)

queryToRun = self.buildNamedQuery(queryName, query)
args = self.buildArgs(queryName)
env = self.buildEnv()
self.Command.createAndRun(args, env, queryToRun, callback, timeout=self.timeout)

def getTableRecords(self, tableName, callback):
# in case we expect multiple values pack them into tuple
formatValues = (tableName, self.rowsLimit)
self.runFormattedNamedQueryCommand('show records', formatValues, callback)

def getTableDescription(self, tableName, callback):
query = self.getOptionsForSgdbCli()['queries']['desc table']['query'] % tableName
queryToRun = '\n'.join(self.getOptionsForSgdbCli()['before'] + [query])
args = self.buildArgs('desc table')
env = self.buildEnv()
self.Command.createAndRun(args, env, queryToRun, callback)
self.runFormattedNamedQueryCommand('desc table', tableName, callback)

def getFunctionDescription(self, functionName, callback):
query = self.getOptionsForSgdbCli()['queries']['desc function'][
'query'] % functionName
queryToRun = '\n'.join(self.getOptionsForSgdbCli()['before'] + [query])
args = self.buildArgs('desc function')
env = self.buildEnv()
self.Command.createAndRun(args, env, queryToRun, callback)
self.runFormattedNamedQueryCommand('desc function', functionName, callback)

def explainPlan(self, queries, callback):
try:
queryFormat = self.getOptionsForSgdbCli()['queries']['explain plan']['query']
except KeyError:
return # do nothing, if DBMS has no support for explain plan
queryName = 'explain plan'
explainQuery = self.getNamedQuery(queryName)
if not explainQuery:
return

stripped_queries = [
queryFormat.format(query.strip().strip(";"))
strippedQueries = [
explainQuery.format(query.strip().strip(";"))
for rawQuery in queries
for query in filter(None, sqlparse.split(rawQuery))
]
queryToRun = '\n'.join(self.getOptionsForSgdbCli()['before'] + stripped_queries)
args = self.buildArgs('explain plan')
queryToRun = self.buildNamedQuery(queryName, strippedQueries)
args = self.buildArgs(queryName)
env = self.buildEnv()
self.Command.createAndRun(args, env, queryToRun, callback, timeout=self.timeout)

def execute(self, queries, callback, stream=False):
queryToRun = ''

for query in self.getOptionsForSgdbCli()['before']:
queryToRun += query + "\n"
queryName = 'execute'

if isinstance(queries, str):
queries = [queries]

# add original (umodified) queries to the history
if self.history:
self.history.add('\n'.join(queries))

processedQueriesList = []
for rawQuery in queries:
for query in sqlparse.split(rawQuery):
if self.safe_limit:
Expand All @@ -172,16 +167,58 @@ def execute(self, queries, callback, stream=False):
if (query.strip()[-1:] == ';'):
query = query.strip()[:-1]
query += " LIMIT {0};".format(self.safe_limit)
queryToRun += query + "\n"
processedQueriesList.append(query)

queryToRun = self.buildNamedQuery(queryName, processedQueriesList)
args = self.buildArgs(queryName)
env = self.buildEnv()

Log("Query: " + queryToRun)

if self.history:
self.history.add(queryToRun)
self.Command.createAndRun(args, env, queryToRun, callback,
options={'show_query': self.show_query},
timeout=self.timeout,
stream=stream)

args = self.buildArgs()
env = self.buildEnv()
self.Command.createAndRun(args, env, queryToRun, callback, options={'show_query': self.show_query}, timeout=self.timeout, stream=stream)
def getNamedQuery(self, queryName):
if not queryName:
return None

cliOptions = self.getOptionsForSgdbCli()
return cliOptions.get('queries', {}).get(queryName, {}).get('query')

def buildNamedQuery(self, queryName, queries):
if not queryName:
return None

if not queries:
return None

cliOptions = self.getOptionsForSgdbCli()
beforeCli = cliOptions.get('before')
beforeQuery = cliOptions.get('queries', {}).get(queryName, {}).get('before')
afterCli = cliOptions.get('after')
afterQuery = cliOptions.get('queries', {}).get(queryName, {}).get('after')

# sometimes we preprocess the raw queries from user, in that case we already have a list
if type(queries) is not list:
queries = [queries]

builtQueries = []
if beforeCli is not None:
builtQueries.extend(beforeCli)
if beforeQuery is not None:
builtQueries.extend(beforeQuery)
if queries is not None:
builtQueries.extend(queries)
if afterCli is not None:
builtQueries.extend(afterCli)
if afterQuery is not None:
builtQueries.extend(afterQuery)

print(builtQueries)

return '\n'.join(builtQueries)

def buildArgs(self, queryName=None):
cliOptions = self.getOptionsForSgdbCli()
Expand All @@ -200,11 +237,24 @@ def buildArgs(self, queryName=None):
if formattedItem:
args = args + shlex.split(formattedItem)

# append generic options
# options = cliOptions.get('options', None)
# if options:
# args = args + options

# append query specific options (if present)
# if queryName:
# queryOptions = cliOptions.get('queries', {}).get(queryName, {}).get.('options')
# if queryOptions:
# if len(queryOptions) > 0:
# args = args + queryOptions

# append query specific options
if queryName:
queryOptions = cliOptions['queries'][queryName]['options']
if len(queryOptions) > 0:
args = args + queryOptions
queryOptions = cliOptions.get('queries', {}).get(queryName, {}).get('options')
if queryOptions:
if len(queryOptions) > 0:
args = args + queryOptions
else:
# append generic options (only if not custom query)
options = cliOptions.get('options', None)
Expand Down

0 comments on commit 1324fbf

Please sign in to comment.