1
0
Fork 0

Add DESCRIBE command to pgspecial.

This commit is contained in:
Amjith Ramanujam 2014-12-11 20:07:54 -08:00
parent 5618104a3b
commit a865c5d40a
4 changed files with 32 additions and 17 deletions

8
TODO
View File

@ -1,21 +1,21 @@
* [O] Add MySQL commands (use, describe etc)
* [] Check why Indexes have a invalid at the end when \d is called on them.
* [] Fix smartcompletion for special commands. \d <tab>
* [] Add some tests. Sanity, Unit, Completion, Config.
* [ ] Add tests for smart completion.
* [] Check how to add the name of the table before printing the table.
* [] Show only table sensitive columns in autocompletion.
* [] Add a toolbar at the bottom with some helpful keyboard shortcuts.
* [] Add logging.
* [] Setup the pgcli.com website.
* [ ] Add a new trigger for M-/ that does dumb completion.
* [] Add function keys that can enable/disable smart completion.
* [] Improve the smart completion for Insert statement.
* [] Improve the smart completion for Update statement.
* [ ] Find a way to add documentation to sql commands. This could get tricky.
* [ ] Detect a '.' and parse the word before it and get it's real name.
* [] Refactor the execution and output into a separate class.
* [] Create a class for the config and make it easy to access.
* [O] Add MySQL commands (use, describe etc)
* [X] Add function keys that can enable/disable smart completion.
* [X] Add a toolbar at the bottom with some helpful keyboard shortcuts.
* [X] Fix smartcompletion for special commands. \d <tab>
* [X] Add more complex slash commands such as \d <table_name>.
* This is going to take a separate lib.
* [X] Create a better framework for adding special commands.

View File

@ -19,6 +19,24 @@ class MockLogging(object):
#log = MockLogging()
#def parse_special_command(sql):
## Sort the command by the length, so the longest command comes first. This
## is to ensure we match the most specific command first. For example: \dt+
## will match \dt instead of \d.
#ordered_commands = sorted(COMMANDS, key=len, reverse=True)
#for command in ordered_commands:
#if sql.startswith(command):
#plus, _, arg = sql[len(command):].partition(' ')
#break
#verbose = '+' in plus
#return (command.strip(), verbose, arg.strip())
def parse_special_command(sql):
command, _, arg = sql.partition(' ')
verbose = '+' in command
return (command.strip(), verbose, arg.strip())
def describe_table_details(cur, pattern, verbose):
"""
Returns (rows, headers, status)
@ -670,6 +688,7 @@ def sql_name_pattern(pattern):
return schema, relname
COMMANDS = {
'describe': describe_table_details,
'\d': describe_table_details,
'\dt': '''SELECT n.nspname as "Schema", c.relname as "Name", CASE
c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN
@ -683,12 +702,12 @@ COMMANDS = {
1,2;'''
}
command_available = COMMANDS.__contains__
def execute(cur, command, verbose, arg):
def execute(cur, sql):
"""Execute a special command and return the results. If the special command
is not supported a KeyError will be raised.
"""
command, verbose, arg = parse_special_command(sql)
global COMMANDS
command_executor = COMMANDS[command]

View File

@ -94,7 +94,7 @@ class PGCompleter(Completer):
return self.find_matches(word_before_cursor, self.column_names)
elif last_token.lower() in ('from', 'update', 'into'):
return self.find_matches(word_before_cursor, self.table_names)
elif last_token in ('d',): # This for the \d special command.
elif last_token in ('d', 'describe'): # This for the \d special command.
return self.find_matches(word_before_cursor, self.table_names)
elif last_token in ('c',): # This for the \c special command.
return self.find_matches(word_before_cursor, self.database_names)

View File

@ -24,12 +24,6 @@ class PGExecute(object):
self.port = port
self.conn.autocommit = True
@staticmethod
def parse_pattern(sql):
command, _, arg = sql.partition(' ')
verbose = '+' in command
return (command.strip(), verbose, arg.strip())
def run(self, sql):
"""Execute the sql in the database and return the results. The results
are a list of tuples. Each tuple has 3 values (rows, headers, status).
@ -43,7 +37,10 @@ class PGExecute(object):
# that cannot be offloaded to `pgspecial` lib. Because we have to
# change the database connection that we're connected to.
if sql.startswith('\c') or sql.lower().startswith('use'):
dbname = self.parse_pattern(sql)[2]
try:
dbname = sql.split()[1]
except:
raise RuntimeError('Database name missing.')
self.conn = psycopg2.connect(database=dbname,
user=self.user, password=self.password, host=self.host,
port=self.port)
@ -53,8 +50,7 @@ class PGExecute(object):
with self.conn.cursor() as cur:
try:
results = pgspecial.execute(cur, *self.parse_pattern(sql))
return results
return pgspecial.execute(cur, sql)
except KeyError:
cur.execute(sql)