comparison MySQLdb/cursors.py @ 64:2d6a35051f64 MySQLdb

Cursor MixIns: DEAD. More of the new type conversion scheme exposed. Two tests failing because encoding hasn't been finished yet.
author adustman
date Sat, 28 Mar 2009 13:37:58 +0000
parents 9ea2b0e9302e
children 7a60c4574baf
comparison
equal deleted inserted replaced
63:34176b94a93f 64:2d6a35051f64
18 r"(\(((?<!\\)'[^\)]*?\)[^\)]*(?<!\\)?'" 18 r"(\(((?<!\\)'[^\)]*?\)[^\)]*(?<!\\)?'"
19 r"|[^\(\)]|" 19 r"|[^\(\)]|"
20 r"(?:\([^\)]*\))" 20 r"(?:\([^\)]*\))"
21 r")+\))") 21 r")+\))")
22 22
23 class BaseCursor(object): 23
24 class Cursor(object):
24 25
25 """A base for Cursor classes. Useful attributes: 26 """A base for Cursor classes. Useful attributes:
26 27
27 description 28 description
28 A tuple of DB API 7-tuples describing the columns in 29 A tuple of DB API 7-tuples describing the columns in
44 InternalError, ProgrammingError, NotSupportedError 45 InternalError, ProgrammingError, NotSupportedError
45 46
46 _defer_warnings = False 47 _defer_warnings = False
47 _fetch_type = None 48 _fetch_type = None
48 49
49 def __init__(self, connection): 50 def __init__(self, connection, decoders, encoders):
51 from MySQLdb.converters import default_decoders
50 self.connection = weakref.proxy(connection) 52 self.connection = weakref.proxy(connection)
51 self.description = None 53 self.description = None
52 self.description_flags = None 54 self.description_flags = None
53 self.rowcount = -1 55 self.rowcount = -1
54 self.arraysize = 1 56 self.arraysize = 1
58 self.errorhandler = connection.errorhandler 60 self.errorhandler = connection.errorhandler
59 self._result = None 61 self._result = None
60 self._warnings = 0 62 self._warnings = 0
61 self._info = None 63 self._info = None
62 self.rownumber = None 64 self.rownumber = None
65 self._decoders = decoders
63 66
64 def __del__(self): 67 def __del__(self):
65 self.close() 68 self.close()
66 self.errorhandler = None 69 self.errorhandler = None
67 self._result = None 70 self._result = None
114 self._do_get_result() 117 self._do_get_result()
115 self._post_get_result() 118 self._post_get_result()
116 self._warning_check() 119 self._warning_check()
117 return True 120 return True
118 121
119 def _post_get_result(self): 122 def _lookup_decoder(self, field):
120 """Stub to be overridden by MixIn.""" 123 from MySQLdb.converters import filter_NULL
121 124 for plugin in self._decoders:
122 def _get_result(self): 125 f = plugin(self, field)
123 """Stub to be overridden by MixIn.""" 126 if f:
124 return [] 127 return filter_NULL(f)
125 128 return None # this should never happen
129
126 def _do_get_result(self): 130 def _do_get_result(self):
127 """Get the result from the last query.""" 131 """Get the result from the last query."""
128 from MySQLdb.converters import lookup_converter
129 connection = self._get_db() 132 connection = self._get_db()
130 self._result = self._get_result() 133 self._result = self._get_result()
131 if self._result: 134 if self._result:
132 self.sql_to_python = [ 135 self.sql_to_python = [
133 lookup_converter(self, f) 136 self._lookup_decoder(f)
134 for f in self._result.fields() 137 for f in self._result.fields()
135 ] 138 ]
136 else: 139 else:
137 self.sql_to_python = [] 140 self.sql_to_python = []
138 self.rowcount = connection.affected_rows() 141 self.rowcount = connection.affected_rows()
332 ) 335 )
333 336
334 def __iter__(self): 337 def __iter__(self):
335 return iter(self.fetchone, None) 338 return iter(self.fetchone, None)
336 339
337 def fetchone(self):
338 """Stub to be overridden by a MixIn."""
339 return None
340
341 def fetchall(self):
342 """Stub to be overridden by a MixIn."""
343 return []
344
345
346 class CursorStoreResultMixIn(object):
347
348 """This is a MixIn class which causes the entire result set to be
349 stored on the client side, i.e. it uses mysql_store_result(). If the
350 result set can be very large, consider adding a LIMIT clause to your
351 query, or using CursorUseResultMixIn instead."""
352
353 def _get_result(self): 340 def _get_result(self):
354 """Low-level; uses mysql_store_result()""" 341 """Low-level; uses mysql_store_result()"""
355 return self._get_db().store_result() 342 return self._get_db().store_result()
356 343
357 def _query(self, query): 344 def _query(self, query):
416 def __iter__(self): 403 def __iter__(self):
417 self._check_executed() 404 self._check_executed()
418 result = self.rownumber and self._rows[self.rownumber:] or self._rows 405 result = self.rownumber and self._rows[self.rownumber:] or self._rows
419 return iter(result) 406 return iter(result)
420 407
421
422 class CursorUseResultMixIn(object):
423
424 """This is a MixIn class which causes the result set to be stored
425 in the server and sent row-by-row to client side, i.e. it uses
426 mysql_use_result(). You MUST retrieve the entire result set and
427 close() the cursor before additional queries can be peformed on
428 the connection."""
429
430 _defer_warnings = True
431
432 def _get_result(self):
433 """Low-level; calls mysql_use_result()"""
434 return self._get_db().use_result()
435
436 def fetchone(self):
437 """Fetches a single row from the cursor."""
438 self._check_executed()
439 rows = self._fetch_row(1)
440 if not rows:
441 self._warning_check()
442 return None
443 self.rownumber = self.rownumber + 1
444 return rows[0]
445
446 def fetchmany(self, size=None):
447 """Fetch up to size rows from the cursor. Result set may be smaller
448 than size. If size is not defined, cursor.arraysize is used."""
449 self._check_executed()
450 rows = self._fetch_row(size or self.arraysize)
451 self.rownumber = self.rownumber + len(rows)
452 if not rows:
453 self._warning_check()
454 return rows
455
456 def fetchall(self):
457 """Fetchs all available rows from the cursor."""
458 self._check_executed()
459 rows = self._fetch_row(0)
460 self.rownumber = self.rownumber + len(rows)
461 self._warning_check()
462 return rows
463
464 def __iter__(self):
465 return self
466
467 def next(self):
468 row = self.fetchone()
469 if row is None:
470 raise StopIteration
471 return row
472
473
474 class CursorTupleRowsMixIn(object):
475
476 """This is a MixIn class that causes all rows to be returned as tuples,
477 which is the standard form required by DB API."""
478
479 _fetch_type = 0 408 _fetch_type = 0
480
481
482 class CursorDictRowsMixIn(object):
483
484 """This is a MixIn class that causes all rows to be returned as
485 dictionaries. This is a non-standard feature."""
486
487 _fetch_type = 1
488
489
490 class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn,
491 BaseCursor):
492
493 """This is the standard Cursor class that returns rows as tuples
494 and stores the result set in the client."""
495
496
497 class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn,
498 BaseCursor):
499
500 """This is a Cursor class that returns rows as dictionaries and
501 stores the result set in the client."""
502
503
504 class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn,
505 BaseCursor):
506
507 """This is a Cursor class that returns rows as tuples and stores
508 the result set in the server."""
509
510
511 class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn,
512 BaseCursor):
513
514 """This is a Cursor class that returns rows as dictionaries and
515 stores the result set in the server."""
516
517