# HG changeset patch # User catherine@dellzilla # Date 1237495545 14400 # Node ID 701f0aae837af622e2b7a7f91858e065141653fa # Parent 8ea39093ddf2f0963ab5cc056f75d4c3c2b9f2d6 got maxtselctrows working again diff -r 8ea39093ddf2 -r 701f0aae837a docs/source/capabilities.rst --- a/docs/source/capabilities.rst Thu Mar 19 13:14:39 2009 -0400 +++ b/docs/source/capabilities.rst Thu Mar 19 16:45:45 2009 -0400 @@ -1,3 +1,4 @@ +============================== SQLPython's extra capabilities ============================== @@ -66,6 +67,55 @@ Run command matching or (as for `history`) - if multiple items would match, run most recent +Special I/O destinations +======================== + +Much as in a UNIX shell, you can follow a command with a special output destination. + +`> {filename}` sends the output to a file. This is more convenient than SQL\*Plus's +SPOOL {filename}... SPOOL OFF (though you can use those as well). + +`>` alone (no filename) sends the output to the paste buffer. + +`|` pipes the output to an operating-system command. + +When `< {filename}` is included in your command, it is replaced with the contents of +{filename} before the command is run. + +Examples:: + +Special output formats +====================== + +By replacing the `;` that terminates a SELECT statement with a backslash-character +sequence, you can get output in a number of useful formats. The `terminators` +command lists them, for your convenience:: + +=== ======================== ================================ + Especially useful for +=== ======================== ================================ +; standard Oracle format +\c CSV (with headings) sending to spreadsheets +\C CSV (no headings) +\g list wide output with linewraps +\G aligned list +\h HTML table web reports +\i INSERT statements copying to other instances +\j JSON +\s CSV (with headings) +\S CSV (no headings) +\t transposed "narrow" tables like v$database +\x XML +\l line plot, with markers +\L scatter plot (no lines) +\b bar graph +\p pie chart +=== ======================== ================================ + +Most of these output formats are even more useful when combined with special output +destinations. For example, `SELECT * FROM party\h > /var/www/party_report.html` +could create an HTML report in the webserver's documents directory, ready to serve. + UNIX-like commands ================== @@ -73,14 +123,41 @@ were files in a UNIX filesystem. Many of the commands also accept flags to modify their behavior. -ls - Lists objects from the data dictionaries, as though they were in a - *object_type*/*object_name* directory structure. Thus, `ls view/\*` - lists all the user's views. +ls {object type/object name, with wildcards} + Lists objects from the data dictionaries, as though they were in a + *object_type*/*object_name* directory structure. Thus, `ls view/\*` + lists all the user's views. Calling with no argument is equivalent + to `ls *`. + + Options:: + + -l, --long long descriptions + -a, --all all schemas' objects (otherwise, you only get your own) + -t, --timesort Sort by last_ddl_time + -r, --reverse Reverse order while sorting -cat - Shorthand for "SELECT * FROM" + `ls -lt *;10` lists the ten items with the most recent last_ddl_time; + this can be a good way to answer the question, "What was I working on?" + +cat {remainder of query} + Shorthand for "SELECT * FROM". Can be combined with anything else + that fits into a SELECT statement (WHERE, ORDER BY, etc.) + +grep {grep {target} {table} [{table2,...}] + Equivalent to SELECT * FROM {table} WHERE *any column* LIKE '%{target}%' + Useful when you don't know, don't remember, or don't care which column + a value may be found in. + + Options:: + + -i, --ignore-case Case-insensitive search +find -c {target}, find -t {column} + Lists all tables or columns whose names contain {target}. More convenient than + querying user_tab_columns/all_tab_columns or user_tables/all_tables. + Options:: + -a Find all objects (not just my own) + PostgreSQL-like shortcuts ========================= @@ -106,6 +183,62 @@ \\? help psql ----- ------------------ +PL/SQL source code +================== + +pull {object_name} + Displays the PL/SQL source code for {object_name}. + + Options: + -d, --dump dump results to files (object_type/object_name.sql) + -f, --full get dependent objects as well + -a, --all all schemas' objects + +bzr, git, hg {object_name} + Dump source code to files, as `pull -f`, but also creates or commits to a + repository of the appropriate distributed version control system + (Bazaar, Git, or Mercurial, respectively). + +find {target} + Lists all PL/SQL objects whose source code contains the {target} string. + Always case-insensitive. + Options:: + -a Search all PL/SQL objects (not just my own) + + +Bind variables +============== + +Bind variables work in sqlpython as they do in SQL\*Plus, but they are set dynamically; there +is no need to declare them before use. The syntax for setting them is more permissive than +in SQL\*Plus; all these are recognized:: + + exec :mybind := 'value' + exec :mybind = 'value' + :mybind := 'value' + :mybind = 'value' + +The current values of all bind variables can be viewed with the `print` command. + +The `bind` command creates and populates bind variables for the final row of the most recent +SELECT statement executed; each column name is used as a bind variable, which is filled with +the value. `bind -r {rownumber}` does the same, but fills from row {rownumber} instead of +from the final row (row numbers begin at 0 for this command). + +When the `autobind` sqlpython parameter is True, a `bind` statement is issued automatically +after every query that returns exactly one row. + +Bind variables are available from within Python as a dictionary named `binds` (see Python). + +Substitution variables +====================== + +Substitution variables ("&" variables) work much as they do in SQL\*Plus. As in SQL\*Plus, +the `scan` parameter determines whether queries are scanned to replace substitution +variables. Unlike SQL\*Plus, sqlpython knows how annoying it is to hit a substitution +variable you didn't expect, so entering "SET SCAN OFF" when prompted for a substitution +variable actually aborts the substitution process. + Wild SQL ======== @@ -120,3 +253,63 @@ Wild SQL can only be used in the primary column list of straightforward SELECT statements, not in subqueries, `UNION`ed queries, etc. + +Parameters +========== + +Several parameters control the behavior of sqlpython itself. + +===================== ================================================== =============== + default +===================== ================================================== =============== +autobind When True, single-row queries automatically `bind` False +commit_on_exit Automatically commits work at end of session True +continuation_prompt Prompt for second line and onward of long statement > +default_file_name The file opened by `edit`, if not specified afiedt.buf +echo Echo command entered before executing False +editor Text editor invoked by `edit`. varies +heading Print column names True +maxfetch Maximum number of rows to return from any query 1000 +maxtselctrows Maximum # of rows from a tselect or \\n query 10 +prompt Probably unwise to change user@instance> +scan Interpret & as indicating substitution variables True +serveroutput Print DBMS_OUTPUT.PUT_LINE results True +sql_echo Print text of "behind-the-scenes" queries False +timeout In seconds 30 +timing Print time for each command to execute False +wildsql Accept *, %, #, and ! in column names False +===================== ================================================== =============== + +The user can change these with the `set {paramname} {new-value}` statement. +The True/False parameters accept new +values permissively, recognizing "True", "False", "T", "F", "yes", "no", "on", "off"... + +`set` and `show` both list the current values of the sqlpython parameters. +`show parameter {param}` shows current Oracle parameters (from v$parameter), as it does +in SQL\*Plus. + +Tuning +====== + +In sqlpython, `explain {SQL ID}` shows the execution plan for the SQL statement with the +given ID. If SQL ID is omitted, it defaults to the most recent SQL executed. +(This is not necessarily the last statement `EXPLAIN PLAN` was issued against.) + +Other specialized sqlpython tuning commands include: + +load + Displays OS load on cluster nodes (10gRAC) + +longops + Displays long-running operations + +sessinfo + Reports session info for the given sid, extended to RAC with gv$ + +top, top9i + Displays active sessions + + + + + diff -r 8ea39093ddf2 -r 701f0aae837a sqlpython/mysqlpy.py --- a/sqlpython/mysqlpy.py Thu Mar 19 13:14:39 2009 -0400 +++ b/sqlpython/mysqlpy.py Thu Mar 19 16:45:45 2009 -0400 @@ -123,7 +123,10 @@ f.close() def do_tselect(self, arg): - '''executes a query and prints the result in trasposed form. Useful when querying tables with many columns''' + ''' + Executes a query and prints the result in trasposed form; + equivalent to terminating query with `\\t` instead of `;`. + Useful when querying tables with many columns and few rows.''' self.do_select(self.parsed(arg, terminator='\\t')) def do_sql(self,args): diff -r 8ea39093ddf2 -r 701f0aae837a sqlpython/sqlpyPlus.py --- a/sqlpython/sqlpyPlus.py Thu Mar 19 13:14:39 2009 -0400 +++ b/sqlpython/sqlpyPlus.py Thu Mar 19 16:45:45 2009 -0400 @@ -387,7 +387,7 @@ def __init__(self): sqlpython.sqlpython.__init__(self) self.binds = CaselessDict() - self.settable += 'autobind commit_on_exit maxfetch maxtselctrows result_history_max_mbytes scan serveroutput sql_echo timeout heading wildsql'.split() + self.settable += 'autobind commit_on_exit maxfetch maxtselctrows scan serveroutput sql_echo store_results timeout heading wildsql'.split() self.settable.remove('case_insensitive') self.settable.sort() self.stdoutBeforeSpool = sys.stdout @@ -400,7 +400,7 @@ self.scan = True self.substvars = {} self.result_history = [] - self.result_history_max_mbytes = 10 + self.store_results = True self.pystate = {'r': [], 'binds': self.binds} # overrides cmd's parseline @@ -655,7 +655,7 @@ return 'null from dual' return result + ' ' + columnlist.remainder - def do_ampersand_substitution(self, raw, regexpr, isglobal): + def ampersand_substitution(self, raw, regexpr, isglobal): subst = regexpr.search(raw) while subst: fullexpr, var = subst.group(1), subst.group(2) @@ -679,16 +679,27 @@ singleampre = re.compile( '(&([a-zA-Z\d_$#]+))') def preparse(self, raw, **kwargs): if self.scan: - raw = self.do_ampersand_substitution(raw, regexpr=self.doubleampre, isglobal=True) + raw = self.ampersand_substitution(raw, regexpr=self.doubleampre, isglobal=True) if self.scan: - raw = self.do_ampersand_substitution(raw, regexpr=self.singleampre, isglobal=False) + raw = self.ampersand_substitution(raw, regexpr=self.singleampre, isglobal=False) return raw rowlimitPattern = pyparsing.Word(pyparsing.nums)('rowlimit') terminators = '; \\C \\t \\i \\p \\l \\L \\b '.split() + output_templates.keys() - def do_bind(self, arg): - self.pystate['r'][-1][-1].bind() + @options([make_option('-r', '--row', type="int", default=-1, + help='Bind row #ROW instead of final row (zero-based)')]) + def do_bind(self, arg=None, opts={}): + ''' + Inserts the results from the final row in the last completed SELECT statement + into bind variables with names corresponding to the column names. When the optional + `autobind` setting is on, this will be issued automatically after every query that + returns exactly one row. + ''' + try: + self.pystate['r'][-1][opts.row].bind() + except IndexError: + print self.do_bind.__doc__ def do_select(self, arg, bindVarsIn=None, terminator=None): """Fetch rows from a table. @@ -706,6 +717,8 @@ except ValueError: rowlimit = 0 print "Specify desired number of rows after terminator (not '%s')" % arg.parsed.suffix + if arg.parsed.terminator == '\\t': + rowlimit = rowlimit or self.maxtselctrows self.varsUsed = findBinds(arg, self.binds, bindVarsIn) if self.wildsql: selecttext = self.expandWildSql(arg) @@ -717,20 +730,20 @@ if self.rc > 0: resultset = ResultSet() resultset.colnames = [d[0].lower() for d in self.curs.description] + resultset.pystate = self.pystate resultset.statement = 'select ' + selecttext resultset.varsUsed = self.varsUsed - resultset.pystate = self.pystate resultset.extend([Result(r) for r in self.rows]) for row in resultset: row.resultset = resultset + self.pystate['r'].append(resultset) self.stdout.write('\n%s\n' % (self.output(arg.parsed.terminator, rowlimit))) - self.pystate['r'].append(resultset) if self.rc == 0: print '\nNo rows Selected.\n' elif self.rc == 1: print '\n1 row selected.\n' if self.autobind: - self.do_bind(None) + self.do_bind() elif self.rc < self.maxfetch: print '\n%d rows selected.\n' % self.rc else: @@ -1029,7 +1042,8 @@ self.stdout = self.spoolFile def do_write(self, args): - print 'Use (query) > outfilename instead.' + 'Obsolete command. Use (query) > outfilename instead.' + print self.do_write.__doc__ return def do_compare(self, args): @@ -1226,6 +1240,9 @@ lines.append(line) def do_begin(self, arg): + ''' + PL/SQL blocks can be used normally in sqlpython, though enclosing statements in + REMARK BEGIN... REMARK END statements can help with parsing speed.''' self.anon_plsql('begin ' + arg) def do_declare(self, arg): @@ -1275,6 +1292,10 @@ make_option('-t', '--timesort', action='store_true', help="Sort by last_ddl_time"), make_option('-r', '--reverse', action='store_true', help="Reverse order while sorting")]) def do_ls(self, arg, opts): + ''' + Lists objects as through they were in an {object_type}/{object_name} UNIX + directory structure. `*` and `%` may be used as wildcards. + ''' statement = '''SELECT object_type || '/' || %(objname)s AS name %(moreColumns)s FROM %(whose)s_objects %(where)s ORDER BY %(orderby)s;''' % self._ls_statement(arg, opts) @@ -1282,7 +1303,7 @@ @options([make_option('-i', '--ignore-case', dest='ignorecase', action='store_true', help='Case-insensitive search')]) def do_grep(self, arg, opts): - """grep PATTERN TABLE - search for term in any of TABLE's fields""" + """grep {target} {table} [{table2,...}] - search for {target} in any of {table}'s fields""" targetnames = arg.split() pattern = targetnames.pop(0)