source: people/peter.buschman/backup_monitoring/dal/dbapi/_dbapi.py@ 987

Last change on this file since 987 was 976, checked in by peter, on Dec 6, 2011 at 10:19:33 AM

Raw checkin of current NetBackup / TSM parsing code.

File size: 34.5 KB
Line 
1###
2### DAL DBAPI 2.0 Wrapper Module
3###
4### --PLB 2007-11-03
5###
6
7import types
8import dtuple
9import string
10
11##
12## Version Information
13##
14version_info = (1, 0, 0)
15version = string.join(['%d' % (v) for v in version_info], '.')
16
17
18##
19## Return a wrapped DBAPI 2.0 module
20##
21## The driver parameter may be an existing module object or the name of a module to be imported
22##
23def wrap(driver):
24 return Module(driver)
25
26
27#
28# DBAPI Exceptions
29#
30# Thanks to Kevin Jacob's 'Virtual Exceptions'
31# http://mail.python.org/pipermail/db-sig/2003-April/003345.html
32
33#
34# Warning
35#
36# Exception raised for important warnings like data
37# truncations while inserting, etc. It must be a subclass of
38# the Python StandardError (defined in the module
39# exceptions).
40#
41class Warning(StandardError):
42 pass
43
44#
45# Error
46#
47# Exception that is the base class of all other error
48# exceptions. You can use this to catch all errors with one
49# single 'except' statement. Warnings are not considered
50# errors and thus should not use this class as base. It must
51# be a subclass of the Python StandardError (defined in the
52# module exceptions).
53#
54class Error(StandardError):
55 pass
56
57#
58# InterfaceError
59#
60# Exception raised for errors that are related to the
61# database interface rather than the database itself. It
62# must be a subclass of Error.
63#
64class InterfaceError(Error):
65 pass
66
67#
68# DatabaseError
69#
70# Exception raised for errors that are related to the
71# database. It must be a subclass of Error.
72#
73class DatabaseError(Error):
74 pass
75
76#
77# DataError
78#
79# Exception raised for errors that are due to problems with
80# the processed data like division by zero, numeric value
81# out of range, etc. It must be a subclass of DatabaseError.
82#
83class DataError(DatabaseError):
84 pass
85
86#
87# OperationalError
88#
89# Exception raised for errors that are related to the
90# database's operation and not necessarily under the control
91# of the programmer, e.g. an unexpected disconnect occurs,
92# the data source name is not found, a transaction could not
93# be processed, a memory allocation error occurred during
94# processing, etc. It must be a subclass of DatabaseError.
95#
96class OperationalError(DatabaseError):
97 pass
98
99#
100# IntegrityError
101#
102# Exception raised when the relational integrity of the
103# database is affected, e.g. a foreign key check fails. It
104# must be a subclass of DatabaseError.
105#
106class IntegrityError(DatabaseError):
107 pass
108
109#
110# InternalError
111#
112# Exception raised when the database encounters an internal
113# error, e.g. the cursor is not valid anymore, the
114# transaction is out of sync, etc. It must be a subclass of
115# DatabaseError.
116#
117class InternalError(DatabaseError):
118 pass
119
120#
121# ProgrammingError
122#
123# Exception raised for programming errors, e.g. table not
124# found or already exists, syntax error in the SQL
125# statement, wrong number of parameters specified, etc. It
126# must be a subclass of DatabaseError.
127#
128class ProgrammingError(DatabaseError):
129 pass
130
131#
132# NotSupportedError
133#
134# Exception raised in case a method or database API was used
135# which is not supported by the database, e.g. requesting a
136# .rollback() on a connection that does not support
137# transaction or has transactions turned off. It must be a
138# subclass of DatabaseError.
139#
140class NotSupportedError(DatabaseError):
141 pass
142
143
144##
145## DBAPI 2.0 Wrapper
146##
147class Module(object):
148
149 #
150 # BEGIN INIT
151 #
152 def __init__(self, driver):
153
154 """DBAPI 2.0 Module Wrapper"""
155
156 object.__init__(self)
157
158 #
159 # Set version
160 #
161 self.version_info = version_info
162 self.version = version
163
164 #
165 # Act appropriately if driver is a module or a string (the name of a module)
166 #
167 if type(driver) is types.ModuleType:
168 self.driver = driver
169 elif type(driver) is str:
170 self.driver = __import__(driver)
171 else:
172 raise ImportError, 'Could not import DBAPI module %s' % (driver)
173
174 #
175 # These module globals must be defined:
176 #
177
178 #
179 # apilevel
180 #
181 # String constant stating the supported DB API level.
182 # Currently only the strings '1.0' and '2.0' are allowed.
183 #
184 # If not given, a DB-API 1.0 level interface should be
185 # assumed.
186 #
187 self.apilevel = '2.0'
188
189 #
190 # threadsafety
191 #
192 # Integer constant stating the level of thread safety the
193 # interface supports. Possible values are:
194 #
195 # 0 Threads may not share the module.
196 # 1 Threads may share the module, but not connections.
197 # 2 Threads may share the module and connections.
198 # 3 Threads may share the module, connections and
199 # cursors.
200 #
201 self.threadsafety = self.driver.threadsafety
202
203 #
204 # paramstyle
205 #
206 # String constant stating the type of parameter marker
207 # formatting expected by the interface. Possible values are
208 # [2]:
209 #
210 # 'qmark' Question mark style,
211 # e.g. '...WHERE name=?'
212 # 'numeric' Numeric, positional style,
213 # e.g. '...WHERE name=:1'
214 # 'named' Named style,
215 # e.g. '...WHERE name=:name'
216 # 'format' ANSI C printf format codes,
217 # e.g. '...WHERE name=%s'
218 # 'pyformat' Python extended format codes,
219 # e.g. '...WHERE name=%(name)s'
220 #
221 self.paramstyle = self.driver.paramstyle
222
223 #
224 # This is the exception inheritance layout:
225 #
226 # StandardError
227 # |__Warning
228 # |__Error
229 # |__InterfaceError
230 # |__DatabaseError
231 # |__DataError
232 # |__OperationalError
233 # |__IntegrityError
234 # |__InternalError
235 # |__ProgrammingError
236 # |__NotSupportedError
237 #
238 # Note: The values of these exceptions are not defined. They should
239 # give the user a fairly good idea of what went wrong, though.
240 #
241 self.exceptions = [
242 'Warning',
243 'Error',
244 'InterfaceError',
245 'DatabaseError',
246 'DataError',
247 'OperationalError',
248 'IntegrityError',
249 'InternalError',
250 'ProgrammingError',
251 'NotSupportedError',
252 ]
253
254 #
255 # Wrap captive driver exceptions
256 #
257 for exception in self.exceptions:
258
259 driver_exception = getattr(self.driver, exception)
260
261 if driver_exception:
262 setattr(self, exception, driver_exception)
263
264 #
265 # STRING
266 #
267 # This type object is used to describe columns in a database
268 # that are string-based (e.g. CHAR).
269 #
270 if hasattr(self.driver, 'STRING'):
271 self.STRING = self.driver.STRING
272
273 #
274 # BINARY
275 #
276 # This type object is used to describe (long) binary columns
277 # in a database (e.g. LONG, RAW, BLOBs).
278 #
279 if hasattr(self.driver, 'BINARY'):
280 self.BINARY = self.driver.BINARY
281
282 #
283 # NUMBER
284 #
285 # This type object is used to describe numeric columns in a
286 # database.
287 #
288 if hasattr(self.driver, 'NUMBER'):
289 self.NUMBER = self.driver.NUMBER
290
291 #
292 # DATETIME
293 #
294 # This type object is used to describe date/time columns in
295 # a database.
296 #
297 if hasattr(self.driver, 'DATETIME'):
298 self.DATETIME = self.driver.DATETIME
299
300 #
301 # ROWID
302 #
303 # This type object is used to describe the "Row ID" column
304 # in a database.
305 #
306 if hasattr(self.driver, 'ROWID'):
307 self.ROWID = self.driver.ROWID
308
309 #
310 # END INIT
311 #
312
313 #
314 # Access to the database is made available through connection
315 # objects. The module must provide the following constructor for
316 # these:
317 #
318 # connect(parameters...)
319 #
320 # Constructor for creating a connection to the database.
321 # Returns a Connection Object. It takes a number of
322 # parameters which are database dependent. [1]
323 #
324 def connect(self, *args, **kwargs):
325
326 conn = self.driver.connect(*args, **kwargs)
327 conn = Connection(conn, module=self)
328
329 #
330 # Optional DBAPI Extension
331 #
332 # Connection Attributes .Error, .ProgrammingError, etc.
333 #
334 # All exception classes defined by the DB API standard should be
335 # exposed on the Connection objects are attributes (in addition
336 # to being available at module scope).
337 #
338 # These attributes simplify error handling in multi-connection
339 # environments.
340 #
341 # Warning Message: "DB-API extension connection.<exception> used"
342 #
343 for exception in self.exceptions:
344
345 driver_exception = getattr(self, exception)
346
347 if driver_exception:
348 setattr(conn, exception, driver_exception)
349
350 return conn
351
352 #
353 # The module exports the following constructors and singletons:
354 #
355
356 #
357 # Date(year,month,day)
358 #
359 # This function constructs an object holding a date value.
360 #
361 def Date(self, year, month, day):
362 return self.driver.Date(year, month, day)
363
364 #
365 # Time(hour,minute,second)
366 #
367 # This function constructs an object holding a time value.
368 #
369 def Time(self, hour, minute, second):
370 return self.driver.Time(hour, minute, second)
371
372 # Timestamp(year,month,day,hour,minute,second)
373 #
374 # This function constructs an object holding a time stamp
375 # value.
376 #
377 def Timestamp(self, year, month, day, hour, minute, second):
378 return self.driver.Timestamp(year, month, day, hour, minute, second)
379
380 #
381 # DateFromTicks(ticks)
382 #
383 # This function constructs an object holding a date value
384 # from the given ticks value (number of seconds since the
385 # epoch; see the documentation of the standard Python time
386 # module for details).
387 #
388 def DateFromTicks(self, ticks):
389 return self.driver.DateFromTicks(ticks)
390
391 #
392 # TimeFromTicks(ticks)
393 #
394 # This function constructs an object holding a time value
395 # from the given ticks value (number of seconds since the
396 # epoch; see the documentation of the standard Python time
397 # module for details).
398 #
399 def TimeFromTicks(self, ticks):
400 return self.driver.TimeFromTicks(ticks)
401
402 #
403 # TimestampFromTicks(ticks)
404 #
405 # This function constructs an object holding a time stamp
406 # value from the given ticks value (number of seconds since
407 # the epoch; see the documentation of the standard Python
408 # time module for details).
409 #
410 def TimestampFromTicks(self, ticks):
411 return self.driver.TimestampFromTicks(ticks)
412
413 #
414 # Binary(string)
415 #
416 # This function constructs an object capable of holding a
417 # binary (long) string value.
418 #
419 def Binary(self, string):
420 return self.driver.Binary(string)
421
422 #
423 # SQL NULL values are represented by the Python None singleton on
424 # input and output.
425 #
426 #
427 # Note: Usage of Unix ticks for database interfacing can cause
428 # troubles because of the limited date range they cover.
429 #
430
431
432##
433## Connection Objects
434##
435class Connection(object):
436
437 """DBAPI 2.0 Connection Wrapper"""
438
439 def __init__(self, conn, module=None, paramstyle=None):
440
441 object.__init__(self)
442
443 self.conn = conn
444
445 #
446 # Set module and driver
447 #
448 if module is not None:
449
450 self.module = module
451
452 if hasattr(module, 'driver'):
453 self.driver = module.driver
454 else:
455 self.driver = None
456
457 else:
458
459 self.module = None
460 self.driver = None
461
462 #
463 # Set paramstyle
464 #
465 if paramstyle is not None:
466 self.paramstyle = paramstyle
467 elif self.driver is not None:
468 self.paramstyle = self.driver.paramstyle
469
470 #
471 # Connection Objects should respond to the following methods:
472 #
473
474 #
475 # .close()
476 #
477 # Close the connection now (rather than whenever __del__ is
478 # called). The connection will be unusable from this point
479 # forward; an Error (or subclass) exception will be raised
480 # if any operation is attempted with the connection. The
481 # same applies to all cursor objects trying to use the
482 # connection. Note that closing a connection without
483 # committing the changes first will cause an implicit
484 # rollback to be performed.
485 #
486 def close(self):
487 return self.conn.close()
488
489 #
490 # .commit()
491 #
492 # Commit any pending transaction to the database. Note that
493 # if the database supports an auto-commit feature, this must
494 # be initially off. An interface method may be provided to
495 # turn it back on.
496 #
497 # Database modules that do not support transactions should
498 # implement this method with void functionality.
499 #
500 def commit(self):
501 return self.conn.commit()
502
503 #
504 # .rollback()
505 #
506 # This method is optional since not all databases provide
507 # transaction support. [3]
508 #
509 # In case a database does provide transactions this method
510 # causes the the database to roll back to the start of any
511 # pending transaction. Closing a connection without
512 # committing the changes first will cause an implicit
513 # rollback to be performed.
514 def rollback(self):
515 return self.conn.rollback()
516
517 #
518 # .cursor()
519 #
520 # Return a new Cursor Object using the connection. If the
521 # database does not provide a direct cursor concept, the
522 # module will have to emulate cursors using other means to
523 # the extent needed by this specification. [4]
524 #
525 def cursor(self):
526 curs = self.conn.cursor()
527 return Cursor(curs, conn=self, paramstyle=self.paramstyle) # include self so the optional .connection attribute can be set properly
528
529 #
530 # Optional DBAPI Extension
531 #
532 # Connection Attribute .messages
533 #
534 # Same as cursor.messages except that the messages in the list
535 # are connection oriented.
536 #
537 # The list is cleared automatically by all standard connection
538 # methods calls (prior to executing the call) to avoid excessive
539 # memory usage and can also be cleared by executing "del
540 # connection.messages[:]".
541 #
542 # Warning Message: "DB-API extension connection.messages used"
543 #
544 # NOT CURRENTLY IMPLEMENTED
545 #
546
547##
548## Cursor Objects
549##
550## These objects represent a database cursor, which is used to
551## manage the context of a fetch operation. Cursors created from
552## the same connection are not isolated, i.e., any changes
553## done to the database by a cursor are immediately visible by the
554## other cursors. Cursors created from different connections can
555## or can not be isolated, depending on how the transaction support
556## is implemented (see also the connection's rollback() and commit()
557## methods.)
558##
559class Cursor(object):
560
561 def __init__(self, curs, conn, paramstyle=None):
562
563 object.__init__(self)
564
565 self.cursor = curs
566 self.curs = curs
567
568 #
569 # Set module and driver
570 #
571 if conn.module is not None:
572
573 self.module = conn.module
574
575 if hasattr(conn.module, 'driver'):
576 self.driver = conn.module.driver
577 else:
578 self.driver = None
579
580 else:
581
582 self.module = None
583 self.driver = None
584
585 #
586 # Set paramstyle
587 #
588 if paramstyle is not None:
589 self.paramstyle = paramstyle
590 elif self.driver is not None:
591 self.paramstyle = self.driver.paramstyle
592
593 #
594 # Optional DBAPI Extension
595 #
596 # Cursor Attributes .connection
597 #
598 # This read-only attribute return a reference to the Connection
599 # object on which the cursor was created.
600 #
601 # The attribute simplifies writing polymorph code in
602 # multi-connection environments.
603 #
604 # Warning Message: "DB-API extension cursor.connection used"
605 #
606 self.connection = conn
607 self.conn = conn
608
609 #
610 # Add convenience commit method
611 #
612 self.commit = self.conn.commit
613
614 #
615 # Cursor Objects should respond to the following methods and attributes:
616 #
617
618 #
619 # .description
620 #
621 # This read-only attribute is a sequence of 7-item
622 # sequences. Each of these sequences contains information
623 # describing one result column: (name, type_code,
624 # display_size, internal_size, precision, scale,
625 # null_ok). The first two items (name and type_code) are
626 # mandatory, the other five are optional and must be set to
627 # None if meaningfull values are not provided.
628 #
629 # This attribute will be None for operations that
630 # do not return rows or if the cursor has not had an
631 # operation invoked via the executeXXX() method yet.
632 #
633 # The type_code can be interpreted by comparing it to the
634 # Type Objects specified in the section below.
635 #
636 description = property(lambda self: self.curs.description)
637
638 #
639 # Update column descriptions for dtuple (not part of DBAPI)
640 #
641 def update_columns(self):
642
643 if self.curs.description:
644
645 columns = []
646
647 for d in self.curs.description:
648 column = d[0]
649 columns.append(d[0])
650
651 self.columns = dtuple.TupleDescriptor([[column] for column in columns])
652
653 #
654 # .rowcount
655 #
656 # This read-only attribute specifies the number of rows that
657 # the last executeXXX() produced (for DQL statements like
658 # 'select') or affected (for DML statements like 'update' or
659 # 'insert').
660 #
661 # The attribute is -1 in case no executeXXX() has been
662 # performed on the cursor or the rowcount of the last
663 # operation is not determinable by the interface. [7]
664 #
665 # Note: Future versions of the DB API specification could
666 # redefine the latter case to have the object return None
667 # instead of -1.
668 #
669 rowcount = property(lambda self: self.curs.rowcount)
670
671 #
672 # .callproc(procname[,parameters])
673 #
674 # (This method is optional since not all databases provide
675 # stored procedures. [3])
676 #
677 # Call a stored database procedure with the given name. The
678 # sequence of parameters must contain one entry for each
679 # argument that the procedure expects. The result of the
680 # call is returned as modified copy of the input
681 # sequence. Input parameters are left untouched, output and
682 # input/output parameters replaced with possibly new values.
683 #
684 # The procedure may also provide a result set as
685 # output. This must then be made available through the
686 # standard fetchXXX() methods.
687 #
688 def callproc(self, procname, parameters=[], *args, **kwargs):
689
690 #
691 # Call the wrapped method and save the results
692 #
693 results = self.curs.callproc(procname, parameters, *args, **kwargs)
694
695 #
696 # Update the column descriptions for dtuple
697 #
698 self.update_columns()
699
700 #
701 # Return the saved results
702 #
703 return results
704
705 #
706 # .close()
707 #
708 # Close the cursor now (rather than whenever __del__ is
709 # called). The cursor will be unusable from this point
710 # forward; an Error (or subclass) exception will be raised
711 # if any operation is attempted with the cursor.
712 #
713 def close(self, *args, **kwargs):
714 return self.curs.close(*args, **kwargs)
715
716 #
717 # .execute(operation[,parameters])
718 #
719 # Prepare and execute a database operation (query or
720 # command). Parameters may be provided as sequence or
721 # mapping and will be bound to variables in the operation.
722 # Variables are specified in a database-specific notation
723 # (see the module's paramstyle attribute for details). [5]
724 #
725 # A reference to the operation will be retained by the
726 # cursor. If the same operation object is passed in again,
727 # then the cursor can optimize its behavior. This is most
728 # effective for algorithms where the same operation is used,
729 # but different parameters are bound to it (many times).
730 #
731 # For maximum efficiency when reusing an operation, it is
732 # best to use the setinputsizes() method to specify the
733 # parameter types and sizes ahead of time. It is legal for
734 # a parameter to not match the predefined information; the
735 # implementation should compensate, possibly with a loss of
736 # efficiency.
737 #
738 # The parameters may also be specified as list of tuples to
739 # e.g. insert multiple rows in a single operation, but this
740 # kind of usage is depreciated: executemany() should be used
741 # instead.
742 #
743 # Return values are not defined.
744 #
745 def execute(self, operation, parameters=None, *args, **kwargs):
746
747 #
748 # Set appropriate default parameters depending on paramstyle type
749 #
750 if not parameters:
751 if self.paramstyle in ['qmark', 'numeric', 'format']:
752 #
753 # sequence
754 #
755 parameters = []
756 else:
757 #
758 # mapping
759 #
760 parameters = {}
761
762 #
763 # Call the wrapped method and save the results
764 #
765 self.curs.execute(operation, parameters, *args, **kwargs)
766
767 #
768 # Update the column descriptions for dtuple
769 #
770 self.update_columns()
771
772 #
773 # Return self so we can iterate over the results
774 #
775 return self
776
777 #
778 # .executemany(operation,seq_of_parameters)
779 #
780 # Prepare a database operation (query or command) and then
781 # execute it against all parameter sequences or mappings
782 # found in the sequence seq_of_parameters.
783 #
784 # Modules are free to implement this method using multiple
785 # calls to the execute() method or by using array operations
786 # to have the database process the sequence as a whole in
787 # one call.
788 #
789 # Use of this method for an operation which produces one or
790 # more result sets constitutes undefined behavior, and the
791 # implementation is permitted (but not required) to raise
792 # an exception when it detects that a result set has been
793 # created by an invocation of the operation.
794 #
795 # The same comments as for execute() also apply accordingly
796 # to this method.
797 #
798 # Return values are not defined.
799 #
800 def executemany(self, operation, seq_of_parameters, *args, **kwargs):
801
802 #
803 # Call the wrapped method and save the results
804 #
805 self.curs.executemany(operation, seq_of_parameters, *args, **kwargs)
806
807 #
808 # Update the column descriptions for dtuple
809 #
810 self.update_columns()
811
812 #
813 # Return self so we can iterate over the results
814 #
815 return self
816
817 #
818 # .fetchone()
819 #
820 # Fetch the next row of a query result set, returning a
821 # single sequence, or None when no more data is
822 # available. [6]
823 #
824 # An Error (or subclass) exception is raised if the previous
825 # call to executeXXX() did not produce any result set or no
826 # call was issued yet.
827 #
828 def fetchone(self, *args, **kwargs):
829
830 row = self.curs.fetchone(*args, **kwargs)
831
832 #
833 # Return results using dtuple
834 #
835 if row:
836 return dtuple.DatabaseTuple(self.columns, row)
837 else:
838 return None
839
840 #
841 # .fetchmany([size=cursor.arraysize])
842 #
843 # Fetch the next set of rows of a query result, returning a
844 # sequence of sequences (e.g. a list of tuples). An empty
845 # sequence is returned when no more rows are available.
846 #
847 # The number of rows to fetch per call is specified by the
848 # parameter. If it is not given, the cursor's arraysize
849 # determines the number of rows to be fetched. The method
850 # should try to fetch as many rows as indicated by the size
851 # parameter. If this is not possible due to the specified
852 # number of rows not being available, fewer rows may be
853 # returned.
854 #
855 # An Error (or subclass) exception is raised if the previous
856 # call to executeXXX() did not produce any result set or no
857 # call was issued yet.
858 #
859 # Note there are performance considerations involved with
860 # the size parameter. For optimal performance, it is
861 # usually best to use the arraysize attribute. If the size
862 # parameter is used, then it is best for it to retain the
863 # same value from one fetchmany() call to the next.
864 #
865 def fetchmany(self, size=None, *args, **kwargs):
866 size = size or self.arraysize
867 return [dtuple.DatabaseTuple(self.columns, row) for row in self.curs.fetchmany(size, *args, **kwargs)]
868
869 #
870 # .fetchall()
871 #
872 # Fetch all (remaining) rows of a query result, returning
873 # them as a sequence of sequences (e.g. a list of tuples).
874 # Note that the cursor's arraysize attribute can affect the
875 # performance of this operation.
876 #
877 # An Error (or subclass) exception is raised if the previous
878 # call to executeXXX() did not produce any result set or no
879 # call was issued yet.
880 #
881 def fetchall(self, *args, **kwargs):
882 return [dtuple.DatabaseTuple(self.columns, row) for row in self.curs.fetchall(*args, **kwargs)]
883
884 #
885 # .nextset()
886 #
887 # (This method is optional since not all databases support
888 # multiple result sets. [3])
889 #
890 # This method will make the cursor skip to the next
891 # available set, discarding any remaining rows from the
892 # current set.
893 #
894 # If there are no more sets, the method returns
895 # None. Otherwise, it returns a true value and subsequent
896 # calls to the fetch methods will return rows from the next
897 # result set.
898 #
899 # An Error (or subclass) exception is raised if the previous
900 # call to executeXXX() did not produce any result set or no
901 # call was issued yet.
902 #
903 def nextset(self, *args, **kwargs):
904 if hasattr(self.curs, 'nextset'):
905 return self.curs.nextset(*args, **kwargs)
906 else:
907 return None
908
909 #
910 # .arraysize
911 #
912 # This read/write attribute specifies the number of rows to
913 # fetch at a time with fetchmany(). It defaults to 1 meaning
914 # to fetch a single row at a time.
915 #
916 # Implementations must observe this value with respect to
917 # the fetchmany() method, but are free to interact with the
918 # database a single row at a time. It may also be used in
919 # the implementation of executemany().
920 #
921 arraysize = property(lambda self: self.curs.arraysize)
922
923 #
924 # .setinputsizes(sizes)
925 #
926 # This can be used before a call to executeXXX() to
927 # predefine memory areas for the operation's parameters.
928 #
929 # sizes is specified as a sequence -- one item for each
930 # input parameter. The item should be a Type Object that
931 # corresponds to the input that will be used, or it should
932 # be an integer specifying the maximum length of a string
933 # parameter. If the item is None, then no predefined memory
934 # area will be reserved for that column (this is useful to
935 # avoid predefined areas for large inputs).
936 #
937 # This method would be used before the executeXXX() method
938 # is invoked.
939 #
940 # Implementations are free to have this method do nothing
941 # and users are free to not use it.
942 #
943 def setinputsizes(self, *args, **kwargs):
944 return self.curs.setinputsizes(*args, **kwargs)
945
946 #
947 # .setoutputsize(size[,column])
948 #
949 # Set a column buffer size for fetches of large columns
950 # (e.g. LONGs, BLOBs, etc.). The column is specified as an
951 # index into the result sequence. Not specifying the column
952 # will set the default size for all large columns in the
953 # cursor.
954 #
955 # This method would be used before the executeXXX() method
956 # is invoked.
957 #
958 # Implementations are free to have this method do nothing
959 # and users are free to not use it.
960 #
961 def setoutputsize(self, *args, **kwargs):
962 return self.curs.setoutputsize(*args, **kwargs)
963
964 #
965 # Optional DBAPI Extension
966 #
967 # Cursor Attribute .rownumber
968 #
969 # This read-only attribute should provide the current 0-based
970 # index of the cursor in the result set or None if the index cannot
971 # be determined.
972 #
973 # The index can be seen as index of the cursor in a sequence (the
974 # result set). The next fetch operation will fetch the row
975 # indexed by .rownumber in that sequence.
976 #
977 # Warning Message: "DB-API extension cursor.rownumber used"
978 #
979 # NOT CURRENTLY IMPLEMENTED
980 #
981
982 #
983 # Optional DBAPI Extension
984 #
985 # Cursor Method .scroll(value[,mode='relative'])
986 #
987 # Scroll the cursor in the result set to a new position according
988 # to mode.
989 #
990 # If mode is 'relative' (default), value is taken as offset to
991 # the current position in the result set, if set to 'absolute',
992 # value states an absolute target position.
993 #
994 # An IndexError should be raised in case a scroll operation would
995 # leave the result set. In this case, the cursor position is left
996 # undefined (ideal would be to not move the cursor at all).
997 #
998 # Note: This method should use native scrollable cursors, if
999 # available , or revert to an emulation for forward-only
1000 # scrollable cursors. The method may raise NotSupportedErrors to
1001 # signal that a specific operation is not supported by the
1002 # database (e.g. backward scrolling).
1003 #
1004 # Warning Message: "DB-API extension cursor.scroll() used"
1005 #
1006 # NOT CURRENTLY IMPLEMENTED
1007 #
1008
1009 #
1010 # Optional DBAPI Extension
1011 #
1012 # Cursor Attribute .messages
1013 #
1014 # This is a Python list object to which the interface appends
1015 # tuples (exception class, exception value) for all messages
1016 # which the interfaces receives from the underlying database for
1017 # this cursor.
1018 #
1019 # The list is cleared by all standard cursor methods calls (prior
1020 # to executing the call) except for the .fetchXXX() calls
1021 # automatically to avoid excessive memory usage and can also be
1022 # cleared by executing "del cursor.messages[:]".
1023 #
1024 # All error and warning messages generated by the database are
1025 # placed into this list, so checking the list allows the user to
1026 # verify correct operation of the method calls.
1027 #
1028 # The aim of this attribute is to eliminate the need for a
1029 # Warning exception which often causes problems (some warnings
1030 # really only have informational character).
1031 #
1032 # Warning Message: "DB-API extension cursor.messages used"
1033 #
1034 # NOT CURRENTLY IMPLEMENTED
1035 #
1036
1037 #
1038 # Optional DBAPI Extension
1039 #
1040 # Cursor Method .next()
1041 #
1042 # Return the next row from the currently executing SQL statement
1043 # using the same semantics as .fetchone(). A StopIteration
1044 # exception is raised when the result set is exhausted for Python
1045 # versions 2.2 and later. Previous versions don't have the
1046 # StopIteration exception and so the method should raise an
1047 # IndexError instead.
1048 #
1049 # Warning Message: "DB-API extension cursor.next() used"
1050 #
1051 def next(self):
1052
1053 row = self.curs.fetchone()
1054
1055 if row:
1056 return dtuple.DatabaseTuple(self.columns, row)
1057 else:
1058 raise StopIteration
1059
1060 #
1061 # Optional DBAPI Extension
1062 #
1063 # Cursor Method .__iter__()
1064 #
1065 # Return self to make cursors compatible to the iteration protocol.
1066 #
1067 # Warning Message: "DB-API extension cursor.__iter__() used"
1068 #
1069 def __iter__(self):
1070 return self
1071
1072 #
1073 # Optional DBAPI Extension
1074 #
1075 # Cursor Attribute .lastrowid
1076 #
1077 # This read-only attribute provides the rowid of the last
1078 # modified row (most databases return a rowid only when a single
1079 # INSERT operation is performed). If the operation does not set
1080 # a rowid or if the database does not support rowids, this
1081 # attribute should be set to None.
1082 #
1083 # The semantics of .lastrowid are undefined in case the last
1084 # executed statement modified more than one row, e.g. when
1085 # using INSERT with .executemany().
1086 #
1087 # Warning Message: "DB-API extension cursor.lastrowid used"
1088 #
1089 # NOT CURRENTLY IMPLEMENTED
1090 #
1091
1092
Note: See TracBrowser for help on using the repository browser.