annotate sqlpython/sqlpyPlus.py @ 355:c66240c3341a

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