Mercurial > p > mysql-python > mysqldb-2
comparison MySQLdb/cursors.py @ 67:98d968f5af11 MySQLdb
Reimplement MySQL->Python type conversion in C; much simpler and easier to deal with now. Hey, all my tests pass, so I guess that means I need to write some more tests.
author | adustman |
---|---|
date | Mon, 30 Mar 2009 20:21:24 +0000 |
parents | 5a7c30cd9de2 |
children | 29b4cfd9af07 |
comparison
equal
deleted
inserted
replaced
66:5a7c30cd9de2 | 67:98d968f5af11 |
---|---|
43 InternalError, ProgrammingError, NotSupportedError | 43 InternalError, ProgrammingError, NotSupportedError |
44 | 44 |
45 _defer_warnings = False | 45 _defer_warnings = False |
46 _fetch_type = None | 46 _fetch_type = None |
47 | 47 |
48 def __init__(self, connection, decoders, encoders): | 48 def __init__(self, connection, encoders): |
49 from MySQLdb.converters import default_decoders | 49 from MySQLdb.converters import default_decoders |
50 self.connection = weakref.proxy(connection) | 50 self.connection = weakref.proxy(connection) |
51 self.description = None | 51 self.description = None |
52 self.description_flags = None | 52 self.description_flags = None |
53 self.rowcount = -1 | 53 self.rowcount = -1 |
58 self.errorhandler = connection.errorhandler | 58 self.errorhandler = connection.errorhandler |
59 self._result = None | 59 self._result = None |
60 self._warnings = 0 | 60 self._warnings = 0 |
61 self._info = None | 61 self._info = None |
62 self.rownumber = None | 62 self.rownumber = None |
63 self._decoders = decoders | 63 self._encoders = encoders |
64 | 64 |
65 def __del__(self): | 65 def __del__(self): |
66 self.close() | 66 self.close() |
67 self.errorhandler = None | 67 self.errorhandler = None |
68 self._result = None | 68 self._result = None |
115 self._do_get_result() | 115 self._do_get_result() |
116 self._post_get_result() | 116 self._post_get_result() |
117 self._warning_check() | 117 self._warning_check() |
118 return True | 118 return True |
119 | 119 |
120 def _lookup_decoder(self, field): | |
121 from MySQLdb.converters import filter_NULL | |
122 for plugin in self._decoders: | |
123 f = plugin(field) | |
124 if f: | |
125 return filter_NULL(f) | |
126 return None # this should never happen | |
127 | |
128 def _do_get_result(self): | 120 def _do_get_result(self): |
129 """Get the result from the last query.""" | 121 """Get the result from the last query.""" |
130 connection = self._get_db() | 122 connection = self._get_db() |
131 self._result = self._get_result() | 123 self._result = self._get_result() |
132 if self._result: | |
133 self.sql_to_python = [ | |
134 self._lookup_decoder(f) | |
135 for f in self._result.fields() | |
136 ] | |
137 else: | |
138 self.sql_to_python = [] | |
139 self.rowcount = connection.affected_rows() | 124 self.rowcount = connection.affected_rows() |
140 self.rownumber = 0 | 125 self.rownumber = 0 |
141 self.description = self._result and self._result.describe() or None | 126 self.description = self._result and self._result.describe() or None |
142 self.description_flags = self._result and self._result.field_flags() or None | 127 self.description_flags = self._result and self._result.field_flags() or None |
143 self.lastrowid = connection.insert_id() | 128 self.lastrowid = connection.insert_id() |
174 del self.messages[:] | 159 del self.messages[:] |
175 db = self._get_db() | 160 db = self._get_db() |
176 charset = db.character_set_name() | 161 charset = db.character_set_name() |
177 if isinstance(query, unicode): | 162 if isinstance(query, unicode): |
178 query = query.encode(charset) | 163 query = query.encode(charset) |
179 if args is not None: | |
180 query = query % self.connection.literal(args) | |
181 try: | 164 try: |
165 if args is not None: | |
166 query = query % tuple(map(self.connection.literal, args)) | |
182 result = self._query(query) | 167 result = self._query(query) |
183 except TypeError, msg: | 168 except TypeError, msg: |
184 if msg.args[0] in ("not enough arguments for format string", | 169 if msg.args[0] in ("not enough arguments for format string", |
185 "not all arguments converted"): | 170 "not all arguments converted"): |
186 self.messages.append((self.ProgrammingError, msg.args[0])) | 171 self.messages.append((self.ProgrammingError, msg.args[0])) |
233 start = matched.group('start') | 218 start = matched.group('start') |
234 end = matched.group('end') | 219 end = matched.group('end') |
235 values = matched.group('values') | 220 values = matched.group('values') |
236 | 221 |
237 try: | 222 try: |
238 sql_params = [ values % self.connection.literal(arg) for arg in args ] | 223 sql_params = ( values % tuple(map(self.connection.literal, row)) for row in args ) |
224 multirow_query = '\n'.join([start, ',\n'.join(sql_params), end]) | |
225 self._executed = multirow_query | |
226 self.rowcount = int(self._query(multirow_query)) | |
227 | |
239 except TypeError, msg: | 228 except TypeError, msg: |
240 if msg.args[0] in ("not enough arguments for format string", | 229 if msg.args[0] in ("not enough arguments for format string", |
241 "not all arguments converted"): | 230 "not all arguments converted"): |
242 self.messages.append((self.ProgrammingError, msg.args[0])) | 231 self.messages.append((self.ProgrammingError, msg.args[0])) |
243 self.errorhandler(self, self.ProgrammingError, msg.args[0]) | 232 self.errorhandler(self, self.ProgrammingError, msg.args[0]) |
246 self.errorhandler(self, TypeError, msg) | 235 self.errorhandler(self, TypeError, msg) |
247 except: | 236 except: |
248 exc, value, traceback = sys.exc_info() | 237 exc, value, traceback = sys.exc_info() |
249 del traceback | 238 del traceback |
250 self.errorhandler(self, exc, value) | 239 self.errorhandler(self, exc, value) |
251 self.rowcount = int(self._query( | 240 |
252 '\n'.join([start, ',\n'.join(sql_params), end, | |
253 ]))) | |
254 if not self._defer_warnings: | 241 if not self._defer_warnings: |
255 self._warning_check() | 242 self._warning_check() |
256 return self.rowcount | 243 return self.rowcount |
257 | 244 |
258 def callproc(self, procname, args=()): | 245 def callproc(self, procname, args=()): |
317 | 304 |
318 def _fetch_row(self, size=1): | 305 def _fetch_row(self, size=1): |
319 """Low-level fetch_row wrapper.""" | 306 """Low-level fetch_row wrapper.""" |
320 if not self._result: | 307 if not self._result: |
321 return () | 308 return () |
322 # unfortunately it is necessary to wrap these generators up as tuples | 309 return self._result.fetch_row(size, self._fetch_type) |
323 # as the rows are expected to be subscriptable. | |
324 return tuple( | |
325 ( | |
326 tuple( ( f(x) for f, x in zip(self.sql_to_python, row) ) ) | |
327 for row in self._result.fetch_row(size, self._fetch_type) | |
328 ) | |
329 ) | |
330 | 310 |
331 def __iter__(self): | 311 def __iter__(self): |
332 return iter(self.fetchone, None) | 312 return iter(self.fetchone, None) |
333 | 313 |
334 def _get_result(self): | 314 def _get_result(self): |