Mercurial > sqlpython
annotate sqlpython.py @ 115:43f5dc75b791
migrating to onecmd from select
author | catherine@Elli.myhome.westell.com |
---|---|
date | Sat, 28 Jun 2008 11:10:09 -0400 |
parents | c1c05670b4e5 |
children |
rev | line source |
---|---|
0 | 1 # |
109 | 2 # SqlPython V1.4.6.1 |
0 | 3 # Author: Luca.Canali@cern.ch, Apr 2006 |
103 | 4 # Rev 29-May-08 |
0 | 5 # |
6 # A python module to reproduce Oracle's command line 'sqlplus-like' within python | |
7 # Intended to allow easy customizations and extentions | |
8 # Best used with the companion modules sqlpyPlus and mysqlpy | |
9 # See also http://twiki.cern.ch/twiki/bin/view/PSSGroup/SqlPython | |
10 | |
102 | 11 import cmd2,getpass,binascii,cx_Oracle,re,os |
80 | 12 import pexpecter, sqlpyPlus |
0 | 13 |
14 # complication! separate sessions -> | |
15 # separate transactions !!!!! | |
16 # also: timeouts, other session failures | |
40
1fb9f7dee7d8
tearing out cmd2
devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
parents:
16
diff
changeset
|
17 |
16
2776755a3a7e
beginning separation of cmd2
devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
parents:
9
diff
changeset
|
18 class sqlpython(cmd2.Cmd): |
0 | 19 '''A python module to reproduce Oracle's command line with focus on customization and extention''' |
20 | |
21 def __init__(self): | |
16
2776755a3a7e
beginning separation of cmd2
devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
parents:
9
diff
changeset
|
22 cmd2.Cmd.__init__(self) |
0 | 23 self.prompt = 'SQL.No_Connection> ' |
24 self.maxfetch = 1000 | |
25 self.failoverSessions = [] | |
26 self.terminator = ';' | |
27 self.timeout = 30 | |
102 | 28 |
29 connection_modes = {re.compile(' AS SYSDBA', re.IGNORECASE): cx_Oracle.SYSDBA, | |
30 re.compile(' AS SYSOPER', re.IGNORECASE): cx_Oracle.SYSOPER} | |
0 | 31 def do_connect(self, arg): |
32 '''Opens the DB connection''' | |
102 | 33 modeval = 0 |
34 for modere, modevalue in self.connection_modes.items(): | |
35 if modere.search(arg): | |
36 arg = modere.sub('', arg) | |
37 modeval = modevalue | |
0 | 38 try: |
102 | 39 orauser, oraserv = arg.split('@') |
40 except ValueError: | |
41 try: | |
42 oraserv = os.environ['ORACLE_SID'] | |
43 except KeyError: | |
44 print 'instance not specified and environment variable ORACLE_SID not set' | |
45 return | |
46 orauser = arg | |
47 sid = oraserv | |
48 try: | |
49 host, sid = oraserv.split('/') | |
50 try: | |
51 host, port = host.split(':') | |
52 port = int(port) | |
53 except ValueError: | |
54 port = 1521 | |
55 oraserv = cx_Oracle.makedsn(host, port, sid) | |
56 except ValueError: | |
57 pass | |
58 try: | |
59 orauser, orapass = orauser.split('/') | |
60 except ValueError: | |
61 orapass = getpass.getpass('Password: ') | |
62 if orauser.upper() == 'SYS' and not modeval: | |
63 print 'Privilege not specified for SYS, assuming SYSOPER' | |
64 modeval = cx_Oracle.SYSOPER | |
65 try: | |
66 self.orcl = cx_Oracle.connect(orauser,orapass,oraserv,modeval) | |
0 | 67 self.curs = self.orcl.cursor() |
102 | 68 self.prompt = '%s@%s> ' % (orauser, sid) |
0 | 69 self.failoverSessions = [f for f in [fbs(arg) for fbs in pexpecter.available] if f.available] |
70 except Exception, e: | |
71 print e | |
102 | 72 |
0 | 73 |
74 def emptyline(self): | |
75 pass | |
76 | |
77 def fail(self, arg, do_everywhere=False): | |
78 if self.failover: | |
79 success, result = False, '' | |
80 for fbs in self.failoverSessions: | |
81 success, result = fbs.attempt(arg) | |
82 if success: | |
83 print result | |
84 if not do_everywhere: | |
85 return True | |
86 print result | |
87 return False | |
88 | |
89 def designated_session(self, arg, sesstype): | |
90 for fbs in self.failoverSessions: | |
91 if fbs.valid and fbs.__class__ == sesstype: | |
92 success, result = fbs.attempt(arg) | |
93 print result | |
94 return | |
95 print 'Valid %s not found' % (sesstype.__name__) | |
96 | |
97 def do_terminators(self, arg): | |
98 """; standard Oracle format | |
99 \\c CSV (with headings) | |
100 \\C CSV (no headings) | |
101 \\g list | |
102 \\G aligned list | |
103 \\h HTML table | |
104 \\i INSERT statements | |
105 \\s CSV (with headings) | |
106 \\S CSV (no headings) | |
107 \\t transposed | |
108 \\x XML""" | |
109 print self.do_terminators.__doc__ | |
115
43f5dc75b791
migrating to onecmd from select
catherine@Elli.myhome.westell.com
parents:
114
diff
changeset
|
110 |
0 | 111 def do_yasql(self, arg): |
112 '''Sends a command to a YASQL session (http://sourceforge.net/projects/yasql/)''' | |
113 self.designated_session(arg, pexpecter.YASQLSession) | |
114 do_y = do_yasql | |
115 def do_sqlplus(self, arg): | |
116 '''Sends a command to a SQL*Plus session''' | |
117 self.designated_session(arg, pexpecter.SqlPlusSession) | |
118 do_sqlp = do_sqlplus | |
119 def do_senora(self, arg): | |
120 '''Sends a command to a Senora session (http://senora.sourceforge.net/)''' | |
121 self.designated_session(arg, pexpecter.SenoraSession) | |
122 do_sen = do_senora | |
9
f70cc3be6377
reporting rowcount
devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
parents:
3
diff
changeset
|
123 |
0 | 124 def default(self, arg, do_everywhere = False): |
114
c1c05670b4e5
going to modify to work with new cmd2
catherine@Elli.myhome.westell.com
parents:
109
diff
changeset
|
125 #self.query = self.finishStatement(arg).strip().rstrip(';') |
c1c05670b4e5
going to modify to work with new cmd2
catherine@Elli.myhome.westell.com
parents:
109
diff
changeset
|
126 self.query = arg |
0 | 127 try: |
80 | 128 self.varsUsed = sqlpyPlus.findBinds(self.query, self.binds, givenBindVars={}) |
129 self.curs.execute(self.query, self.varsUsed) | |
9
f70cc3be6377
reporting rowcount
devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
parents:
3
diff
changeset
|
130 print '\nExecuted%s\n' % ((self.curs.rowcount > 0) and ' (%d rows)' % self.curs.rowcount or '') |
0 | 131 if do_everywhere: |
132 self.fail(arg, do_everywhere = True ) | |
133 except Exception, e: | |
134 result = self.fail(arg) | |
135 if not result: | |
136 print str(e) | |
115
43f5dc75b791
migrating to onecmd from select
catherine@Elli.myhome.westell.com
parents:
114
diff
changeset
|
137 |
0 | 138 # shortcuts |
92 | 139 do_exit = cmd2.Cmd.do_quit |
0 | 140 |
141 def pmatrix(rows,desc,maxlen=30): | |
142 '''prints a matrix, used by sqlpython to print queries' result sets''' | |
143 names = [] | |
144 maxen = [] | |
145 toprint = [] | |
146 for d in desc: | |
147 n = d[0] | |
148 names.append(n) # list col names | |
149 maxen.append(len(n)) # col length | |
150 rcols = range(len(desc)) | |
151 rrows = range(len(rows)) | |
152 for i in rrows: # loops for all rows | |
153 rowsi = map(str, rows[i]) # current row to process | |
154 split = [] # service var is row split is needed | |
155 mustsplit = 0 # flag | |
156 for j in rcols: | |
157 if str(desc[j][1]) == "<type 'cx_Oracle.BINARY'>": # handles RAW columns | |
80 | 158 rowsi[j] = binascii.b2a_hex(rowsi[j]) |
0 | 159 maxen[j] = max(maxen[j], len(rowsi[j])) # computes max field length |
160 if maxen[j] <= maxlen: | |
161 split.append('') | |
162 else: # split the line is 2 because field is too long | |
163 mustsplit = 1 | |
164 maxen[j] = maxlen | |
165 split.append(rowsi[j][maxlen-1:2*maxlen-1]) | |
166 rowsi[j] = rowsi[j][0:maxlen-1] # this implem. truncates after maxlen*2 | |
167 toprint.append(rowsi) # 'toprint' is a printable copy of rows | |
168 if mustsplit != 0: | |
169 toprint.append(split) | |
170 sepcols = [] | |
171 for i in rcols: | |
172 maxcol = maxen[i] | |
173 name = names[i] | |
174 sepcols.append("-" * maxcol) # formats column names (header) | |
175 names[i] = name + (" " * (maxcol-len(name))) # formats separ line with -- | |
176 rrows2 = range(len(toprint)) | |
177 for j in rrows2: | |
178 val = toprint[j][i] | |
179 if str(desc[i][1]) == "<type 'cx_Oracle.NUMBER'>": # right align numbers | |
180 toprint[j][i] = (" " * (maxcol-len(val))) + val | |
181 else: | |
182 toprint[j][i] = val + (" " * (maxcol-len(val))) | |
183 for j in rrows2: | |
184 toprint[j] = ' '.join(toprint[j]) | |
185 names = ' '.join(names) | |
186 sepcols = ' '.join(sepcols) | |
187 toprint.insert(0, sepcols) | |
188 toprint.insert(0, names) | |
189 return '\n'.join(toprint) | |
190 |