annotate sqlpython/sqlpython.py @ 198:b2d8bf5f89db

merged with changes from work
author catherine@Elli.myhome.westell.com
date Tue, 02 Dec 2008 11:00:21 -0500
parents 3af1615e6ea8
children 3ca2271847e2
rev   line source
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
1 #
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
2 # SqlPython V1.5.0
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
3 # Author: Luca.Canali@cern.ch, Apr 2006
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
4 # Rev 29-May-08
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
5 #
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
6 # A python module to reproduce Oracle's command line 'sqlplus-like' within python
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
7 # Intended to allow easy customizations and extentions
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
8 # Best used with the companion modules sqlpyPlus and mysqlpy
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
9 # See also http://twiki.cern.ch/twiki/bin/view/PSSGroup/SqlPython
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
10
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
11 import cmd2,getpass,binascii,cx_Oracle,re,os
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
12 import sqlpyPlus
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
13 __version__ = '1.5.0'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
14 # complication! separate sessions ->
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
15 # separate transactions !!!!!
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
16 # also: timeouts, other session failures
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
17
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
18 class sqlpython(cmd2.Cmd):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
19 '''A python module to reproduce Oracle's command line with focus on customization and extention'''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
20
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
21 def __init__(self):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
22 cmd2.Cmd.__init__(self)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
23 self.prompt = 'SQL.No_Connection> '
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
24 self.maxfetch = 1000
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
25 self.terminator = ';'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
26 self.timeout = 30
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
27 self.commit_on_exit = True
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
28
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
29 connection_modes = {re.compile(' AS SYSDBA', re.IGNORECASE): cx_Oracle.SYSDBA,
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
30 re.compile(' AS SYSOPER', re.IGNORECASE): cx_Oracle.SYSOPER}
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
31 def do_connect(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
32 '''Opens the DB connection'''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
33 modeval = 0
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
34 for modere, modevalue in self.connection_modes.items():
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
35 if modere.search(arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
36 arg = modere.sub('', arg)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
37 modeval = modevalue
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
38 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
39 orauser, oraserv = arg.split('@')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
40 except ValueError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
41 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
42 oraserv = os.environ['ORACLE_SID']
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
43 except KeyError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
44 print 'instance not specified and environment variable ORACLE_SID not set'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
45 return
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
46 orauser = arg
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
47 sid = oraserv
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
48 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
49 host, sid = oraserv.split('/')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
50 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
51 host, port = host.split(':')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
52 port = int(port)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
53 except ValueError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
54 port = 1521
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
55 oraserv = cx_Oracle.makedsn(host, port, sid)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
56 except ValueError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
57 pass
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
58 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
59 orauser, orapass = orauser.split('/')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
60 except ValueError:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
61 orapass = getpass.getpass('Password: ')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
62 if orauser.upper() == 'SYS' and not modeval:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
63 print 'Privilege not specified for SYS, assuming SYSOPER'
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
64 modeval = cx_Oracle.SYSOPER
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
65 try:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
66 self.orcl = cx_Oracle.connect(orauser,orapass,oraserv,modeval)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
67 self.curs = self.orcl.cursor()
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
68 self.prompt = '%s@%s> ' % (orauser, sid)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
69 except Exception, e:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
70 print e
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
71
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
72
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
73 def emptyline(self):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
74 pass
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
75
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
76 def do_terminators(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
77 """; standard Oracle format
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
78 \\c CSV (with headings)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
79 \\C CSV (no headings)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
80 \\g list
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
81 \\G aligned list
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
82 \\h HTML table
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
83 \\i INSERT statements
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
84 \\s CSV (with headings)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
85 \\S CSV (no headings)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
86 \\t transposed
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
87 \\x XML
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
88 \\l line plot, with markers
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
89 \\L scatter plot (no lines)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
90 \\b bar graph
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
91 \\p pie chart"""
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
92 print self.do_terminators.__doc__
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
93
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
94 terminatorSearchString = '|'.join('\\' + d.split()[0] for d in do_terminators.__doc__.splitlines())
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
95
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
96 def default(self, arg):
198
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
97 self.varsUsed = sqlpyPlus.findBinds(arg, self.binds, givenBindVars={})
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
98 self.curs.execute('%s %s' % (arg.parsed.command, arg.parsed.args), self.varsUsed)
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
99 print '\nExecuted%s\n' % ((self.curs.rowcount > 0) and ' (%d rows)' % self.curs.rowcount or '')
198
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
100
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
101 def do_commit(self, arg=''):
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
102 self.default(self.parsed('commit %s;' % (arg)))
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
103 def do_rollback(self, arg=''):
b2d8bf5f89db merged with changes from work
catherine@Elli.myhome.westell.com
parents: 197
diff changeset
104 self.default(self.parsed('rollback %s;' % (arg)))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
105 def do_quit(self, arg):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
106 if self.commit_on_exit and hasattr(self, 'curs'):
197
3af1615e6ea8 default fix
catherine@dellzilla
parents: 196
diff changeset
107 self.default(self.parsed('commit'))
189
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
108 return cmd2.Cmd.do_quit(self, None)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
109 do_exit = do_quit
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
110 do_q = do_quit
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
111
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
112 def pmatrix(rows,desc,maxlen=30):
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
113 '''prints a matrix, used by sqlpython to print queries' result sets'''
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
114 names = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
115 maxen = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
116 toprint = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
117 for d in desc:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
118 n = d[0]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
119 names.append(n) # list col names
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
120 maxen.append(len(n)) # col length
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
121 rcols = range(len(desc))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
122 rrows = range(len(rows))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
123 for i in rrows: # loops for all rows
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
124 rowsi = map(str, rows[i]) # current row to process
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
125 split = [] # service var is row split is needed
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
126 mustsplit = 0 # flag
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
127 for j in rcols:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
128 if str(desc[j][1]) == "<type 'cx_Oracle.BINARY'>": # handles RAW columns
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
129 rowsi[j] = binascii.b2a_hex(rowsi[j])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
130 maxen[j] = max(maxen[j], len(rowsi[j])) # computes max field length
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
131 if maxen[j] <= maxlen:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
132 split.append('')
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
133 else: # split the line is 2 because field is too long
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
134 mustsplit = 1
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
135 maxen[j] = maxlen
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
136 split.append(rowsi[j][maxlen-1:2*maxlen-1])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
137 rowsi[j] = rowsi[j][0:maxlen-1] # this implem. truncates after maxlen*2
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
138 toprint.append(rowsi) # 'toprint' is a printable copy of rows
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
139 if mustsplit != 0:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
140 toprint.append(split)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
141 sepcols = []
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
142 for i in rcols:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
143 maxcol = maxen[i]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
144 name = names[i]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
145 sepcols.append("-" * maxcol) # formats column names (header)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
146 names[i] = name + (" " * (maxcol-len(name))) # formats separ line with --
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
147 rrows2 = range(len(toprint))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
148 for j in rrows2:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
149 val = toprint[j][i]
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
150 if str(desc[i][1]) == "<type 'cx_Oracle.NUMBER'>": # right align numbers
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
151 toprint[j][i] = (" " * (maxcol-len(val))) + val
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
152 else:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
153 toprint[j][i] = val + (" " * (maxcol-len(val)))
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
154 for j in rrows2:
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
155 toprint[j] = ' '.join(toprint[j])
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
156 names = ' '.join(names)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
157 sepcols = ' '.join(sepcols)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
158 toprint.insert(0, sepcols)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
159 toprint.insert(0, names)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
160 return '\n'.join(toprint)
c5398d87498e cat bug
catherine@dellzilla
parents:
diff changeset
161