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):