Repository navigation
Expand file tree
/
Copy pathscratch.py
More file actions
311 lines (236 loc) · 9.15 KB
/
Copy pathscratch.py
File metadata and controls
311 lines (236 loc) · 9.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
class DBMagicSource(object):
def __init__(self, odbc_args):
"""
:param odbc_args: the arguments parsed from @magic_arguments
:returns: formatted string
"""
pass
def explain(self, alias, key, cmd, fetch, args, line):
"""
Explains the operations that are going to be done as part of the command line invocation
:param alias: the plain english name to associate with this connection
:param type: the type of connection to use
:param key: the key that will be used to find the correct connection.
:param cmd: the command that will be executed
:param fetch: the argument for fetching data or not
:param args: all the arguments passed to the class
:param line: the command line used to call the class
"""
pass
def connect_to_source(self, connection_source, username=None, password=None):
"""
Establishes a connection to a data source and removes the alias.
:param connection_source: the name of an an ODBC DSN or connection string
:param username: the username to use for a connection (optional)
:param password: connection_source: the password to use for a connection (optional)
:returns: formatted string
"""
pass
def disconnect_from_source(self):
"""
Disconnects a particular connection to a data source and removes the alias.
"""
pass
def execute_command(self, command, fetch):
"""
Execute a command on a remote data source
NOTE: this will not return a value, just execute the command. Use fetch()
:param command: the command to execute at the connection
"""
pass
def fetch(self, fetch):
"""
Fetch the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
:param fetch: how many records to fetch, either a positive integer or 'all'
"""
pass
def commit(self):
"""
commit the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
"""
pass
def list_values(self, list_value):
"""
commit the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
:param list_value: the thing inside the database to list
"""
pass
def cleanup(self):
" shutting down all connections properly"
pass
def __del__(self):
self.cleanup()
class ODBCSource(DBMagicSource):
self._connection = None
self._cursor = None
self._is_connected = False
def __init__self, odbc_args):
"""
:param odbc_args: the arguments parsed from @magic_arguments
:returns: formatted string
"""
pass
def explain(self, alias, key, cmd, fetch, args, line):
"""
Explains the operations that are going to be done as part of the command line invocation
:param alias: the plain english name to associate with this connection
:param type: the type of connection to use
:param key: the key that will be used to find the correct connection.
:param cmd: the command that will be executed
:param fetch: the argument for fetching data or not
:param args: all the arguments passed to the class
:param line: the command line used to call the class
"""
print("Command Line called : %%db %s" % line)
print("-------------------")
print("Args Parsed: %s" % args)
print("-------------------")
print("Data Source to Use: %s" % args.source)
print("Data Source Type: %s" % args.type)
print("Data Source Alias: %s" % alias)
print("Command to Execute: %s" % cmd)
print("Execution Notes: %s" % str(args.note))
print("-------------------")
print("Open Connections: %s" % self._conn_info)
print("-------------------")
print("Is this a Naked Query?: %s" % args.naked)
print("Is this a Unsourced Query?: %s" % args.unsourced)
print("-------------------")
print("Are we Connecting to DB?: %s" % (args.connect or args.naked))
print("Are we Commiting Transaction?: %s" % (args.commit))
print("Are we Fetching records?: %s" % fetch)
print("Are we Listing values?: %s" % args.list)
print("Are we Disconnecting from DB?: %s" % (args.disconnect or args.naked))
print("=========================================================")
def connect_to_source(self, connection_source, username=None, password=None):
"""
Establishes a connection to a data source and removes the alias.
:param connection_source: the name of an an ODBC DSN or connection string
:param username: the username to use for a connection (optional)
:param password: connection_source: the password to use for a connection (optional)
:returns: formatted string
"""
try:
logging.debug("Attempting to connect")
if (len(username) > 0 and len(password) > 0):
self._connection = pyodbc.connect(connection_source,uid=username,pwd=password)
else:
self._connection = pyodbc.connect(connection_source)
self._cursor = self._connection.cursor()
self._is_connected = True
except pyodbc.Error, err:
logging.error(self._connection)
logging.error(err[1])
raise err
def disconnect_from_source(self):
"""
Disconnects a particular connection to a data source and removes the alias.
"""
try:
logging.debug("Attempting to disconnect")
cursor = self._cursor.close()
cnxn = self._connection.close()
self._is_connected = False
except pyodbc.Error, err:
logging.error(err[1])
raise err
logging.debug("Disconnected data source")
def execute_command(self, command, fetch):
"""
Execute a command on a remote data source
NOTE: this will not return a value, just execute the command. Use fetch()
:param command: the command to execute at the connection
"""
if len(command) > 0:
try:
logging.debug("Attempting to execute '%s'" % command)
self.__cursor.execute(command)
except pyodbc.Error, err:
logging.error(err[1])
raise err
else:
logging.debug("Skipping empty command.")
def fetch(self, fetch):
"""
Fetch the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
:param fetch: how many records to fetch, either a positive integer or 'all'
"""
try:
cursor = self._cursor
description = []
if (isinstance(fetch, str) or isinstance(fetch, unicode)) and 'all' in fetch:
logging.debug("Running cursor.fetchall()")
return cursor.fetchall()
elif (long(fetch) == 0):
logging.debug("Running cursor.fetchall()")
return cursor.fetchall()
elif long(fetch) > 0:
logging.debug("Running cursor.fetchmany(%s)" % long(fetch))
return cursor.fetchmany(long(fetch))
else:
logging.debug("'%s' is an invalid number of rows to fetch" % fetch)
except pyodbc.ProgrammingError, err:
logging.warning(err)
pass
except pyodbc.Error, err:
logging.error(err)
raise err
def commit(self):
"""
commit the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
"""
logging.debug("Commiting cursor")
if not self.is_connected:
logging.debug("The alias '%s' is not connected" % connection_alias)
return
try:
self._cursor.commit()
except pyodbc.Error, err:
logging.error(err)
def list_values(self, list_value):
"""
commit the results from a previous command. This is always used in conjunction
with the execute_command() function, either implicitly or explicitly.
:param list_value: the thing inside the database to list
"""
if not self._is_connected and list_value != 'sources':
logging.debug("This object is not connected")
return
try:
logging.debug("The list value is '%s'" % list_value)
results = []
if list_value == 'tables':
logging.debug("Listing tables.)
cursor = self._cursor
for row in cursor.tables():
results.append(row)
elif list_value == 'procedures':
logging.debug("Listing procedures.)
cursor = self._conn_info[connection_alias]['cursor']
for row in cursor.procedures():
results.append(row)
elif list_value == 'sources':
logging.debug("Listing sources in")
for row in pyodbc.dataSources():
results.append(row)
else:
raise Exception(stack()[0][3], "The list value provided ('%s') is not valid. No connection made" % list_value)
return results
def cleanup(self):
" shutting down all connections properly"
shutdown_had_problems = False
try:
logging.debug("Closing %s" % alias)
self.disconnect_from_source()
except err:
logging.warning("There was a problem shutting down")
shutdown_had_problems = True
finally:
if shutdown_had_problems:
raise Exception(stack()[0][3], \
"This object could not be shut down.")