annotate sqlpython/sqlpyPlus.py @ 285:316abf2191a4

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