annotate sqlpython/sqlpyPlus.py @ 370:388ee8fa5664

fixed raw SHOW bug
author catherine@cordelia
date Mon, 06 Jul 2009 09:03:55 -0400
parents c632618f461c
children e0750f7967d7
rev   line source
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1 """sqlpyPlus - extra features (inspired by Oracle SQL*Plus) for Luca Canali's sqlpython.py
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
2
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
3 Features include:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
4 - SQL*Plus-style bind variables
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
5 - `set autobind on` stores single-line result sets in bind variables automatically
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
6 - SQL buffer with list, run, ed, get, etc.; unlike SQL*Plus, buffer stores session's full history
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
7 - @script.sql loads and runs (like SQL*Plus)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
8 - ! runs operating-system command
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
9 - show and set to control sqlpython parameters
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
10 - SQL*Plus-style describe, spool
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
11 - write sends query result directly to file
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
12 - comments shows table and column comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
13 - compare ... to ... graphically compares results of two queries
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
14 - commands are case-insensitive
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
15 - context-sensitive tab-completion for table names, column names, etc.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
16
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
17 Use 'help' within sqlpython for details.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
18
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
19 Set bind variables the hard (SQL*Plus) way
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
20 exec :b = 3
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
21 or with a python-like shorthand
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
22 :b = 3
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
23
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
24 - catherinedevlin.blogspot.com May 31, 2006
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
25 """
366
39a88f53a03a saving pics as hashes
catherine@cordelia
parents: 364
diff changeset
26 import sys, os, re, sqlpython, cx_Oracle, pyparsing, re, completion, datetime, pickle, binascii, subprocess, time, itertools, hashlib
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
27 from cmd2 import Cmd, make_option, options, Statekeeper, Cmd2TestCase
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
28 from output_templates import output_templates
317
f200a222a936 beginning to set up metadata.py
Catherine Devlin <catherine.devlin@gmail.com>
parents: 315
diff changeset
29 from metadata import metaqueries
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
30 from plothandler import Plot
339
545f63b6ef42 supports bind variables in postgresql
Catherine Devlin <catherine.devlin@gmail.com>
parents: 338
diff changeset
31 from sqlpython import Parser
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
32 import imagedetect
359
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
33 import warnings
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
34 warnings.filterwarnings('ignore', 'BaseException.message', DeprecationWarning)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
35 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
36 import pylab
198
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 196
diff changeset
37 except (RuntimeError, ImportError):
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
38 pass
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
39
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
40 queries = {
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
41 'resolve': """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
42 SELECT object_type, object_name, owner FROM (
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
43 SELECT object_type, object_name, user AS owner, 1 priority
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
44 FROM user_objects
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
45 WHERE object_name = :objName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
46 UNION ALL
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
47 SELECT ao.object_type, ao.object_name, ao.owner, 2 priority
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
48 FROM all_objects ao
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
49 JOIN user_synonyms us ON (us.table_owner = ao.owner AND us.table_name = ao.object_name)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
50 WHERE us.synonym_name = :objName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
51 AND ao.object_type != 'SYNONYM'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
52 UNION ALL
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
53 SELECT ao.object_type, ao.object_name, ao.owner, 3 priority
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
54 FROM all_objects ao
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
55 JOIN all_synonyms asyn ON (asyn.table_owner = ao.owner AND asyn.table_name = ao.object_name)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
56 WHERE asyn.synonym_name = :objName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
57 AND ao.object_type != 'SYNONYM'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
58 AND asyn.owner = 'PUBLIC'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
59 UNION ALL
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
60 SELECT 'DIRECTORY' object_type, dir.directory_name, dir.owner, 6 priority
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
61 FROM all_directories dir
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
62 WHERE dir.directory_name = :objName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
63 UNION ALL
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
64 SELECT 'DATABASE LINK' object_type, db_link, owner, 7 priority
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
65 FROM all_db_links dbl
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
66 WHERE dbl.db_link = :objName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
67 ) ORDER BY priority ASC,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
68 length(object_type) ASC,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
69 object_type DESC""", # preference: PACKAGE before PACKAGE BODY, TABLE before INDEX
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
70 'tabComments': """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
71 SELECT comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
72 FROM all_tab_comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
73 WHERE owner = :owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
74 AND table_name = :table_name""",
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
75 'colComments': """
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
76 SELECT
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
77 atc.column_name,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
78 acc.comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
79 FROM all_tab_columns atc
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
80 JOIN all_col_comments acc ON (atc.owner = acc.owner and atc.table_name = acc.table_name and atc.column_name = acc.column_name)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
81 WHERE atc.table_name = :object_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
82 AND atc.owner = :owner
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
83 ORDER BY atc.column_id;""",
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
84 'oneColComments': """
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
85 SELECTatc.column_name,
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
86 acc.comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
87 FROM all_tab_columns atc
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
88 JOIN all_col_comments acc ON (atc.owner = acc.owner and atc.table_name = acc.table_name and atc.column_name = acc.column_name)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
89 WHERE atc.table_name = :object_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
90 AND atc.owner = :owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
91 AND acc.column_name = :column_name
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
92 ORDER BY atc.column_id;""",
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
93 #thanks to Senora.pm for "refs"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
94 'refs': """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
95 NULL referenced_by,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
96 c2.table_name references,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
97 c1.constraint_name constraint
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
98 FROM
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
99 user_constraints c1,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
100 user_constraints c2
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
101 WHERE
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
102 c1.table_name = :object_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
103 and c1.constraint_type ='R'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
104 and c1.r_constraint_name = c2.constraint_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
105 and c1.r_owner = c2.owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
106 and c1.owner = :owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
107 UNION
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
108 SELECT c1.table_name referenced_by,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
109 NULL references,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
110 c1.constraint_name constraint
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
111 FROM
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
112 user_constraints c1,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
113 user_constraints c2
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
114 WHERE
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
115 c2.table_name = :object_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
116 and c1.constraint_type ='R'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
117 and c1.r_constraint_name = c2.constraint_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
118 and c1.r_owner = c2.owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
119 and c1.owner = :owner
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
120 """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
121 }
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
122
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
123 class SoftwareSearcher(object):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
124 def __init__(self, softwareList, purpose):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
125 self.softwareList = softwareList
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
126 self.purpose = purpose
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
127 self.software = None
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
128 def invoke(self, *args):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
129 if not self.software:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
130 (self.software, self.invokeString) = self.find()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
131 argTuple = tuple([self.software] + list(args))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
132 os.system(self.invokeString % argTuple)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
133 def find(self):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
134 if self.purpose == 'text editor':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
135 software = os.environ.get('EDITOR')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
136 if software:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
137 return (software, '%s %s')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
138 for (n, (software, invokeString)) in enumerate(self.softwareList):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
139 if os.path.exists(software):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
140 if n > (len(self.softwareList) * 0.7):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
141 print """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
142
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
143 Using %s. Note that there are better options available for %s,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
144 but %s couldn't find a better one in your PATH.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
145 Feel free to open up %s
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
146 and customize it to find your favorite %s program.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
147
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
148 """ % (software, self.purpose, __file__, __file__, self.purpose)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
149 return (software, invokeString)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
150 stem = os.path.split(software)[1]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
151 for p in os.environ['PATH'].split(os.pathsep):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
152 if os.path.exists(os.sep.join([p, stem])):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
153 return (stem, invokeString)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
154 raise (OSError, """Could not find any %s programs. You will need to install one,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
155 or customize %s to make it aware of yours.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
156 Looked for these programs:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
157 %s""" % (self.purpose, __file__, "\n".join([s[0] for s in self.softwareList])))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
158
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
159 softwareLists = {
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
160 'diff/merge': [
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
161 ('/usr/bin/meld',"%s %s %s"),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
162 ('/usr/bin/kdiff3',"%s %s %s"),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
163 (r'C:\Program Files\Araxis\Araxis Merge v6.5\Merge.exe','"%s" %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
164 (r'C:\Program Files\TortoiseSVN\bin\TortoiseMerge.exe', '"%s" /base:"%s" /mine:"%s"'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
165 ('FileMerge','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
166 ('kompare','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
167 ('WinMerge','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
168 ('xxdiff','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
169 ('fldiff','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
170 ('gtkdiff','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
171 ('tkdiff','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
172 ('gvimdiff','%s %s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
173 ('diff',"%s %s %s"),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
174 (r'c:\windows\system32\comp.exe',"%s %s %s")],
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
175 'text editor': [
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
176 ('gedit', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
177 ('textpad', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
178 ('notepad.exe', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
179 ('pico', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
180 ('emacs', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
181 ('vim', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
182 ('vi', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
183 ('ed', '%s %s'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
184 ('edlin', '%s %s')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
185 ]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
186 }
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
187
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
188 diffMergeSearcher = SoftwareSearcher(softwareLists['diff/merge'],'diff/merge')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
189 editSearcher = SoftwareSearcher(softwareLists['text editor'], 'text editor')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
190 editor = os.environ.get('EDITOR')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
191 if editor:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
192 editSearcher.find = lambda: (editor, "%s %s")
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
193
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
194 class CaselessDict(dict):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
195 """dict with case-insensitive keys.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
196
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
197 Posted to ASPN Python Cookbook by Jeff Donner - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66315"""
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
198 def __init__(self, other=None):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
199 if other:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
200 # Doesn't do keyword args
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
201 if isinstance(other, dict):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
202 for k,v in other.items():
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
203 dict.__setitem__(self, k.lower(), v)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
204 else:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
205 for k,v in other:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
206 dict.__setitem__(self, k.lower(), v)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
207 def __getitem__(self, key):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
208 return dict.__getitem__(self, key.lower())
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
209 def __setitem__(self, key, value):
273
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
210 try:
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
211 key = key.lower()
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
212 except AttributeError:
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
213 pass
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
214 dict.__setitem__(self, key, value)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
215 def __contains__(self, key):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
216 return dict.__contains__(self, key.lower())
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
217 def has_key(self, key):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
218 return dict.has_key(self, key.lower())
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
219 def get(self, key, def_val=None):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
220 return dict.get(self, key.lower(), def_val)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
221 def setdefault(self, key, def_val=None):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
222 return dict.setdefault(self, key.lower(), def_val)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
223 def update(self, other):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
224 for k,v in other.items():
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
225 dict.__setitem__(self, k.lower(), v)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
226 def fromkeys(self, iterable, value=None):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
227 d = CaselessDict()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
228 for k in iterable:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
229 dict.__setitem__(d, k.lower(), value)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
230 return d
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
231 def pop(self, key, def_val=None):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
232 return dict.pop(self, key.lower(), def_val)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
233
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
234 class ResultSet(list):
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
235 pass
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
236
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
237 class Result(tuple):
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
238 def __str__(self):
272
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
239 return '\n'.join('%s: %s' % (colname, self[idx])
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
240 for (idx, colname) in enumerate(self.resultset.colnames))
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
241 def __getattr__(self, attr):
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
242 attr = attr.lower()
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
243 try:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
244 return self[self.resultset.colnames.index(attr)]
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
245 except ValueError:
307
e804c08292b3 several bugs out
catherine@dellzilla
parents: 306
diff changeset
246 if attr in ('colnames', 'statement', 'bindvars', 'resultset'):
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
247 return getattr(self.resultset, attr)
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
248 else:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
249 raise AttributeError, "available columns are: " + ", ".join(self.resultset.colnames)
273
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
250 def bind(self):
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
251 for (idx, colname) in enumerate(self.resultset.colnames):
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
252 self.resultset.pystate['binds'][colname] = self[idx]
277
6ffe31149306 now passing tests
catherine@Elli.myhome.westell.com
parents: 275
diff changeset
253 self.resultset.pystate['binds'][str(idx+1)] = self[idx]
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
254
288
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
255 def centeredSlice(lst, center=0, width=1):
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
256 width = max(width, -1)
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
257 if center < 0:
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
258 end = center + width + 1
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
259 if end >= 0:
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
260 end = None
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
261 return lst[center-width:end]
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
262 else:
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
263 return lst[max(center-width,0):center+width+1]
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
264
360
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
265
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
266 def offset_to_line(instring, offset):
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
267 r"""
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
268 >>> offset_to_line('abcdefghijkl', 5)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
269 (0, 'abcdefghijkl', 5)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
270 >>> offset_to_line('ab\ncd\nefg', 6)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
271 (2, 'efg', 0)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
272 >>> offset_to_line('ab\ncd\nefg', 5)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
273 (1, 'cd\n', 2)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
274 >>> offset_to_line('abcdefghi\njkl', 5)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
275 (0, 'abcdefghi\n', 5)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
276 >>> offset_to_line('abcdefghi\njkl', 700)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
277
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
278 """
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
279 lineNum = 0
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
280 for line in instring.splitlines(True):
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
281 if offset < len(line):
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
282 return lineNum, line, offset
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
283 lineNum += 1
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
284 offset -= len(line)
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
285
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
286 class BlobDisplayer(object):
366
39a88f53a03a saving pics as hashes
catherine@cordelia
parents: 364
diff changeset
287 folder_name = 'sqlpython_blob_store'
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
288 imgwidth = 400
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
289 def folder_ok(self):
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
290 if not os.access(self.folder_name, os.F_OK):
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
291 try:
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
292 os.mkdir(self.folder_name)
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
293 readme = open(os.path.join(self.folder_name, 'README.txt'),'w')
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
294 readme.write('''
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
295 Temporary files for display of BLOBs from within
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
296 sqlpython. Delete when sqlpython is closed.''')
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
297 readme.close()
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
298 except:
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
299 return False
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
300 return True
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
301 def __init__(self, blob, under_limit):
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
302 self.url = ''
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
303 if under_limit:
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
304 self.blob = blob.read()
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
305 self.hashed = hashlib.md5(self.blob).hexdigest()
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
306 self.extension = imagedetect.extension_from_data(self.blob)
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
307 if self.folder_ok():
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
308 self.file_name = '%s/%s%s' % (
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
309 os.path.join(os.getcwd(), self.folder_name),
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
310 self.hashed, self.extension)
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
311 self.url = 'file://%s' % self.file_name
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
312 if not os.access(self.file_name, os.F_OK):
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
313 outfile = open(self.file_name, 'wb')
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
314 outfile.write(self.blob)
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
315 outfile.close()
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
316 def __str__(self):
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
317 if self.url:
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
318 return '(BLOB at %s)' % self.url
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
319 else:
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
320 return '(BLOB)'
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
321 def html(self):
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
322 if self.url:
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
323 return '<a href="%s"><img src="%s" width="%d" /></a>' % (
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
324 self.url, self.url, self.imgwidth)
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
325 else:
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
326 return '(BLOB not saved, check bloblimit)'
360
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
327
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
328 class sqlpyPlus(sqlpython.sqlpython):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
329 defaultExtension = 'sql'
289
3cade02da892 replacing manual abbreviations with abbrev param
catherine@Elli.myhome.westell.com
parents: 285
diff changeset
330 abbrev = True
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
331 sqlpython.sqlpython.shortcuts.update({':': 'setbind',
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
332 '\\': 'psql',
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
333 '@': 'get'})
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
334 multilineCommands = '''select insert update delete tselect
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
335 create drop alter _multiline_comment'''.split()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
336 sqlpython.sqlpython.noSpecialParse.append('spool')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
337 commentGrammars = pyparsing.Or([pyparsing.Literal('--') + pyparsing.restOfLine, pyparsing.cStyleComment])
246
b5d4a122354a can round-trip a package now
catherine@dellzilla
parents: 245
diff changeset
338 commentGrammars = pyparsing.Or([Parser.comment_def, pyparsing.cStyleComment])
259
c0847a4c7f49 one-shot connection changes
catherine@Elli.myhome.westell.com
parents: 257
diff changeset
339 prefixParser = pyparsing.Optional(pyparsing.Word(pyparsing.nums)('connection_number')
c0847a4c7f49 one-shot connection changes
catherine@Elli.myhome.westell.com
parents: 257
diff changeset
340 + ':')
309
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
341 reserved_words = [
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
342 'alter', 'begin', 'comment', 'create', 'delete', 'drop', 'end', 'for', 'grant',
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
343 'insert', 'intersect', 'lock', 'minus', 'on', 'order', 'rename',
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
344 'resource', 'revoke', 'select', 'share', 'start', 'union', 'update',
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
345 'where', 'with']
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
346 default_file_name = 'afiedt.buf'
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
347 def __init__(self):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
348 sqlpython.sqlpython.__init__(self)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
349 self.binds = CaselessDict()
370
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
350 self.settable += 'autobind bloblimit colors commit_on_exit maxfetch maxtselctrows rows_remembered scan serveroutput sql_echo timeout heading wildsql version'.split()
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
351 self.settable.remove('case_insensitive')
230
e1e6b820f81b improving ambiguous SETs
catherine@dellzilla
parents: 229
diff changeset
352 self.settable.sort()
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
353 self.stdoutBeforeSpool = sys.stdout
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
354 self.sql_echo = False
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
355 self.spoolFile = None
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
356 self.autobind = False
229
411f78dc1e07 accept SET HEADING
catherine@dellzilla
parents: 228
diff changeset
357 self.heading = True
240
6d9a65b442b5 negative wildcards fixed
catherine@Elli.myhome.westell.com
parents: 239
diff changeset
358 self.wildsql = False
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
359 self.serveroutput = True
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
360 self.scan = True
292
d727f209acf9 py really working right now
catherine@dellzilla
parents: 291
diff changeset
361 self.nonpythoncommand = 'sql'
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
362 self.substvars = {}
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
363 self.result_history = []
330
8dd71d47f3cb merged with rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 329 328
diff changeset
364 self.rows_remembered = 10000
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
365 self.bloblimit = 5
370
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
366 self.version = 'SQLPython %s' % sqlpython.__version__
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
367 self.pystate = {'r': [], 'binds': self.binds, 'substs': self.substvars}
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
368
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
369 # overrides cmd's parseline
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
370 def parseline(self, line):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
371 """Parse the line into a command name and a string containing
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
372 the arguments. Returns a tuple containing (command, args, line).
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
373 'command' and 'args' may be None if the line couldn't be parsed.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
374 Overrides cmd.cmd.parseline to accept variety of shortcuts.."""
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
375
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
376 cmd, arg, line = sqlpython.sqlpython.parseline(self, line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
377 if cmd in ('select', 'sleect', 'insert', 'update', 'delete', 'describe',
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
378 'desc', 'comments', 'pull', 'refs', 'desc', 'triggers', 'find') \
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
379 and not hasattr(self, 'curs'):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
380 self.perror('Not connected.')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
381 return '', '', ''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
382 return cmd, arg, line
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
383
359
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
384 def perror(self, err, statement=None):
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
385 try:
360
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
386 linenum, line, offset = offset_to_line(statement.parsed.raw, err.message.offset)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
387 print line.strip()
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
388 print '%s*' % (' ' * offset)
692ce3ee80d2 error location reporting working
catherine@cordelia
parents: 359
diff changeset
389 print 'ERROR at line %d:' % (linenum + 1)
359
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
390 except AttributeError:
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
391 pass
f42f92dc7464 silencing baseexception warnings
catherine@cordelia
parents: 357
diff changeset
392 print str(err)
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
393 def dbms_output(self):
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
394 "Dumps contents of Oracle's DBMS_OUTPUT buffer (where PUT_LINE goes)"
261
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
395 try:
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
396 line = self.curs.var(cx_Oracle.STRING)
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
397 status = self.curs.var(cx_Oracle.NUMBER)
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
398 self.curs.callproc('dbms_output.get_line', [line, status])
261
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
399 while not status.getvalue():
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
400 self.poutput(line.getvalue())
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
401 self.poutput('\n')
261
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
402 self.curs.callproc('dbms_output.get_line', [line, status])
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
403 except AttributeError:
0044cfa5867a disconnections worked out
catherine@dellzilla
parents: 259
diff changeset
404 pass
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
405
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
406 def postcmd(self, stop, line):
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
407 """Hook method executed just after a command dispatch is finished."""
317
f200a222a936 beginning to set up metadata.py
Catherine Devlin <catherine.devlin@gmail.com>
parents: 315
diff changeset
408 if (self.rdbms == 'oracle') and self.serveroutput:
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
409 self.dbms_output()
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
410 return stop
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
411
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
412 def do_remark(self, line):
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
413 '''
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
414 REMARK is one way to denote a comment in SQL*Plus.
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
415
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
416 Wrapping a *single* SQL or PL/SQL statement in `REMARK BEGIN` and `REMARK END`
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
417 tells sqlpython to submit the enclosed code directly to Oracle as a single
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
418 unit of code.
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
419
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
420 Without these markers, sqlpython fails to properly distinguish the beginning
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
421 and end of all but the simplest PL/SQL blocks, causing errors. sqlpython also
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
422 slows down when parsing long SQL statements as it tries to determine whether
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
423 the statement has ended yet; `REMARK BEGIN` and `REMARK END` allow it to skip this
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
424 parsing.
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
425
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
426 Standard SQL*Plus interprets REMARK BEGIN and REMARK END as comments, so it is
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
427 safe to include them in SQL*Plus scripts.
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
428 '''
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
429 if not line.lower().strip().startswith('begin'):
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
430 return
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
431 statement = []
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
432 next = self.pseudo_raw_input(self.continuation_prompt)
245
05c90f80815c trying REMARK BEGIN / REMARK END
catherine@Elli.myhome.westell.com
parents: 244
diff changeset
433 while next.lower().split()[:2] != ['remark','end']:
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
434 statement.append(next)
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
435 next = self.pseudo_raw_input(self.continuation_prompt)
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
436 return self.onecmd('\n'.join(statement))
272
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
437
292
d727f209acf9 py really working right now
catherine@dellzilla
parents: 291
diff changeset
438 def do_py(self, arg):
272
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
439 '''
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
440 py <command>: Executes a Python command.
297
f4e8919c5cdf adjust docstring for windows
catherine@dellzilla
parents: 296
diff changeset
441 py: Enters interactive Python mode.
f4e8919c5cdf adjust docstring for windows
catherine@dellzilla
parents: 296
diff changeset
442 End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, 'exit()`.
292
d727f209acf9 py really working right now
catherine@dellzilla
parents: 291
diff changeset
443 Past SELECT results are exposed as list `r`;
275
df78546969c9 spacing change in py doc
catherine@Elli.myhome.westell.com
parents: 274
diff changeset
444 most recent resultset is `r[-1]`.
292
d727f209acf9 py really working right now
catherine@dellzilla
parents: 291
diff changeset
445 SQL bind, substitution variables are exposed as `binds`, `substs`.
296
ba5d5483e0db shortened docstring to avoid word wrap
catherine@dellzilla
parents: 293
diff changeset
446 SQL and sqlpython commands can be issued with `sql("your command")`.
272
fee766daa57b yay py works fully
catherine@Elli.myhome.westell.com
parents: 271
diff changeset
447 '''
292
d727f209acf9 py really working right now
catherine@dellzilla
parents: 291
diff changeset
448 return Cmd.do_py(self, arg)
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
449
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
450 def do_get(self, args):
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
451 """
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
452 `get {script.sql}` or `@{script.sql}` runs the command(s) in {script.sql}.
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
453 If additional arguments are supplied, they are assigned to &1, &2, etc.
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
454 """
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
455 fname, args = args.split()[0], args.split()[1:]
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
456 for (idx, arg) in enumerate(args):
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
457 self.substvars[str(idx+1)] = arg
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
458 return Cmd.do__load(self, fname)
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
459
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
460 def onecmd_plus_hooks(self, line):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
461 line = self.precmd(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
462 stop = self.onecmd(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
463 stop = self.postcmd(stop, line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
464
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
465 def _onchange_serveroutput(self, old, new):
317
f200a222a936 beginning to set up metadata.py
Catherine Devlin <catherine.devlin@gmail.com>
parents: 315
diff changeset
466 if (self.rdbms == 'oracle'):
315
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
467 if new:
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
468 self.curs.callproc('dbms_output.enable', [])
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
469 else:
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
470 self.curs.callproc('dbms_output.disable', [])
257
6d4d90fb2082 dbms_output.put_line working
catherine@Elli.myhome.westell.com
parents: 254
diff changeset
471
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
472 def do_shortcuts(self,arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
473 """Lists available first-character shortcuts
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
474 (i.e. '!dir' is equivalent to 'shell dir')"""
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
475 for (scchar, scto) in self.shortcuts:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
476 self.poutput('%s: %s' % (scchar, scto))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
477
254
b61e21386383 oops, restore lines of code after sql_format_item
catherine@Elli.myhome.westell.com
parents: 253
diff changeset
478 tableNameFinder = re.compile(r'from\s+([\w$#_"]+)', re.IGNORECASE | re.MULTILINE | re.DOTALL)
322
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
479 def formattedForSql(self, datum):
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
480 if datum is None:
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
481 return 'NULL'
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
482 elif isinstance(datum, basestring):
334
1e199ea5b846 fixed single-quote inclusion
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
483 return "'%s'" % datum.replace("'","''")
322
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
484 try:
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
485 return datum.strftime("TO_DATE('%Y-%m-%d %H:%M:%S', 'YYYY-MM-DD HH24:MI:SS')")
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
486 except AttributeError:
334
1e199ea5b846 fixed single-quote inclusion
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
487 return str(datum)
322
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
488
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
489 def output(self, outformat, rowlimit):
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
490 try:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
491 self.tblname = self.tableNameFinder.search(self.querytext).group(1)
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
492 except AttributeError:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
493 self.tblname = ''
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
494 self.colnames = [d[0] for d in self.curs.description]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
495 if outformat in output_templates:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
496 self.colnamelen = max(len(colname) for colname in self.colnames)
322
d791333902f7 handle NULLs and apostrophes in \i inserts
Catherine Devlin <catherine.devlin@gmail.com>
parents: 318
diff changeset
497 result = output_templates[outformat].generate(formattedForSql=self.formattedForSql, **self.__dict__)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
498 elif outformat == '\\t': # transposed
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
499 rows = [self.colnames]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
500 rows.extend(list(self.rows))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
501 transpr = [[rows[y][x] for y in range(len(rows))]for x in range(len(rows[0]))] # matrix transpose
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
502 newdesc = [['ROW N.'+str(y),10] for y in range(len(rows))]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
503 for x in range(len(self.curs.description)):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
504 if str(self.curs.description[x][1]) == "<type 'cx_Oracle.BINARY'>": # handles RAW columns
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
505 rname = transpr[x][0]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
506 transpr[x] = map(binascii.b2a_hex, transpr[x])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
507 transpr[x][0] = rname
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
508 newdesc[0][0] = 'COLUMN NAME'
337
Catherine Devlin <catherine.devlin@gmail.com>
parents: 333
diff changeset
509 result = '\n' + self.pmatrix(transpr,newdesc)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
510 elif outformat in ('\\l', '\\L', '\\p', '\\b'):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
511 plot = Plot()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
512 plot.build(self, outformat)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
513 plot.shelve()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
514 plot.draw()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
515 return ''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
516 else:
337
Catherine Devlin <catherine.devlin@gmail.com>
parents: 333
diff changeset
517 result = self.pmatrix(self.rows, self.curs.description,
Catherine Devlin <catherine.devlin@gmail.com>
parents: 333
diff changeset
518 self.maxfetch, heading=self.heading,
Catherine Devlin <catherine.devlin@gmail.com>
parents: 333
diff changeset
519 restructuredtext = (outformat == '\\r'))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
520 return result
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
521
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
522 legalOracle = re.compile('[a-zA-Z_$#]')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
523
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
524 def select_scalar_list(self, sql, binds={}):
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
525 self._execute(sql, binds)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
526 return [r[0] for r in self.curs.fetchall()]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
527
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
528 columnNameRegex = re.compile(
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
529 r'select\s+(.*)from',
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
530 re.IGNORECASE | re.DOTALL | re.MULTILINE)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
531 def completedefault(self, text, line, begidx, endidx):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
532 segment = completion.whichSegment(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
533 text = text.upper()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
534 completions = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
535 if segment == 'select':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
536 stmt = "SELECT column_name FROM user_tab_columns WHERE column_name LIKE '%s%%'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
537 completions = self.select_scalar_list(stmt % (text))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
538 if not completions:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
539 stmt = "SELECT column_name FROM all_tab_columns WHERE column_name LIKE '%s%%'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
540 completions = self.select_scalar_list(stmt % (text))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
541 if segment == 'from':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
542 columnNames = self.columnNameRegex.search(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
543 if columnNames:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
544 columnNames = columnNames.group(1)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
545 columnNames = [c.strip().upper() for c in columnNames.split(',')]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
546 stmt1 = "SELECT table_name FROM all_tab_columns WHERE column_name = '%s' AND table_name LIKE '%s%%'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
547 for columnName in columnNames:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
548 # and if columnName is * ?
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
549 completions.extend(self.select_scalar_list(stmt1 % (columnName, text)))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
550 if segment in ('from', 'update', 'insert into') and (not completions):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
551 stmt = "SELECT table_name FROM user_tables WHERE table_name LIKE '%s%%'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
552 completions = self.select_scalar_list(stmt % (text))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
553 if not completions:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
554 stmt = """SELECT table_name FROM user_tables WHERE table_name LIKE '%s%%'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
555 UNION
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
556 SELECT DISTINCT owner FROM all_tables WHERE owner LIKE '%%%s'"""
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
557 completions = self.select_scalar_list(stmt % (text, text))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
558 if segment in ('where', 'group by', 'order by', 'having', 'set'):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
559 tableNames = completion.tableNamesFromFromClause(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
560 if tableNames:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
561 stmt = """SELECT column_name FROM all_tab_columns
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
562 WHERE table_name IN (%s)""" % \
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
563 (','.join("'%s'" % (t) for t in tableNames))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
564 stmt = "%s AND column_name LIKE '%s%%'" % (stmt, text)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
565 completions = self.select_scalar_list(stmt)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
566 if not segment:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
567 stmt = "SELECT object_name FROM all_objects WHERE object_name LIKE '%s%%'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
568 completions = self.select_scalar_list(stmt % (text))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
569 return completions
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
570
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
571 columnlistPattern = pyparsing.SkipTo(pyparsing.CaselessKeyword('from'))('columns') + \
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
572 pyparsing.SkipTo(pyparsing.stringEnd)('remainder')
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
573
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
574 negator = pyparsing.Literal('!')('exclude')
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
575 colNumber = pyparsing.Optional(negator) + pyparsing.Literal('#') + pyparsing.Word('-' + pyparsing.nums, pyparsing.nums)('column_number')
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
576 colName = negator + pyparsing.Word('$_#' + pyparsing.alphas, '$_#' + pyparsing.alphanums)('column_name')
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
577 wildColName = pyparsing.Optional(negator) + pyparsing.Word('?*%$_#' + pyparsing.alphas, '?*%$_#' + pyparsing.alphanums, min=2)('column_name')
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
578 colNumber.ignore(pyparsing.cStyleComment).ignore(Parser.comment_def). \
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
579 ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString)
235
8e5f58d504d4 tightening up wildcard pyparsing
catherine@dellzilla
parents: 234
diff changeset
580 wildSqlParser = colNumber ^ colName ^ wildColName
8e5f58d504d4 tightening up wildcard pyparsing
catherine@dellzilla
parents: 234
diff changeset
581 wildSqlParser.ignore(pyparsing.cStyleComment).ignore(Parser.comment_def). \
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
582 ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
583 emptyCommaRegex = re.compile(',\s*,', re.DOTALL)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
584 deadStarterCommaRegex = re.compile('^\s*,', re.DOTALL)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
585 deadEnderCommaRegex = re.compile(',\s*$', re.DOTALL)
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
586 def expandWildSql(self, arg):
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
587 try:
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
588 columnlist = self.columnlistPattern.parseString(arg)
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
589 except pyparsing.ParseException:
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
590 return arg
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
591 parseresults = list(self.wildSqlParser.scanString(columnlist.columns))
239
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
592 # I would rather exclude non-wild column names in the grammar,
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
593 # but can't figure out how
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
594 parseresults = [p for p in parseresults if
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
595 p[0].column_number or
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
596 '*' in p[0].column_name or
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
597 '%' in p[0].column_name or
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
598 '?' in p[0].column_name or
239
4c563c2218e6 catching standard names caught
catherine@Elli.myhome.westell.com
parents: 238
diff changeset
599 p[0].exclude]
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
600 if not parseresults:
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
601 return arg
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
602 self.curs.execute('select * ' + columnlist.remainder, self.varsUsed)
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
603 columns_available = [d[0] for d in self.curs.description]
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
604 replacers = {}
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
605 included = set()
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
606 excluded = set()
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
607 for (col, startpos, endpos) in parseresults:
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
608 replacers[arg[startpos:endpos]] = []
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
609 if col.column_name:
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
610 finder = col.column_name.replace('*','.*')
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
611 finder = finder.replace('%','.*')
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
612 finder = finder.replace('?','.')
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
613 colnames = [c for c in columns_available if re.match(finder + '$', c, re.IGNORECASE)]
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
614 elif col.column_number:
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
615 idx = int(col.column_number)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
616 if idx > 0:
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
617 idx -= 1
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
618 colnames = [columns_available[idx]]
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
619 if not colnames:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
620 self.pfeedback('No columns found matching criteria.')
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
621 return 'null from dual'
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
622 for colname in colnames:
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
623 if col.exclude:
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
624 included.discard(colname)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
625 include_here = columns_available[:]
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
626 include_here.remove(colname)
240
6d9a65b442b5 negative wildcards fixed
catherine@Elli.myhome.westell.com
parents: 239
diff changeset
627 replacers[arg[startpos:endpos]].extend(i for i in include_here if i not in replacers[arg[startpos:endpos]])
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
628 excluded.add(colname)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
629 else:
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
630 excluded.discard(colname)
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
631 replacers[arg[startpos:endpos]].append(colname)
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
632
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
633 replacers = sorted(replacers.items(), key=len, reverse=True)
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
634 result = columnlist.columns
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
635 for (target, replacement) in replacers:
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
636 cols = [r for r in replacement if r not in excluded and r not in included]
238
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
637 replacement = ', '.join(cols)
254fb9d3f4c3 must fix catching regular cols as wilds, repeating on eqdbw/mtndew@orcl
catherine@Elli.myhome.westell.com
parents: 237
diff changeset
638 included.update(cols)
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
639 result = result.replace(target, replacement)
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
640 # some column names could get wiped out completely, so we fix their dangling commas
236
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
641 result = self.emptyCommaRegex.sub(',', result)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
642 result = self.deadStarterCommaRegex.sub('', result)
7f999b141fcd debugging streamlined wild sql
catherine@dellzilla
parents: 235
diff changeset
643 result = self.deadEnderCommaRegex.sub('', result)
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
644 if not result.strip():
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
645 self.pfeedback('No columns found matching criteria.')
242
8866fe0706c3 message when all columns excluded
catherine@dellzilla
parents: 241
diff changeset
646 return 'null from dual'
237
95070e01907d not col num works
catherine@Elli.myhome.westell.com
parents: 236
diff changeset
647 return result + ' ' + columnlist.remainder
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
648
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
649 do_prompt = Cmd.poutput
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
650
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
651 def do_accept(self, args):
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
652 try:
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
653 prompt = args[args.lower().index('prompt ')+7:]
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
654 except ValueError:
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
655 prompt = ''
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
656 varname = args.lower().split()[0]
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
657 self.substvars[varname] = self.pseudo_raw_input(prompt)
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
658
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
659 def ampersand_substitution(self, raw, regexpr, isglobal):
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
660 subst = regexpr.search(raw)
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
661 while subst:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
662 fullexpr, var = subst.group(1), subst.group(2)
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
663 self.pfeedback('Substitution variable %s found in:' % fullexpr)
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
664 self.pfeedback(raw[max(subst.start()-20, 0):subst.end()+20])
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
665 if var in self.substvars:
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
666 val = self.substvars[var]
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
667 else:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
668 val = raw_input('Substitution for %s (SET SCAN OFF to halt substitution): ' % fullexpr)
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
669 if val.lower().split() == ['set','scan','off']:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
670 self.scan = False
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
671 return raw
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
672 if isglobal:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
673 self.substvars[var] = val
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
674 raw = raw.replace(fullexpr, val)
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
675 self.pfeedback('Substituted %s for %s' % (val, fullexpr))
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
676 subst = regexpr.search(raw) # do not FINDALL b/c we don't want to ask twice
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
677 return raw
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
678
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
679 numericampre = re.compile('(&(\d+))')
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
680 doubleampre = re.compile('(&&([a-zA-Z\d_$#]+))', re.IGNORECASE)
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
681 singleampre = re.compile( '(&([a-zA-Z\d_$#]+))', re.IGNORECASE)
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
682 def preparse(self, raw, **kwargs):
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
683 if self.scan:
284
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
684 raw = self.ampersand_substitution(raw, regexpr=self.numericampre, isglobal=False)
ad20675a17f7 working on adding accept, prompt
catherine@dellzilla
parents: 281
diff changeset
685 if self.scan:
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
686 raw = self.ampersand_substitution(raw, regexpr=self.doubleampre, isglobal=True)
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
687 if self.scan:
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
688 raw = self.ampersand_substitution(raw, regexpr=self.singleampre, isglobal=False)
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
689 return raw
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
690
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
691 rowlimitPattern = pyparsing.Word(pyparsing.nums)('rowlimit')
308
4d24fea42364 py scripts working again
catherine@Elli.myhome.westell.com
parents: 307
diff changeset
692 terminators = '; \\C \\t \\i \\p \\l \\L \\b \\r'.split() + output_templates.keys()
199
09592342a33d ugh - parsing stripping command causes real trouble
catherine@dellzilla
parents: 198
diff changeset
693
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
694 @options([make_option('-r', '--row', type="int", default=-1,
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
695 help='Bind row #ROW instead of final row (zero-based)')])
314
0473ad96ddb7 transcript tests work
catherine@Elli.myhome.westell.com
parents: 313
diff changeset
696 def do_bind(self, arg, opts):
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
697 '''
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
698 Inserts the results from the final row in the last completed SELECT statement
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
699 into bind variables with names corresponding to the column names. When the optional
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
700 `autobind` setting is on, this will be issued automatically after every query that
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
701 returns exactly one row.
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
702 '''
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
703 try:
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
704 self.pystate['r'][-1][opts.row].bind()
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
705 except IndexError:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
706 self.poutput(self.do_bind.__doc__)
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
707
327
7cc5cc19891f added rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 326
diff changeset
708 def age_out_resultsets(self):
7cc5cc19891f added rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 326
diff changeset
709 total_len = sum(len(rs) for rs in self.pystate['r'])
328
b2fbb9de8845 avoid infinite loop when r[-1] > rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 327
diff changeset
710 for (i, rset) in enumerate(self.pystate['r'][:-1]):
b2fbb9de8845 avoid infinite loop when r[-1] > rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 327
diff changeset
711 if total_len <= self.rows_remembered:
b2fbb9de8845 avoid infinite loop when r[-1] > rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 327
diff changeset
712 return
b2fbb9de8845 avoid infinite loop when r[-1] > rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 327
diff changeset
713 total_len -= len(rset)
b2fbb9de8845 avoid infinite loop when r[-1] > rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 327
diff changeset
714 self.pystate['r'][i] = []
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
715
192
6bb8a112af6b accept special terminators on most anything
catherine@dellzilla
parents: 191
diff changeset
716 def do_select(self, arg, bindVarsIn=None, terminator=None):
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
717 """Fetch rows from a table.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
718
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
719 Limit the number of rows retrieved by appending
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
720 an integer after the terminator
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
721 (example: SELECT * FROM mytable;10 )
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
722
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
723 Output may be formatted by choosing an alternative terminator
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
724 ("help terminators" for details)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
725 """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
726 bindVarsIn = bindVarsIn or {}
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
727 try:
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
728 rowlimit = int(arg.parsed.suffix or 0)
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
729 except ValueError:
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
730 rowlimit = 0
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
731 self.perror("Specify desired number of rows after terminator (not '%s')" % arg.parsed.suffix)
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
732 if arg.parsed.terminator == '\\t':
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
733 rowlimit = rowlimit or self.maxtselctrows
340
001d01eeac90 bind vars for postgres
Catherine Devlin <catherine.devlin@gmail.com>
parents: 339
diff changeset
734 self.varsUsed = self.findBinds(arg, bindVarsIn)
233
dc7683970717 beginning wildsql
catherine@Elli.myhome.westell.com
parents: 232
diff changeset
735 if self.wildsql:
234
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
736 selecttext = self.expandWildSql(arg)
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
737 else:
a86efbca3da9 ha ha ha - wildcards in selects working now
catherine@dellzilla
parents: 233
diff changeset
738 selecttext = arg
315
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
739 self.querytext = 'select ' + selecttext
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
740 if self.varsUsed:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
741 self.curs.execute(self.querytext, self.varsUsed)
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
742 else: # this is an ugly workaround for the evil paramstyle curse upon DB-API2
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
743 self.curs.execute(self.querytext)
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
744 self.rows = self.curs.fetchmany(min(self.maxfetch, (rowlimit or self.maxfetch)))
364
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
745 self.coltypes = [d[1] for d in self.curs.description]
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
746 if cx_Oracle.BLOB in self.coltypes:
ea6d35cb6c73 images work, except brackets get escaped
catherine@cordelia
parents: 361
diff changeset
747 self.rows = [
367
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
748 [( (coltype == cx_Oracle.BLOB)
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
749 and BlobDisplayer(datum, (rownum < self.bloblimit)))
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
750 or datum
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
751 for (datum, coltype) in zip(row, self.coltypes)]
c632618f461c bloblimit implemented
catherine@cordelia
parents: 366
diff changeset
752 for (rownum, row) in enumerate(self.rows)]
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
753 self.rc = len(self.rows)
315
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
754 if self.rc != 0:
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
755 resultset = ResultSet()
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
756 resultset.colnames = [d[0].lower() for d in self.curs.description]
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
757 resultset.pystate = self.pystate
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
758 resultset.statement = 'select ' + selecttext
273
9d67065ea030 data into/out of py via binds
catherine@Elli.myhome.westell.com
parents: 272
diff changeset
759 resultset.varsUsed = self.varsUsed
271
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
760 resultset.extend([Result(r) for r in self.rows])
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
761 for row in resultset:
fbe23b635300 py object manipulation almost done
catherine@dellzilla
parents: 265
diff changeset
762 row.resultset = resultset
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
763 self.pystate['r'].append(resultset)
327
7cc5cc19891f added rows_remembered
Catherine Devlin <catherine.devlin@gmail.com>
parents: 326
diff changeset
764 self.age_out_resultsets()
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
765 self.poutput('\n%s\n' % (self.output(arg.parsed.terminator, rowlimit)))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
766 if self.rc == 0:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
767 self.pfeedback('\nNo rows Selected.\n')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
768 elif self.rc == 1:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
769 self.pfeedback('\n1 row selected.\n')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
770 if self.autobind:
314
0473ad96ddb7 transcript tests work
catherine@Elli.myhome.westell.com
parents: 313
diff changeset
771 self.do_bind('')
315
a0a36232983a url_connect
catherine@Elli.myhome.westell.com
parents: 314
diff changeset
772 elif (self.rc < self.maxfetch and self.rc > 0):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
773 self.pfeedback('\n%d rows selected.\n' % self.rc)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
774 else:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
775 self.pfeedback('\nSelected Max Num rows (%d)' % self.rc)
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
776
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
777 def do_cat(self, arg):
361
catherine@cordelia
parents: 360
diff changeset
778 '''Shortcut for SELECT * FROM
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
779 return self.do_select(self.parsed('SELECT * FROM %s;' % arg,
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
780 terminator = arg.parsed.terminator or ';',
361
catherine@cordelia
parents: 360
diff changeset
781 suffix = arg.parsed.suffix))'''
catherine@cordelia
parents: 360
diff changeset
782 return self.onecmd('SELECT * FROM %s%s%s' % (arg, arg.parsed.terminator or ';',
catherine@cordelia
parents: 360
diff changeset
783 arg.parsed.suffix or ''))
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
784
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
785 def _pull(self, arg, opts, vc=None):
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
786 """Displays source code."""
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
787 if opts.dump:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
788 statekeeper = Statekeeper(self, ('stdout',))
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
789 try:
331
a6cbcf24f148 oops, needed to fix resolve_many
Catherine Devlin <catherine.devlin@gmail.com>
parents: 330
diff changeset
790 for (owner, object_name, object_type) in self.resolve_many(arg, opts):
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
791 if object_type in self.supported_ddl_types:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
792 object_type = {'DATABASE LINK': 'DB_LINK', 'JAVA CLASS': 'JAVA_SOURCE'
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
793 }.get(object_type) or object_type
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
794 object_type = object_type.replace(' ', '_')
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
795 if opts.dump:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
796 try:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
797 os.makedirs(os.path.join(owner.lower(), object_type.lower()))
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
798 except OSError:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
799 pass
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
800 filename = os.path.join(owner.lower(), object_type.lower(), '%s.sql' % object_name.lower())
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
801 self.stdout = open(filename, 'w')
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
802 if vc:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
803 subprocess.call(vc + [filename])
248
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
804 if object_type == 'PACKAGE':
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
805 ddl = [['PACKAGE_SPEC', object_name, owner],['PACKAGE_BODY', object_name, owner]]
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
806 elif object_type in ['CONTEXT', 'DIRECTORY', 'JOB']:
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
807 ddl = [[object_type, object_name]]
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
808 else:
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
809 ddl = [[object_type, object_name, owner]]
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
810 for ddlargs in ddl:
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
811 try:
288
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
812 code = str(self.curs.callfunc('DBMS_METADATA.GET_DDL', cx_Oracle.CLOB, ddlargs))
305
9c727d6afdc0 docs changes
catherine@dellzilla
parents: 297
diff changeset
813 if hasattr(opts, 'lines') and opts.lines:
288
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
814 code = code.splitlines()
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
815 template = "%%-%dd:%%s" % len(str(len(code)))
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
816 code = '\n'.join(template % (n+1, line) for (n, line) in enumerate(code))
305
9c727d6afdc0 docs changes
catherine@dellzilla
parents: 297
diff changeset
817 if hasattr(opts, 'num') and (opts.num is not None):
288
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
818 code = code.splitlines()
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
819 code = centeredSlice(code, center=opts.num+1, width=opts.width)
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
820 code = '\n'.join(code)
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
821 self.poutput(code)
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
822 else:
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
823 self.poutput('REMARK BEGIN %s\n%s\nREMARK END\n' % (object_name, code))
248
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
824 except cx_Oracle.DatabaseError, errmsg:
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
825 if object_type == 'JOB':
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
826 self.pfeedback('%s: DBMS_METADATA.GET_DDL does not support JOBs (MetaLink DocID 567504.1)' % object_name)
248
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
827 elif 'ORA-31603' in str(errmsg): # not found, as in package w/o package body
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
828 pass
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
829 else:
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
830 raise
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
831 if opts.full:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
832 for dependent_type in ('OBJECT_GRANT', 'CONSTRAINT', 'TRIGGER'):
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
833 try:
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
834 self.poutput('REMARK BEGIN\n%s\nREMARK END\n\n' % str(self.curs.callfunc('DBMS_METADATA.GET_DEPENDENT_DDL', cx_Oracle.CLOB,
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
835 [dependent_type, object_name, owner])))
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
836 except cx_Oracle.DatabaseError:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
837 pass
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
838 if opts.dump:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
839 self.stdout.close()
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
840 except:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
841 if opts.dump:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
842 statekeeper.restore()
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
843 raise
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
844 if opts.dump:
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
845 statekeeper.restore()
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
846
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
847 def _show_shortcut(self, shortcut, argpieces):
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
848 try:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
849 newarg = argpieces[1]
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
850 if newarg == 'on':
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
851 try:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
852 newarg = argpieces[2]
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
853 except IndexError:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
854 pass
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
855 except IndexError:
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
856 newarg = ''
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
857 return self.onecmd(shortcut + ' ' + newarg)
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
858
221
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
859 def do_show(self, arg):
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
860 '''
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
861 show - display value of all sqlpython parameters
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
862 show (parameter name) - display value of a sqlpython parameter
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
863 show parameter (parameter name) - display value of an ORACLE parameter
265
041c656dc8e5 show err working nicely now
catherine@Elli.myhome.westell.com
parents: 264
diff changeset
864 show err (object type/name) - errors from latest PL/SQL object compilation.
041c656dc8e5 show err working nicely now
catherine@Elli.myhome.westell.com
parents: 264
diff changeset
865 show all err (type/name) - all compilation errors from the user's PL/SQL objects.
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
866 show (index/schema/tablespace/trigger/view/constraint/comment) on (table)
221
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
867 '''
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
868 if arg.startswith('param'):
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
869 try:
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
870 paramname = arg.split()[1].lower()
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
871 except IndexError:
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
872 paramname = ''
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
873 self.onecmd("""SELECT name,
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
874 CASE type WHEN 1 THEN 'BOOLEAN'
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
875 WHEN 2 THEN 'STRING'
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
876 WHEN 3 THEN 'INTEGER'
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
877 WHEN 4 THEN 'PARAMETER FILE'
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
878 WHEN 5 THEN 'RESERVED'
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
879 WHEN 6 THEN 'BIG INTEGER' END type,
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
880 value FROM v$parameter WHERE name LIKE '%%%s%%';""" % paramname)
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
881 else:
264
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
882 argpieces = arg.lower().split()
370
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
883 argpieces = [a for a in argpieces if not a.startswith('-')]
264
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
884 try:
370
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
885 for (kwd, shortcut) in (
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
886 ('ind', '\\di'), ('schema', '\\dn'),
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
887 ('tablesp', '\\db'), ('trig', '\\dt'),
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
888 ('view', '\\dv'), ('cons', '\\dc'),
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
889 ('comm', '\\dd'), ('ref', 'ref')):
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
890 if argpieces[0].lower().startswith(kwd):
388ee8fa5664 fixed raw SHOW bug
catherine@cordelia
parents: 367
diff changeset
891 return self._show_shortcut(shortcut, argpieces)
264
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
892 if argpieces[0][:3] == 'err':
265
041c656dc8e5 show err working nicely now
catherine@Elli.myhome.westell.com
parents: 264
diff changeset
893 return self._show_errors(all_users=False, limit=1, targets=argpieces[1:])
264
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
894 elif (argpieces[0], argpieces[1][:3]) == ('all','err'):
265
041c656dc8e5 show err working nicely now
catherine@Elli.myhome.westell.com
parents: 264
diff changeset
895 return self._show_errors(all_users=False, limit=None, targets=argpieces[2:])
264
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
896 except IndexError:
a8deaa38f11e show errors works. limiting ls
catherine@Elli.myhome.westell.com
parents: 261
diff changeset
897 pass
221
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
898 return Cmd.do_show(self, arg)
3a59ca05f980 added show parameter
catherine@Elli.myhome.westell.com
parents: 220
diff changeset
899
218
397979c7f6d6 dumping working but not for wildcards
catherine@Elli.myhome.westell.com
parents: 217
diff changeset
900 @options([make_option('-d', '--dump', action='store_true', help='dump results to files'),
397979c7f6d6 dumping working but not for wildcards
catherine@Elli.myhome.westell.com
parents: 217
diff changeset
901 make_option('-f', '--full', action='store_true', help='get dependent objects as well'),
288
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
902 make_option('-l', '--lines', action='store_true', help='print line numbers'),
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
903 make_option('-n', '--num', type='int', help='only code near line #num'),
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
904 make_option('-w', '--width', type='int', default=5,
e7578e7ff9dd sliced pull almost working...
catherine@dellzilla
parents: 286
diff changeset
905 help='# of lines before and after --lineNo'),
217
a65b98938596 multi-pull working pretty well
catherine@Elli.myhome.westell.com
parents: 216
diff changeset
906 make_option('-a', '--all', action='store_true', help="all schemas' objects"),
218
397979c7f6d6 dumping working but not for wildcards
catherine@Elli.myhome.westell.com
parents: 217
diff changeset
907 make_option('-x', '--exact', action='store_true', help="match object name exactly")])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
908 def do_pull(self, arg, opts):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
909 """Displays source code."""
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
910 self._pull(arg, opts)
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
911
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
912 supported_ddl_types = 'CLUSTER, CONTEXT, DATABASE LINK, DIRECTORY, FUNCTION, INDEX, JOB, LIBRARY, MATERIALIZED VIEW, PACKAGE, PACKAGE BODY, PACKAGE SPEC, OPERATOR, PACKAGE, PROCEDURE, SEQUENCE, SYNONYM, TABLE, TRIGGER, VIEW, TYPE, TYPE BODY, XML SCHEMA'
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
913 do_pull.__doc__ += '\n\nSupported DDL types: ' + supported_ddl_types
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
914 supported_ddl_types = supported_ddl_types.split(', ')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
915
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
916 def _vc(self, arg, opts, program):
248
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
917 if not os.path.exists('.%s' % program):
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
918 create = raw_input('%s repository not yet in current directory (%s). Create (y/N)? ' %
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
919 (program, os.getcwd()))
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
920 if not create.strip().lower().startswith('y'):
230447ce6e60 end wed
catherine@dellzilla
parents: 247
diff changeset
921 return
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
922 subprocess.call([program, 'init'])
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
923 opts.dump = True
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
924 self._pull(arg, opts, vc=[program, 'add'])
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
925 subprocess.call([program, 'commit', '-m', '"%s"' % opts.message or 'committed from sqlpython'])
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
926
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
927 @options([
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
928 make_option('-f', '--full', action='store_true', help='get dependent objects as well'),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
929 make_option('-a', '--all', action='store_true', help="all schemas' objects"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
930 make_option('-x', '--exact', action='store_true', help="match object name exactly"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
931 make_option('-m', '--message', action='store', type='string', dest='message', help="message to save to hg log during commit")])
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
932 def do_hg(self, arg, opts):
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
933 '''hg (opts) (objects):
226
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
934 Stores DDL on disk and puts files under Mercurial version control.
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
935 Args specify which objects to store, same format as `ls`.'''
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
936 self._vc(arg, opts, 'hg')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
937
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
938 @options([
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
939 make_option('-f', '--full', action='store_true', help='get dependent objects as well'),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
940 make_option('-a', '--all', action='store_true', help="all schemas' objects"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
941 make_option('-x', '--exact', action='store_true', help="match object name exactly"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
942 make_option('-m', '--message', action='store', type='string', dest='message', help="message to save to hg log during commit")])
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
943 def do_bzr(self, arg, opts):
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
944 '''bzr (opts) (objects):
226
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
945 Stores DDL on disk and puts files under Bazaar version control.
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
946 Args specify which objects to store, same format as `ls`.'''
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
947 self._vc(arg, opts, 'bzr')
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
948
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
949 @options([
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
950 make_option('-f', '--full', action='store_true', help='get dependent objects as well'),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
951 make_option('-a', '--all', action='store_true', help="all schemas' objects"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
952 make_option('-x', '--exact', action='store_true', help="match object name exactly"),
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
953 make_option('-m', '--message', action='store', type='string', dest='message', help="message to save to hg log during commit")])
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
954 def do_git(self, arg, opts):
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
955 '''git (opts) (objects):
226
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
956 Stores DDL on disk and puts files under git version control.
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
957 Args specify which objects to store, same format as `ls`.'''
224
582c84365f6a svn sucks - supporting git instead
catherine@dellzilla
parents: 223
diff changeset
958 self._vc(arg, opts, 'git')
220
01af6bfbe78f hg works
catherine@Elli.myhome.westell.com
parents: 219
diff changeset
959
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
960 all_users_option = make_option('-a', action='store_const', dest="scope",
222
catherine@dellzilla
parents: 221
diff changeset
961 default={'col':'', 'view':'user', 'schemas':'user', 'firstcol': ''},
catherine@dellzilla
parents: 221
diff changeset
962 const={'col':', owner', 'view':'all', 'schemas':'all', 'firstcol': 'owner, '},
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
963 help='Describe all objects (not just my own)')
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
964 @options([all_users_option,
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
965 make_option('-c', '--col', action='store_true', help='find column'),
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
966 make_option('-t', '--table', action='store_true', help='find table')])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
967 def do_find(self, arg, opts):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
968 """Finds argument in source code or (with -c) in column definitions."""
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
969
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
970 capArg = arg.upper()
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
971
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
972 if opts.col:
222
catherine@dellzilla
parents: 221
diff changeset
973 sql = "SELECT table_name, column_name %s FROM %s_tab_columns where column_name like '%%%s%%' ORDER BY %s table_name, column_name;" \
catherine@dellzilla
parents: 221
diff changeset
974 % (opts.scope['col'], opts.scope['view'], capArg, opts.scope['firstcol'])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
975 elif opts.table:
222
catherine@dellzilla
parents: 221
diff changeset
976 sql = "SELECT table_name %s from %s_tables where table_name like '%%%s%%' ORDER BY %s table_name;" \
catherine@dellzilla
parents: 221
diff changeset
977 % (opts.scope['col'], opts.scope['view'], capArg, opts.scope['firstcol'])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
978 else:
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
979 sql = "SELECT * from %s_source where UPPER(text) like '%%%s%%';" % (opts.scope['view'], capArg)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
980 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix))
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
981
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
982
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
983 @options([all_users_option,
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
984 make_option('-l', '--long', action='store_true', help='include column #, comments')])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
985 def do_describe(self, arg, opts):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
986 "emulates SQL*Plus's DESCRIBE"
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
987 target = arg.upper()
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
988 objnameclause = ''
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
989 if target:
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
990 objnameclause = "AND object_name LIKE '%%%s%%' " % target
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
991 object_type, owner, object_name = self.resolve(target)
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
992 if (not target) or (not object_type):
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
993 if opts.long:
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
994 query = """SELECT o.object_name, o.object_type, o.owner, c.comments
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
995 FROM all_objects o
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
996 LEFT OUTER JOIN all_tab_comments c ON (o.owner = c.owner AND o.object_name = c.table_name AND o.object_type = 'TABLE')
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
997 WHERE object_type IN ('TABLE','VIEW','INDEX')
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
998 %sORDER BY object_name;""" % objnameclause
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
999 else:
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1000 query = """SELECT object_name, object_type%s
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1001 FROM %s_objects
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1002 WHERE object_type IN ('TABLE','VIEW','INDEX')
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1003 %sORDER BY object_name;""" % \
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1004 (opts.scope['col'], opts.scope['view'], objnameclause)
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1005 return self.do_select(self.parsed(query, terminator=arg.parsed.terminator or ';',
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1006 suffix=arg.parsed.suffix))
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1007 self.poutput("%s %s.%s\n" % (object_type, owner, object_name))
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1008 try:
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1009 if object_type == 'TABLE':
309
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
1010 if opts.long:
0d16630d8e04 added table comment to desc -l
catherine@Elli.myhome.westell.com
parents: 308
diff changeset
1011 self._execute(queries['tabComments'], {'table_name':object_name, 'owner':owner})
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1012 self.poutput(self.curs.fetchone()[0])
318
0aad38fbc361 finished replacing descQueries with metaqueries
Catherine Devlin <catherine.devlin@gmail.com>
parents: 317
diff changeset
1013 descQ = metaqueries['desc'][self.rdbms][object_type][(opts.long and 'long') or 'short']
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1014 else:
318
0aad38fbc361 finished replacing descQueries with metaqueries
Catherine Devlin <catherine.devlin@gmail.com>
parents: 317
diff changeset
1015 descQ = metaqueries['desc'][self.rdbms][object_type]
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1016 for q in descQ:
204
1c3df79fd088 \n\n finally works
catherine@dellzilla
parents: 203
diff changeset
1017 self.do_select(self.parsed(q, terminator=arg.parsed.terminator or ';' , suffix=arg.parsed.suffix),
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1018 bindVarsIn={'object_name':object_name, 'owner':owner})
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1019 except KeyError:
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1020 if object_type == 'PACKAGE':
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1021 packageContents = self.select_scalar_list(descQueries['PackageObjects'][0], {'package_name':object_name, 'owner':owner})
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1022 for packageObj_name in packageContents:
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1023 self.poutput('Arguments to %s\n' % (packageObj_name))
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1024 sql = self.parsed(descQueries['PackageObjArgs'][0], terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix)
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1025 self.do_select(sql, bindVarsIn={'package_name':object_name, 'owner':owner, 'object_name':packageObj_name})
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1026
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1027
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1028 def do_deps(self, arg):
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1029 '''Lists all objects that are dependent upon the object.'''
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1030 target = arg.upper()
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1031 object_type, owner, object_name = self.resolve(target)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1032 if object_type == 'PACKAGE BODY':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1033 q = "and (type != 'PACKAGE BODY' or name != :object_name)'"
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1034 object_type = 'PACKAGE'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1035 else:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1036 q = ""
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1037 q = """SELECT name,
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1038 type
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1039 from user_dependencies
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1040 where
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1041 referenced_name like :object_name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1042 and referenced_type like :object_type
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1043 and referenced_owner like :owner
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1044 %s;""" % (q)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1045 self.do_select(self.parsed(q, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix),
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1046 bindVarsIn={'object_name':object_name, 'object_type':object_type, 'owner':owner})
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1047
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1048 def do_comments(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1049 'Prints comments on a table and its columns.'
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1050 target = arg.upper()
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1051 object_type, owner, object_name, colName = self.resolve_with_column(target)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1052 if object_type:
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1053 self._execute(queries['tabComments'], {'table_name':object_name, 'owner':owner})
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1054 self.poutput("%s %s.%s: %s\n" % (object_type, owner, object_name, self.curs.fetchone()[0]))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1055 if colName:
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1056 sql = queries['oneColComments']
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1057 bindVarsIn={'owner':owner, 'object_name': object_name, 'column_name': colName}
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1058 else:
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1059 sql = queries['colComments']
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1060 bindVarsIn={'owner':owner, 'object_name': object_name}
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1061 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix),
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1062 bindVarsIn=bindVarsIn)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1063
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1064 def _resolve(self, identifier):
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1065 parts = identifier.split('.')
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1066 if len(parts) == 2:
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1067 owner, object_name = parts
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1068 object_type = self.select_scalar_list('SELECT object_type FROM all_objects WHERE owner = :owner AND object_name = :object_name',
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1069 {'owner': owner, 'object_name': object_name.upper()}
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1070 )[0]
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1071 elif len(parts) == 1:
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1072 object_name = parts[0]
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1073 self._execute(queries['resolve'], {'objName':object_name.upper()})
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1074 object_type, object_name, owner = self.curs.fetchone()
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1075 return object_type, owner, object_name
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1076
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1077 def resolve(self, identifier):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1078 """Checks (my objects).name, (my synonyms).name, (public synonyms).name
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1079 to resolve a database object's name. """
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1080 try:
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1081 return self._resolve(identifier)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1082 except (TypeError, IndexError):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1083 self.pfeedback('Could not resolve object %s.' % identifier)
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1084 return '', '', ''
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1085
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1086 def resolve_with_column(self, identifier):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1087 colName = None
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1088 object_type, owner, object_name = self.resolve(identifier)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1089 if not object_type:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1090 parts = identifier.split('.')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1091 if len(parts) > 1:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1092 colName = parts[-1]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1093 identifier = '.'.join(parts[:-1])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1094 object_type, owner, object_name = self.resolve(identifier)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1095 return object_type, owner, object_name, colName
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1096
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1097 def do_resolve(self, arg):
195
4a3af9ac215f wow, parsing is broken
catherine@dellzilla
parents: 194
diff changeset
1098 target = arg.upper()
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1099 self.poutput(','.join(self.resolve(target))+'\n')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1100
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1101 def spoolstop(self):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1102 if self.spoolFile:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1103 self.stdout = self.stdoutBeforeSpool
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1104 self.pfeedback('Finished spooling to ', self.spoolFile.name)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1105 self.spoolFile.close()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1106 self.spoolFile = None
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1107
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1108 def do_spool(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1109 """spool [filename] - begins redirecting output to FILENAME."""
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1110 self.spoolstop()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1111 arg = arg.strip()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1112 if not arg:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1113 arg = 'output.lst'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1114 if arg.lower() != 'off':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1115 if '.' not in arg:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1116 arg = '%s.lst' % arg
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1117 self.pfeedback('Sending output to %s (until SPOOL OFF received)' % (arg))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1118 self.spoolFile = open(arg, 'w')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1119 self.stdout = self.spoolFile
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1120
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1121 def sqlfeedback(self, arg):
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1122 if self.sql_echo:
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1123 self.pfeedback(arg)
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1124
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1125 def do_write(self, args):
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1126 'Obsolete command. Use (query) > outfilename instead.'
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1127 self.poutput(self.do_write.__doc__)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1128 return
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1129
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1130 def do_compare(self, args):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1131 """COMPARE query1 TO query2 - uses external tool to display differences.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1132
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1133 Sorting is recommended to avoid false hits.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1134 Will attempt to use a graphical diff/merge tool like kdiff3, meld, or Araxis Merge,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1135 if they are installed."""
193
01548a399ccf big switch to ParsedString
catherine@dellzilla
parents: 192
diff changeset
1136 #TODO: Update this to use pyparsing
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1137 fnames = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1138 args2 = args.split(' to ')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1139 if len(args2) < 2:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1140 self.pfeedback(self.do_compare.__doc__)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1141 return
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1142 for n in range(len(args2)):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1143 query = args2[n]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1144 fnames.append('compare%s.txt' % n)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1145 #TODO: update this terminator-stripping
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1146 if query.rstrip()[-1] != self.terminator:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1147 query = '%s%s' % (query, self.terminator)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1148 self.onecmd_plus_hooks('%s > %s' % (query, fnames[n]))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1149 diffMergeSearcher.invoke(fnames[0], fnames[1])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1150
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1151 bufferPosPattern = re.compile('\d+')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1152 rangeIndicators = ('-',':')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1153
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1154 def do_psql(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1155 '''Shortcut commands emulating psql's backslash commands.
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1156
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1157 \c connect
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1158 \d desc
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1159 \e edit
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1160 \g run
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1161 \h help
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1162 \i load
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1163 \o spool
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1164 \p list
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1165 \q quit
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1166 \w save
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1167 \db _dir_tablespaces
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1168 \dd comments
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1169 \dn _dir_schemas
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1170 \dt _dir_tables
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1171 \dv _dir_views
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1172 \di _dir_indexes
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1173 \? help psql'''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1174 commands = {}
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1175 for c in self.do_psql.__doc__.splitlines()[2:]:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1176 (abbrev, command) = c.split(None, 1)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1177 commands[abbrev[1:]] = command
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1178 words = arg.split(None,1)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1179 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1180 abbrev = words[0]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1181 except IndexError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1182 return
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1183 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1184 args = words[1]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1185 except IndexError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1186 args = ''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1187 try:
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1188 return self.onecmd('%s %s%s%s' % (commands[abbrev], args, arg.parsed.terminator, arg.parsed.suffix))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1189 except KeyError:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1190 self.perror('psql command \%s not yet supported.' % abbrev)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1191
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1192 @options([all_users_option])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1193 def do__dir_tables(self, arg, opts):
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1194 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1195 Lists all tables whose names match argument.
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1196 '''
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1197 sql = """SELECT table_name, 'TABLE' as type%s FROM %s_tables WHERE table_name LIKE '%%%s%%';""" % \
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
1198 (opts.scope['col'], opts.scope['view'], arg.upper())
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1199 self.sqlfeedback(sql)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1200 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix))
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1201
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1202 @options([all_users_option])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1203 def do__dir_views(self, arg, opts):
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1204 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1205 Lists all views whose names match argument.
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1206 '''
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1207 sql = """SELECT view_name, 'VIEW' as type%s FROM %s_views WHERE view_name LIKE '%%%s%%';""" % \
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
1208 (opts.scope['col'], opts.scope['view'], arg.upper())
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1209 self.sqlfeedback(sql)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1210 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix))
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1211
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1212 def do__dir_indexes(self, arg):
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1213 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1214 Called with an exact table name, lists the indexes of that table.
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1215 Otherwise, acts as shortcut for `ls index/*(arg)*`
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1216 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1217 try:
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1218 table_type, table_owner, table_name = self._resolve(arg)
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1219 except TypeError, IndexError:
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1220 return self.onecmd('ls Index/*%s*' % arg)
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1221 sql = """SELECT owner, index_name, index_type FROM all_indexes
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1222 WHERE table_owner = :table_owner
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1223 AND table_name = :table_name;
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1224 ORDER BY owner, index_name"""
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1225 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix),
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1226 bindVarsIn = {'table_owner': table_owner, 'table_name': table_name})
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1227
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1228 def do__dir_tablespaces(self, arg):
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1229 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1230 Lists all tablespaces.
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1231 '''
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1232 sql = """SELECT tablespace_name, file_name from dba_data_files;"""
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1233 self.sqlfeedback(sql)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1234 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1235
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1236 def do__dir_schemas(self, arg):
251
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1237 '''
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1238 Lists all object owners, together with the number of objects they own.
aa33f495a289 reworked \di - not truly better?
catherine@Elli.myhome.westell.com
parents: 250
diff changeset
1239 '''
194
932893dcf0c9 useTerminatorFrom
catherine@dellzilla
parents: 193
diff changeset
1240 sql = """SELECT owner, count(*) AS objects FROM all_objects GROUP BY owner ORDER BY owner;"""
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1241 self.sqlfeedback(sql)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1242 self.do_select(self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1243
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1244 def do_head(self, arg):
226
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
1245 '''Shortcut for SELECT * FROM <arg>;10
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
1246 The terminator (\\t, \\g, \\x, etc.) and number of rows can
6701c3f097f9 more comments
catherine@Elli.myhome.westell.com
parents: 224
diff changeset
1247 be changed as for any other SELECT statement.'''
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1248 sql = self.parsed('SELECT * FROM %s;' % arg, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix)
195
4a3af9ac215f wow, parsing is broken
catherine@dellzilla
parents: 194
diff changeset
1249 sql.parsed['suffix'] = sql.parsed.suffix or '10'
196
7940955920a8 little fixes
catherine@dellzilla
parents: 195
diff changeset
1250 self.do_select(self.parsed(sql))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1251
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1252 def do_print(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1253 'print VARNAME: Show current value of bind variable VARNAME.'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1254 if arg:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1255 if arg[0] == ':':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1256 arg = arg[1:]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1257 try:
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1258 self.poutput(str(self.binds[arg])+'\n')
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1259 except KeyError:
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1260 self.poutput('No bind variable %s\n' % arg)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1261 else:
250
aec778ef82b6 print full help on -h
catherine@Elli.myhome.westell.com
parents: 249
diff changeset
1262 for (var, val) in sorted(self.binds.items()):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1263 self.poutput(':%s = %s' % (var, val))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1264
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1265 def split_on_parser(self, parser, arg):
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1266 try:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1267 assigner, startat, endat = parser.scanner.scanString(arg).next()
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1268 return (arg[:startat].strip(), arg[endat:].strip())
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1269 except StopIteration:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1270 return ''.join(arg.split()[:1]), ''
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1271
355
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1272 assignmentSplitter = re.compile(':?=')
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1273 def interpret_variable_assignment(self, arg):
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1274 '''
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1275 Accepts strings like `foo = 'bar'` or `baz := 22`, returning Python
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1276 variables as appropriate
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1277 '''
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1278 try:
355
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1279 var, val = self.assignmentSplitter.split(arg.parsed.expanded, maxsplit=1)
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1280 except ValueError:
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1281 return False, arg.parsed.expanded.split()[0] or None, None
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1282 var = var.split()[-1]
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1283 if (len(val) > 1) and ((val[0] == val[-1] == "'") or (val[0] == val[-1] == '"')):
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1284 return True, var, val[1:-1]
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1285 try:
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1286 return True, var, int(val)
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1287 except ValueError:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1288 try:
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1289 return True, var, float(val)
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1290 except ValueError:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1291 # use the conversions implicit in cx_Oracle's select to
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1292 # cast the value into an appropriate type (dates, for instance)
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1293 try:
355
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1294 if self.rdbms == 'oracle':
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1295 sql = 'SELECT %s FROM dual'
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1296 else:
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1297 sql = 'SELECT %s'
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1298 self.curs.execute(sql % val)
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1299 return True, var, self.curs.fetchone()[0]
355
c66240c3341a fixed setbind bug
catherine@cordelia
parents: 340
diff changeset
1300 except: # should not be bare - should catch cx_Oracle.DatabaseError, etc.
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1301 return True, var, val # we give up and assume it's a string
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1302
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1303 def do_setbind(self, arg):
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1304 '''Sets or shows values of bind (`:`) variables.'''
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1305 if not arg:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1306 return self.do_print(arg)
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1307 assigned, var, val = self.interpret_variable_assignment(arg)
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1308 if not assigned:
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1309 return self.do_print(var)
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1310 else:
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1311 self.binds[var] = val
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1312
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1313 def do_define(self, arg):
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1314 '''Sets or shows values of substitution (`&`) variables.'''
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1315 if not arg:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1316 for (substvar, val) in sorted(self.substvars.items()):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1317 self.poutput('DEFINE %s = "%s" (%s)' % (substvar, val, type(val)))
329
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1318 assigned, var, val = self.interpret_variable_assignment(arg)
3efffbf7481f fixed bug in assigning 0, null to bind vars
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1319 if assigned:
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1320 self.substvars[var] = val
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1321 else:
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1322 if var in self.substvars:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1323 self.poutput('DEFINE %s = "%s" (%s)' % (var, self.substvars[var], type(self.substvars[var])))
285
316abf2191a4 substvar define working now
catherine@dellzilla
parents: 284
diff changeset
1324
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1325 def do_exec(self, arg):
213
a3eeea9ee8cc synched with cmd2 0.4.5
catherine@Elli.myhome.westell.com
parents: 211
diff changeset
1326 if arg.startswith(':'):
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1327 self.do_setbind(arg[1:])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1328 else:
340
001d01eeac90 bind vars for postgres
Catherine Devlin <catherine.devlin@gmail.com>
parents: 339
diff changeset
1329 varsUsed = self.findBinds(arg, {})
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1330 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1331 self.curs.execute('begin\n%s;end;' % arg, varsUsed)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1332 except Exception, e:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1333 self.perror(e)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1334
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1335 '''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1336 Fails:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1337 select n into :n from test;'''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1338
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1339 def anon_plsql(self, line1):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1340 lines = [line1]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1341 while True:
247
f0f293d83337 begin docs
catherine@dellzilla
parents: 246
diff changeset
1342 line = self.pseudo_raw_input(self.continuation_prompt)
311
38ac0fbb2b63 history on plsql
catherine@Elli.myhome.westell.com
parents: 310
diff changeset
1343 self.history[-1] = '%s\n%s' % (self.history[-1], line)
241
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
1344 if line == 'EOF':
d1f1022d2387 trying remark_begin
catherine@Elli.myhome.westell.com
parents: 240
diff changeset
1345 return
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1346 if line.strip() == '/':
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1347 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1348 self.curs.execute('\n'.join(lines))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1349 except Exception, e:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1350 self.perror(e)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1351 return
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1352 lines.append(line)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1353
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1354 def do_begin(self, arg):
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1355 '''
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1356 PL/SQL blocks can be used normally in sqlpython, though enclosing statements in
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1357 REMARK BEGIN... REMARK END statements can help with parsing speed.'''
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1358 self.anon_plsql('begin ' + arg)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1359
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1360 def do_declare(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1361 self.anon_plsql('declare ' + arg)
216
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1362
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1363 def ls_where_clause(self, arg, opts):
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1364 where = ['WHERE (1=1) ']
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1365 if arg:
280
8ea39093ddf2 struggling with catching terminator after /*
catherine@dellzilla
parents: 277
diff changeset
1366 target = arg.upper().replace('*','%')
313
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1367 if target in self.object_types:
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1368 target += '/%'
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1369 where.append("""
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1370 AND( UPPER(object_type) || '/' || UPPER(object_name) LIKE '%s'
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1371 OR UPPER(object_name) LIKE '%s')""" % (target, target))
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1372 if not opts.all:
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1373 where.append("AND owner = my_own")
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1374 return '\n'.join(where)
216
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1375
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1376 def resolve_many(self, arg, opts):
331
a6cbcf24f148 oops, needed to fix resolve_many
Catherine Devlin <catherine.devlin@gmail.com>
parents: 330
diff changeset
1377 statement = """SELECT owner, object_name, object_type FROM (%s)
a6cbcf24f148 oops, needed to fix resolve_many
Catherine Devlin <catherine.devlin@gmail.com>
parents: 330
diff changeset
1378 %s""" % (metaqueries['ls'][self.rdbms], self.ls_where_clause(arg, opts))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1379 self._execute(statement)
216
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1380 return self.curs.fetchall()
313
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1381
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1382 object_types = (
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1383 'BASE TABLE',
313
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1384 'CLUSTER',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1385 'CONSUMER GROUP',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1386 'CONTEXT',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1387 'DIRECTORY',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1388 'EDITION',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1389 'EVALUATION CONTEXT',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1390 'FUNCTION',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1391 'INDEX',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1392 'INDEX PARTITION',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1393 'INDEXTYPE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1394 'JAVA CLASS',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1395 'JAVA DATA',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1396 'JAVA RESOURCE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1397 'JOB',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1398 'JOB CLASS',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1399 'LIBRARY',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1400 'MATERIALIZED VIEW',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1401 'OPERATOR',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1402 'PACKAGE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1403 'PACKAGE BODY',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1404 'PROCEDURE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1405 'PROGRAM',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1406 'RULE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1407 'RULE SET',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1408 'SCHEDULE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1409 'SEQUENCE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1410 'SYNONYM',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1411 'TABLE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1412 'TABLE PARTITION',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1413 'TRIGGER',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1414 'TYPE',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1415 'TYPE BODY',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1416 'VIEW',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1417 'WINDOW',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1418 'WINDOW GROUP',
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1419 'XML SCHEMA')
216
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1420
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1421 @options([make_option('-l', '--long', action='store_true', help='long descriptions'),
217
a65b98938596 multi-pull working pretty well
catherine@Elli.myhome.westell.com
parents: 216
diff changeset
1422 make_option('-a', '--all', action='store_true', help="all schemas' objects"),
227
5cfa3eff8e4b time and reverse sorting added to ls
catherine@dellzilla
parents: 226
diff changeset
1423 make_option('-t', '--timesort', action='store_true', help="Sort by last_ddl_time"),
313
22fc9a350eaa finally, ls working right
catherine@Elli.myhome.westell.com
parents: 311
diff changeset
1424 make_option('-r', '--reverse', action='store_true', help="Reverse order while sorting")])
216
c5a49947eedc going to try multiple pull
catherine@Elli.myhome.westell.com
parents: 213
diff changeset
1425 def do_ls(self, arg, opts):
281
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1426 '''
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1427 Lists objects as through they were in an {object_type}/{object_name} UNIX
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1428 directory structure. `*` and `%` may be used as wildcards.
701f0aae837a got maxtselctrows working again
catherine@dellzilla
parents: 280
diff changeset
1429 '''
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1430 clauses = {'owner': '', 'moreColumns': '',
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1431 'source': metaqueries['ls'][self.rdbms],
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1432 'where': self.ls_where_clause(arg, opts)}
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1433 if opts.long:
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1434 clauses['moreColumns'] = ', status, last_ddl_time'
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1435 if opts.all:
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1436 clauses['owner'] = "owner || '.' ||"
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1437
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1438 # 'Normal' sort order is DATE DESC (maybe), object type ASC, object name ASC
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1439 sortdirection = (hasattr(opts, 'reverse') and opts.reverse and 'DESC') or 'ASC'
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1440 orderby = 'object_type %s, object_name %s' % (sortdirection, sortdirection)
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1441 if hasattr(opts, 'timesort') and opts.timesort:
357
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1442 if hasattr(opts, 'reverse') and opts.reverse:
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1443 direction = 'DESC'
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1444 else:
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1445 direction = 'ASC'
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1446 orderby = 'last_ddl_time %s, %s' % (direction, orderby)
326
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1447 clauses['orderby'] = orderby
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1448 statement = '''
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1449 SELECT object_type || '/' || %(owner)s object_name AS name %(moreColumns)s
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1450 FROM (%(source)s) source
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1451 %(where)s
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1452 ORDER BY %(orderby)s;''' % clauses
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1453 self.do_select(self.parsed(statement,
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1454 terminator=arg.parsed.terminator or ';',
82937b8dcbfe very basic multi-RDBMS ls in place
Catherine Devlin <catherine.devlin@gmail.com>
parents: 322
diff changeset
1455 suffix=arg.parsed.suffix))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1456
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1457 @options([make_option('-i', '--ignore-case', dest='ignorecase', action='store_true', help='Case-insensitive search')])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1458 def do_grep(self, arg, opts):
314
0473ad96ddb7 transcript tests work
catherine@Elli.myhome.westell.com
parents: 313
diff changeset
1459 """grep {target} {table} [{table2,...}]
0473ad96ddb7 transcript tests work
catherine@Elli.myhome.westell.com
parents: 313
diff changeset
1460 search for {target} in any of {table}'s fields"""
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1461
195
4a3af9ac215f wow, parsing is broken
catherine@dellzilla
parents: 194
diff changeset
1462 targetnames = arg.split()
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1463 pattern = targetnames.pop(0)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1464 targets = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1465 for target in targetnames:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1466 if '*' in target:
310
c897add05eb1 fixed grep bug
catherine@Elli.myhome.westell.com
parents: 309
diff changeset
1467 self._execute("""SELECT owner, object_name FROM all_objects
c897add05eb1 fixed grep bug
catherine@Elli.myhome.westell.com
parents: 309
diff changeset
1468 WHERE object_type IN ('TABLE','VIEW')
311
38ac0fbb2b63 history on plsql
catherine@Elli.myhome.westell.com
parents: 310
diff changeset
1469 AND object_name LIKE '%s'""" %
38ac0fbb2b63 history on plsql
catherine@Elli.myhome.westell.com
parents: 310
diff changeset
1470 target.upper().replace('*','%'))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1471 for row in self.curs:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1472 targets.append('%s.%s' % row)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1473 else:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1474 targets.append(target)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1475 for target in targets:
356
c86177642f75 replacing stdout with poutput; no bracketing partial pulls with remarks
catherine@cordelia
parents: 355
diff changeset
1476 self.pfeedback('%s\n' % target)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1477 target = target.rstrip(';')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1478 try:
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1479 self._execute('select * from %s where 1=0' % target) # first pass fills description
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1480 if opts.ignorecase:
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1481 colnames = ['LOWER(%s)' % self._cast(d[0], 'CHAR') for d in self.curs.description]
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1482 else:
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1483 colnames = ['LOWER(%s)' % self._cast(d[0], 'CHAR') for d in self.curs.description]
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1484 sql = ' or '.join("%s LIKE '%%%s%%'" % (cn, pattern.lower()) for cn in colnames)
200
54cd1e802fa0 terminators + suffixes now preserved
catherine@dellzilla
parents: 199
diff changeset
1485 sql = self.parsed('SELECT * FROM %s WHERE %s;' % (target, sql), terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix)
199
09592342a33d ugh - parsing stripping command causes real trouble
catherine@dellzilla
parents: 198
diff changeset
1486 self.do_select(sql)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1487 except Exception, e:
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1488 self.perror(e)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1489 import traceback
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1490 traceback.print_exc(file=sys.stdout)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1491
335
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1492 def _cast(self, colname, typ='CHAR'):
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1493 'self._cast(colname, typ) => Returns the RDBMS-equivalent "CAST (colname AS typ) expression.'
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1494 converter = {'oracle': 'TO_%(typ)s(%(colname)s)'}.get(self.rdbms, 'CAST(%(colname)s AS %(typ)s)')
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1495 return converter % {'colname': colname, 'typ': typ}
00b183a103b3 bare prefix switches connection
Catherine Devlin <catherine.devlin@gmail.com>
parents: 334
diff changeset
1496
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1497 def _execute(self, sql, bindvars={}):
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1498 self.sqlfeedback(sql)
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1499 self.curs.execute(sql, bindvars)
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1500
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1501 #@options([make_option('-l', '--long', action='store_true',
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1502 # help='Wordy, easy-to-understand form'),])
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1503 def do_refs(self, arg):
286
abb4c6524113 adding ioug paper
catherine@dellzilla
parents: 285
diff changeset
1504 '''Lists referential integrity (foreign key constraints) on an object or referring to it.'''
211
catherine@Elli.myhome.westell.com
parents: 210
diff changeset
1505
catherine@Elli.myhome.westell.com
parents: 210
diff changeset
1506 if not arg.strip():
333
1cde0ec62e61 send up
Catherine Devlin <catherine.devlin@gmail.com>
parents: 332
diff changeset
1507 self.perror('Usage: refs (table name)')
190
e9d0492d7358 changing refs
catherine@dellzilla
parents: 189
diff changeset
1508 result = []
205
catherine@dellzilla
parents: 204
diff changeset
1509 (type, owner, table_name) = self.resolve(arg.upper())
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1510 sql = """SELECT constraint_name, r_owner, r_constraint_name
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1511 FROM all_constraints
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1512 WHERE constraint_type = 'R'
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1513 AND owner = :owner
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1514 AND table_name = :table_name"""
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1515 self._execute(sql, {"owner": owner, "table_name": table_name})
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1516 for (constraint_name, remote_owner, remote_constraint_name) in self.curs.fetchall():
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1517 result.append('%s on %s.%s:' % (constraint_name, owner, table_name))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1518
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1519 self._execute("SELECT column_name FROM all_cons_columns WHERE owner = :owner AND constraint_name = :constraint_name ORDER BY position",
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1520 {'constraint_name': constraint_name, 'owner': owner})
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1521 result.append(" (%s)" % (",".join(col[0] for col in self.curs.fetchall())))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1522 self._execute("SELECT table_name FROM all_constraints WHERE owner = :remote_owner AND constraint_name = :remote_constraint_name",
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1523 {'remote_owner': remote_owner, 'remote_constraint_name': remote_constraint_name})
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1524 remote_table_name = self.curs.fetchone()[0]
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1525 result.append("must be in %s:" % (remote_table_name))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1526 self._execute("SELECT column_name FROM all_cons_columns WHERE owner = :remote_owner AND constraint_name = :remote_constraint_name ORDER BY position",
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1527 {'remote_constraint_name': remote_constraint_name, 'remote_owner': remote_owner})
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1528 result.append(' (%s)\n' % (",".join(col[0] for col in self.curs.fetchall())))
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1529 remote_table_name = table_name
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1530 remote_owner = owner
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1531 self._execute("""SELECT owner, constraint_name, table_name, r_constraint_name
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1532 FROM all_constraints
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1533 WHERE (r_owner, r_constraint_name) IN
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1534 ( SELECT owner, constraint_name
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1535 FROM all_constraints
192
6bb8a112af6b accept special terminators on most anything
catherine@dellzilla
parents: 191
diff changeset
1536 WHERE table_name = :remote_table_name
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1537 AND owner = :remote_owner )""",
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1538 {'remote_table_name': remote_table_name, 'remote_owner': remote_owner})
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1539 for (owner, constraint_name, table_name, remote_constraint_name) in self.curs.fetchall():
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1540 result.append('%s on %s.%s:' % (constraint_name, owner, table_name))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1541 self._execute("SELECT column_name FROM all_cons_columns WHERE owner = :owner AND constraint_name = :constraint_name ORDER BY position",
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1542 {'constraint_name': constraint_name, 'owner': owner})
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1543 result.append(" (%s)" % (",".join(col[0] for col in self.curs.fetchall())))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1544 self._execute("SELECT table_name FROM all_constraints WHERE owner = :remote_owner AND constraint_name = :remote_constraint_name",
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1545 {'remote_owner': remote_owner, 'remote_constraint_name': remote_constraint_name})
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1546 remote_table_name = self.curs.fetchone()[0]
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1547 result.append("must be in %s:" % (remote_table_name))
249
9e3e49c95abf added sql_echo
catherine@Elli.myhome.westell.com
parents: 248
diff changeset
1548 self._execute("SELECT column_name FROM all_cons_columns WHERE owner = :remote_owner AND constraint_name = :remote_constraint_name ORDER BY position",
191
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1549 {'remote_constraint_name': remote_constraint_name, 'remote_owner': remote_owner})
eca4361bfdb6 improved refs
catherine@dellzilla
parents: 190
diff changeset
1550 result.append(' (%s)\n' % (",".join(col[0] for col in self.curs.fetchall())))
357
9960bece1e88 added defaultdict backport
catherine@cordelia
parents: 356
diff changeset
1551 self.poutput('\n'.join(result) + "\n")
190
e9d0492d7358 changing refs
catherine@dellzilla
parents: 189
diff changeset
1552
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1553 def _test():
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1554 import doctest
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1555 doctest.testmod()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1556
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1557 if __name__ == "__main__":
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1558 "Silent return implies that all unit tests succeeded. Use -v to see details."
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1559 _test()
198
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 196
diff changeset
1560 if __name__ == "__main__":
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 196
diff changeset
1561 "Silent return implies that all unit tests succeeded. Use -v to see details."
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 196
diff changeset
1562 _test()