Mercurial > p > mysql-python > mysqldb-2
annotate MySQLdb/cursors.py @ 51:6122b2cacd20 MySQLdb
set and frozenset always available in Python 2.4 and newer
author | adustman |
---|---|
date | Sun, 22 Feb 2009 20:09:56 +0000 |
parents | 10038670b963 |
children | 6e31278d3433 |
rev | line source |
---|---|
14 | 1 """ |
2 MySQLdb Cursors | |
3 --------------- | |
0 | 4 |
5 This module implements Cursors of various types for MySQLdb. By | |
6 default, MySQLdb uses the Cursor class. | |
7 | |
8 """ | |
9 | |
14 | 10 __revision__ = "$Revision$"[11:-2] |
11 __author__ = "$Author$"[9:-2] | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
12 |
0 | 13 import re |
14 | |
31 | 15 INSERT_VALUES = re.compile(r"\svalues\s*" |
16 r"(\(((?<!\\)'[^\)]*?\)[^\)]*(?<!\\)?'" | |
17 r"|[^\(\)]|" | |
18 r"(?:\([^\)]*\))" | |
19 r")+\))") | |
0 | 20 |
21 class BaseCursor(object): | |
22 | |
23 """A base for Cursor classes. Useful attributes: | |
24 | |
25 description | |
26 A tuple of DB API 7-tuples describing the columns in | |
27 the last executed query; see PEP-249 for details. | |
28 | |
29 description_flags | |
30 Tuple of column flags for last query, one entry per column | |
31 in the result set. Values correspond to those in | |
32 MySQLdb.constants.FLAG. See MySQL documentation (C API) | |
33 for more information. Non-standard extension. | |
34 | |
35 arraysize | |
36 default number of rows fetchmany() will fetch | |
37 | |
38 """ | |
39 | |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
40 from MySQLdb.exceptions import MySQLError, Warning, Error, InterfaceError, \ |
0 | 41 DatabaseError, DataError, OperationalError, IntegrityError, \ |
42 InternalError, ProgrammingError, NotSupportedError | |
4 | 43 |
44 _defer_warnings = False | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
45 _fetch_type = None |
4 | 46 |
0 | 47 def __init__(self, connection): |
48 from weakref import proxy | |
49 | |
50 self.connection = proxy(connection) | |
51 self.description = None | |
52 self.description_flags = None | |
53 self.rowcount = -1 | |
54 self.arraysize = 1 | |
55 self._executed = None | |
56 self.lastrowid = None | |
57 self.messages = [] | |
58 self.errorhandler = connection.errorhandler | |
59 self._result = None | |
60 self._warnings = 0 | |
61 self._info = None | |
62 self.rownumber = None | |
63 | |
64 def __del__(self): | |
65 self.close() | |
66 self.errorhandler = None | |
67 self._result = None | |
68 | |
69 def close(self): | |
70 """Close the cursor. No further queries will be possible.""" | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
71 if not self.connection: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
72 return |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
73 try: |
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
74 while self.nextset(): |
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
75 pass |
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
76 except: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
77 pass |
0 | 78 self.connection = None |
79 | |
80 def _check_executed(self): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
81 """Ensure that .execute() has been called.""" |
0 | 82 if not self._executed: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
83 self.errorhandler(self, self.ProgrammingError, "execute() first") |
0 | 84 |
85 def _warning_check(self): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
86 """Check for warnings, and report via the warnings module.""" |
0 | 87 from warnings import warn |
88 if self._warnings: | |
89 warnings = self._get_db().show_warnings() | |
90 if warnings: | |
91 # This is done in two loops in case | |
92 # Warnings are set to raise exceptions. | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
93 for warning in warnings: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
94 self.messages.append((self.Warning, warning)) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
95 for warning in warnings: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
96 warn(warning[-1], self.Warning, 3) |
0 | 97 elif self._info: |
98 self.messages.append((self.Warning, self._info)) | |
99 warn(self._info, self.Warning, 3) | |
100 | |
101 def nextset(self): | |
102 """Advance to the next result set. | |
103 | |
104 Returns None if there are no more result sets. | |
105 """ | |
106 if self._executed: | |
107 self.fetchall() | |
108 del self.messages[:] | |
109 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
110 connection = self._get_db() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
111 num_rows = connection.next_result() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
112 if num_rows == -1: |
0 | 113 return None |
114 self._do_get_result() | |
115 self._post_get_result() | |
116 self._warning_check() | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
117 return True |
0 | 118 |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
119 def _post_get_result(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
120 """Stub to be overridden by MixIn.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
121 |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
122 def _get_result(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
123 """Stub to be overridden by MixIn.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
124 return [] |
0 | 125 |
126 def _do_get_result(self): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
127 """Get the result from the last query.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
128 connection = self._get_db() |
0 | 129 self._result = self._get_result() |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
130 self.rowcount = connection.affected_rows() |
0 | 131 self.rownumber = 0 |
132 self.description = self._result and self._result.describe() or None | |
133 self.description_flags = self._result and self._result.field_flags() or None | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
134 self.lastrowid = connection.insert_id() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
135 self._warnings = connection.warning_count() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
136 self._info = connection.info() |
0 | 137 |
138 def setinputsizes(self, *args): | |
139 """Does nothing, required by DB API.""" | |
140 | |
141 def setoutputsizes(self, *args): | |
142 """Does nothing, required by DB API.""" | |
143 | |
144 def _get_db(self): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
145 """Get the database connection. |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
146 |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
147 Raises ProgrammingError if the connection has been closed.""" |
0 | 148 if not self.connection: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
149 self.errorhandler(self, self.ProgrammingError, "cursor closed") |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
150 return self.connection._db |
0 | 151 |
152 def execute(self, query, args=None): | |
153 """Execute a query. | |
154 | |
155 query -- string, query to execute on server | |
156 args -- optional sequence or mapping, parameters to use with query. | |
157 | |
158 Note: If args is a sequence, then %s must be used as the | |
159 parameter placeholder in the query. If a mapping is used, | |
160 %(key)s must be used as the placeholder. | |
161 | |
162 Returns long integer rows affected, if any | |
163 | |
164 """ | |
165 from sys import exc_info | |
166 del self.messages[:] | |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
167 db = self._get_db() |
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
168 charset = db.character_set_name() |
4 | 169 if isinstance(query, unicode): |
170 query = query.encode(charset) | |
0 | 171 if args is not None: |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
172 query = query % self.connection.literal(args) |
0 | 173 try: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
174 result = self._query(query) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
175 except TypeError, msg: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
176 if msg.args[0] in ("not enough arguments for format string", |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
177 "not all arguments converted"): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
178 self.messages.append((self.ProgrammingError, msg.args[0])) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
179 self.errorhandler(self, self.ProgrammingError, msg.args[0]) |
0 | 180 else: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
181 self.messages.append((TypeError, msg)) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
182 self.errorhandler(self, TypeError, msg) |
0 | 183 except: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
184 exc, value, traceback = exc_info() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
185 del traceback |
0 | 186 self.messages.append((exc, value)) |
187 self.errorhandler(self, exc, value) | |
188 self._executed = query | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
189 if not self._defer_warnings: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
190 self._warning_check() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
191 return result |
0 | 192 |
193 def executemany(self, query, args): | |
194 """Execute a multi-row query. | |
195 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
196 query |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
197 |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
198 string, query to execute on server |
0 | 199 |
200 args | |
201 | |
202 Sequence of sequences or mappings, parameters to use with | |
203 query. | |
204 | |
205 Returns long integer rows affected, if any. | |
206 | |
207 This method improves performance on multiple-row INSERT and | |
208 REPLACE. Otherwise it is equivalent to looping over args with | |
209 execute(). | |
210 | |
211 """ | |
212 del self.messages[:] | |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
213 db = self._get_db() |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
214 if not args: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
215 return |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
216 charset = self.connection.character_set_name() |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
217 if isinstance(query, unicode): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
218 query = query.encode(charset) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
219 matched = INSERT_VALUES.match(query) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
220 if not matched: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
221 self.rowcount = sum([ self.execute(query, arg) for arg in args ]) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
222 return self.rowcount |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
223 |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
224 start = matched.group('start') |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
225 end = matched.group('end') |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
226 values = matched.group('values') |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
227 |
0 | 228 try: |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
229 sql_params = [ values % self.connection.literal(arg) for arg in args ] |
0 | 230 except TypeError, msg: |
231 if msg.args[0] in ("not enough arguments for format string", | |
232 "not all arguments converted"): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
233 self.messages.append((self.ProgrammingError, msg.args[0])) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
234 self.errorhandler(self, self.ProgrammingError, msg.args[0]) |
0 | 235 else: |
236 self.messages.append((TypeError, msg)) | |
237 self.errorhandler(self, TypeError, msg) | |
238 except: | |
239 from sys import exc_info | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
240 exc, value, traceback = exc_info() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
241 del traceback |
0 | 242 self.errorhandler(self, exc, value) |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
243 self.rowcount = int(self._query( |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
244 '\n'.join([start, ',\n'.join(sql_params), end, |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
245 ]))) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
246 if not self._defer_warnings: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
247 self._warning_check() |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
248 return self.rowcount |
0 | 249 |
250 def callproc(self, procname, args=()): | |
251 """Execute stored procedure procname with args | |
252 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
253 procname |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
254 string, name of procedure to execute on server |
0 | 255 |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
256 args |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
257 Sequence of parameters to use with procedure |
0 | 258 |
259 Returns the original args. | |
260 | |
261 Compatibility warning: PEP-249 specifies that any modified | |
262 parameters must be returned. This is currently impossible | |
263 as they are only available by storing them in a server | |
264 variable and then retrieved by a query. Since stored | |
265 procedures return zero or more result sets, there is no | |
266 reliable way to get at OUT or INOUT parameters via callproc. | |
267 The server variables are named @_procname_n, where procname | |
268 is the parameter above and n is the position of the parameter | |
269 (from zero). Once all result sets generated by the procedure | |
270 have been fetched, you can issue a SELECT @_procname_0, ... | |
271 query using .execute() to get any OUT or INOUT values. | |
272 | |
273 Compatibility warning: The act of calling a stored procedure | |
274 itself creates an empty result set. This appears after any | |
275 result sets generated by the procedure. This is non-standard | |
276 behavior with respect to the DB-API. Be sure to use nextset() | |
277 to advance through all result sets; otherwise you may get | |
278 disconnected. | |
279 """ | |
280 | |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
281 db = self._get_db() |
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
282 charset = self.connection.character_set_name() |
0 | 283 for index, arg in enumerate(args): |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
284 query = "SET @_%s_%d=%s" % (procname, index, |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
285 self.connection.literal(arg)) |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
286 if isinstance(query, unicode): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
287 query = query.encode(charset) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
288 self._query(query) |
0 | 289 self.nextset() |
290 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
291 query = "CALL %s(%s)" % (procname, |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
292 ','.join(['@_%s_%d' % (procname, i) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
293 for i in range(len(args))])) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
294 if isinstance(query, unicode): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
295 query = query.encode(charset) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
296 self._query(query) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
297 self._executed = query |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
298 if not self._defer_warnings: |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
299 self._warning_check() |
0 | 300 return args |
301 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
302 def _do_query(self, query): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
303 """Low-levey query wrapper. Overridden by MixIns.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
304 connection = self._get_db() |
18
d55bfb1a4701
Tons of changes from major refactoring/cleanup. This is all really broken
adustman
parents:
14
diff
changeset
|
305 self._executed = query |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
306 connection.query(query) |
0 | 307 self._do_get_result() |
308 return self.rowcount | |
309 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
310 def _query(self, query): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
311 """Hook for _do_query.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
312 return self._do_query(query) |
0 | 313 |
314 def _fetch_row(self, size=1): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
315 """Low-level fetch_row wrapper.""" |
0 | 316 if not self._result: |
317 return () | |
318 return self._result.fetch_row(size, self._fetch_type) | |
319 | |
320 def __iter__(self): | |
321 return iter(self.fetchone, None) | |
322 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
323 def fetchone(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
324 """Stub to be overridden by a MixIn.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
325 return None |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
326 |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
327 def fetchall(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
328 """Stub to be overridden by a MixIn.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
329 return [] |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
330 |
0 | 331 |
332 class CursorStoreResultMixIn(object): | |
333 | |
334 """This is a MixIn class which causes the entire result set to be | |
335 stored on the client side, i.e. it uses mysql_store_result(). If the | |
336 result set can be very large, consider adding a LIMIT clause to your | |
337 query, or using CursorUseResultMixIn instead.""" | |
338 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
339 def _get_result(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
340 """Low-level; uses mysql_store_result()""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
341 return self._get_db().store_result() |
0 | 342 |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
343 def _query(self, query): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
344 """Low-level; executes query, gets result, and returns rowcount.""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
345 rowcount = self._do_query(query) |
0 | 346 self._post_get_result() |
347 return rowcount | |
348 | |
349 def _post_get_result(self): | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
350 """Low-level""" |
0 | 351 self._rows = self._fetch_row(0) |
352 self._result = None | |
353 | |
354 def fetchone(self): | |
355 """Fetches a single row from the cursor. None indicates that | |
356 no more rows are available.""" | |
357 self._check_executed() | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
358 if self.rownumber >= len(self._rows): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
359 return None |
0 | 360 result = self._rows[self.rownumber] |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
361 self.rownumber += 1 |
0 | 362 return result |
363 | |
364 def fetchmany(self, size=None): | |
365 """Fetch up to size rows from the cursor. Result set may be smaller | |
366 than size. If size is not defined, cursor.arraysize is used.""" | |
367 self._check_executed() | |
368 end = self.rownumber + (size or self.arraysize) | |
369 result = self._rows[self.rownumber:end] | |
370 self.rownumber = min(end, len(self._rows)) | |
371 return result | |
372 | |
373 def fetchall(self): | |
374 """Fetchs all available rows from the cursor.""" | |
375 self._check_executed() | |
376 if self.rownumber: | |
377 result = self._rows[self.rownumber:] | |
378 else: | |
379 result = self._rows | |
380 self.rownumber = len(self._rows) | |
381 return result | |
382 | |
383 def scroll(self, value, mode='relative'): | |
384 """Scroll the cursor in the result set to a new position according | |
385 to mode. | |
386 | |
387 If mode is 'relative' (default), value is taken as offset to | |
388 the current position in the result set, if set to 'absolute', | |
389 value states an absolute target position.""" | |
390 self._check_executed() | |
391 if mode == 'relative': | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
392 row = self.rownumber + value |
0 | 393 elif mode == 'absolute': |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
394 row = value |
0 | 395 else: |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
396 self.errorhandler(self, self.ProgrammingError, |
0 | 397 "unknown scroll mode %s" % `mode`) |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
398 if row < 0 or row >= len(self._rows): |
0 | 399 self.errorhandler(self, IndexError, "out of range") |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
400 self.rownumber = row |
0 | 401 |
402 def __iter__(self): | |
403 self._check_executed() | |
404 result = self.rownumber and self._rows[self.rownumber:] or self._rows | |
405 return iter(result) | |
406 | |
407 | |
408 class CursorUseResultMixIn(object): | |
409 | |
410 """This is a MixIn class which causes the result set to be stored | |
411 in the server and sent row-by-row to client side, i.e. it uses | |
412 mysql_use_result(). You MUST retrieve the entire result set and | |
413 close() the cursor before additional queries can be peformed on | |
414 the connection.""" | |
415 | |
4 | 416 _defer_warnings = True |
417 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
418 def _get_result(self): |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
419 """Low-level; calls mysql_use_result()""" |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
420 return self._get_db().use_result() |
0 | 421 |
422 def fetchone(self): | |
423 """Fetches a single row from the cursor.""" | |
424 self._check_executed() | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
425 rows = self._fetch_row(1) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
426 if not rows: |
4 | 427 self._warning_check() |
428 return None | |
0 | 429 self.rownumber = self.rownumber + 1 |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
430 return rows[0] |
0 | 431 |
432 def fetchmany(self, size=None): | |
433 """Fetch up to size rows from the cursor. Result set may be smaller | |
434 than size. If size is not defined, cursor.arraysize is used.""" | |
435 self._check_executed() | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
436 rows = self._fetch_row(size or self.arraysize) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
437 self.rownumber = self.rownumber + len(rows) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
438 if not rows: |
4 | 439 self._warning_check() |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
440 return rows |
0 | 441 |
442 def fetchall(self): | |
443 """Fetchs all available rows from the cursor.""" | |
444 self._check_executed() | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
445 rows = self._fetch_row(0) |
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
446 self.rownumber = self.rownumber + len(rows) |
4 | 447 self._warning_check() |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
448 return rows |
0 | 449 |
450 def __iter__(self): | |
451 return self | |
452 | |
453 def next(self): | |
454 row = self.fetchone() | |
455 if row is None: | |
456 raise StopIteration | |
457 return row | |
458 | |
459 | |
460 class CursorTupleRowsMixIn(object): | |
461 | |
462 """This is a MixIn class that causes all rows to be returned as tuples, | |
463 which is the standard form required by DB API.""" | |
464 | |
465 _fetch_type = 0 | |
466 | |
467 | |
468 class CursorDictRowsMixIn(object): | |
469 | |
470 """This is a MixIn class that causes all rows to be returned as | |
471 dictionaries. This is a non-standard feature.""" | |
472 | |
473 _fetch_type = 1 | |
474 | |
475 | |
476 class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn, | |
477 BaseCursor): | |
478 | |
479 """This is the standard Cursor class that returns rows as tuples | |
480 and stores the result set in the client.""" | |
481 | |
482 | |
483 class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn, | |
484 BaseCursor): | |
485 | |
10
3f4c6af70e52
Me and PyLint had a knife fight, but PyLint had a gun.
adustman
parents:
8
diff
changeset
|
486 """This is a Cursor class that returns rows as dictionaries and |
0 | 487 stores the result set in the client.""" |
488 | |
489 | |
490 class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn, | |
491 BaseCursor): | |
492 | |
493 """This is a Cursor class that returns rows as tuples and stores | |
494 the result set in the server.""" | |
495 | |
496 | |
497 class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn, | |
498 BaseCursor): | |
499 | |
500 """This is a Cursor class that returns rows as dictionaries and | |
501 stores the result set in the server.""" | |
502 | |
503 |