diff --git a/TODO b/TODO index b01349c0..a8135054 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,10 @@ * [] Vendor in tabulate. +* [] Add MySQL commands (use, describe etc) +* [X] Add exit keyword. * [] Show only table sensitive columns. * [] Add logging. * [] Add some tests. Sanity, Unit, Completion, Config. +* [] Setup the pgcli.com website. * [ ] Add a new trigger for M-/ that does dumb completion. * [] Improve the smart completion for Insert statement. * [] Improve the smart completion for Update statement. diff --git a/pgcli/main.py b/pgcli/main.py index 34f4188a..ef047b68 100755 --- a/pgcli/main.py +++ b/pgcli/main.py @@ -60,6 +60,13 @@ def cli(database, user, password, host, port): try: while True: document = cli.read_input(on_exit=AbortAction.RAISE_EXCEPTION) + + # The reason we check here instead of inside the pgexecute is + # because we want to raise the Exit exception which will be caught + # by the try/except block that wraps the pgexecute.run() statement. + if (document.text.strip() == 'exit' + or document.text.strip() == 'quit'): + raise Exit try: rows, headers, status = pgexecute.run(document.text) if rows: diff --git a/pgcli/pgline.py b/pgcli/pgline.py index 97604ef5..831c490c 100644 --- a/pgcli/pgline.py +++ b/pgcli/pgline.py @@ -10,7 +10,7 @@ class PGLine(Line): Dynamically determine whether we're in multiline mode. """ - if self.text.rstrip().endswith(';'): + if _multiline_exception(self.text): return False return True @@ -18,3 +18,12 @@ class PGLine(Line): @is_multiline.setter def is_multiline(self, value): pass + + +def _multiline_exception(text): + text = text.strip() + return (text.startswith('\\') or # Special Command + text.endswith(';') or # Ended with a semi-colon + (text == 'exit') or # Exit and Quit doesn't need semi-colon + (text == 'quit') + ) diff --git a/pgcli/pgspecial.py b/pgcli/pgspecial.py index a78a20e8..ccdcb91a 100644 --- a/pgcli/pgspecial.py +++ b/pgcli/pgspecial.py @@ -25,15 +25,21 @@ def describe_table_details(cur, pattern, verbose): """ Returns (rows, headers, status) """ - schema, relname = sql_name_pattern(pattern) + sql = '''SELECT c.oid, n.nspname, c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace ''' - if relname: - sql += ' WHERE c.relname ~ ' + relname - if schema: - sql += ' AND n.nspname ~ ' + schema - sql += ' AND pg_catalog.pg_table_is_visible(c.oid) ' + if pattern: + schema, relname = sql_name_pattern(pattern) + if relname: + sql += ' WHERE c.relname ~ ' + relname + if schema: + sql += ' AND n.nspname ~ ' + schema + sql += ' AND pg_catalog.pg_table_is_visible(c.oid) ' + else: + sql += """WHERE n.nspname <> 'pg_catalog' + AND n.nspname <> 'information_schema'""" + sql += ' ORDER BY 2,3' # Execute the sql, get the results and call describe_one_table_details on each table. @@ -248,4 +254,5 @@ if __name__ == '__main__': import psycopg2 con = psycopg2.connect(database='misago_testforum') cur = con.cursor() - print describe_table_details(cur, 'django_migrations', False) + #print describe_table_details(cur, 'django_migrations', False) + print describe_table_details(cur, None, False)