Update of /cvsroot/pywin32/pywin32/adodbapi
In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv20495/adodbapi
Modified Files:
__init__.py adodbapi.py readme.txt
Log Message:
adodbapi version 2.4.0
Index: adodbapi.py
===================================================================
RCS file: /cvsroot/pywin32/pywin32/adodbapi/adodbapi.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** adodbapi.py 5 Jun 2010 21:59:48 -0000 1.13
--- adodbapi.py 31 Jul 2010 05:48:09 -0000 1.14
***************
*** 27,31 ****
or, after running through 2to3.py, CPython 3.0 or later.
"""
! __version__ = '2.3.0'
version = 'adodbapi v' + __version__
# N.O.T.E.:...
--- 27,31 ----
or, after running through 2to3.py, CPython 3.0 or later.
"""
! __version__ = '2.4.0'
version = 'adodbapi v' + __version__
# N.O.T.E.:...
***************
*** 47,55 ****
# or # from django.utils import _decimal as decimal
! if sys.platform != 'cli':
! import win32com.client
! onIronPython = False
! else: # implies running on IronPython
! onIronPython = True
# --- define objects to smooth out IronPython <-> CPython differences
--- 47,57 ----
# or # from django.utils import _decimal as decimal
! onIronPython = sys.platform == 'cli'
! if not onIronPython:
! try:
! import win32com.client
! except ImportError:
! import warnings
! warnings.warn("pywin32 package required but not found.",ImportWarning)
# --- define objects to smooth out IronPython <-> CPython differences
***************
*** 64,72 ****
return obj.Item[index]
else: #pywin32
! import pythoncom
! import pywintypes
! pythoncom.__future_currency__ = True
! def Dispatch(dispatch):
! return win32com.client.Dispatch(dispatch)
def getIndexedValue(obj,index):
return obj(index)
--- 66,77 ----
return obj.Item[index]
else: #pywin32
! try:
! import pythoncom
! import pywintypes
! pythoncom.__future_currency__ = True
! def Dispatch(dispatch):
! return win32com.client.Dispatch(dispatch)
! except:
! pass #warning already given above
def getIndexedValue(obj,index):
return obj(index)
***************
*** 143,146 ****
--- 148,153 ----
def DateObjectFromCOMDate(self,comDate):
return mx.DateTime.DateTimeFromCOMDate(comDate)
+ def DateObjectFromCOMDate(self,comDate):
+ return mx.DateTime.DateTimeFromCOMDate(comDate)
def Date(self,year,month,day):
return mx.DateTime.Date(year,month,day)
***************
*** 167,184 ****
return self.COMDateFromTuple(YMDHMSmsTuple)
def DateObjectFromCOMDate(self,comDate):
- #ComDate is number of days since 1899-12-31
if isinstance(comDate,datetime.datetime):
return comDate.replace(tzinfo=None) # make non aware
elif isinstance(comDate,DateTime):
! fComDate = comDate.ToOADate()
else:
! fComDate=float(comDate)
! millisecondsperday=86400000 # 24*60*60*1000
integerPart = int(fComDate)
floatpart=fComDate-integerPart
! if floatpart == 0.0:
! return datetime.date.fromordinal(integerPart + self._ordinal_1899_12_31)
dte=datetime.datetime.fromordinal(integerPart + self._ordinal_1899_12_31) \
! + datetime.timedelta(milliseconds=floatpart*millisecondsperday)
return dte
def Date(self,year,month,day):
--- 174,190 ----
return self.COMDateFromTuple(YMDHMSmsTuple)
def DateObjectFromCOMDate(self,comDate):
if isinstance(comDate,datetime.datetime):
return comDate.replace(tzinfo=None) # make non aware
elif isinstance(comDate,DateTime):
! fComDate = comDate.ToOADate() # ironPython clr Date/Time
else:
! fComDate=float(comDate) #ComDate is number of days since 1899-12-31
integerPart = int(fComDate)
floatpart=fComDate-integerPart
! ##if floatpart == 0.0:
! ## return datetime.date.fromordinal(integerPart + self._ordinal_1899_12_31)
dte=datetime.datetime.fromordinal(integerPart + self._ordinal_1899_12_31) \
! + datetime.timedelta(milliseconds=floatpart*86400000)
! # millisecondsperday=86400000 # 24*60*60*1000
return dte
def Date(self,year,month,day):
***************
*** 224,228 ****
if isinstance(comDate,datetime.datetime):
return comDate.timetuple()
! elif isinstance(comDate,DateTime):
fcomDate = comDate.ToOADate()
else:
--- 230,234 ----
if isinstance(comDate,datetime.datetime):
return comDate.timetuple()
! elif isinstance(comDate,DateTime): # ironPython clr date/time
fcomDate = comDate.ToOADate()
else:
***************
*** 337,341 ****
# For example:
# import adodbapi, ado_consts
! # adodbapi.adodbapi.defaultIsolationLevel=adc.adXactBrowse"
#
# Set defaultCursorLocation on module level before creating the connection.
--- 343,347 ----
# For example:
# import adodbapi, ado_consts
! # adodbapi.adodbapi.defaultIsolationLevel=ado_consts.adXactBrowse"
#
# Set defaultCursorLocation on module level before creating the connection.
***************
*** 346,350 ****
# Used for COM to Python date conversions.
_ordinal_1899_12_31 = datetime.date(1899,12,31).toordinal()-1
- _milliseconds_per_day = 24*60*60*1000
def format_parameters(parameters, show_value=False):
--- 352,355 ----
***************
*** 394,405 ****
p.Value = s
p.Size = len(s)
!
elif type(value) in dateconverter.types:
if settings_known and p.Type in adoDateTimeTypes:
p.Value=dateconverter.COMDate(value)
else: #probably a string
! #Known problem with JET Provider. Date can not be specified as a COM date.
! # See for example..http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b284843
! # One workaround is to provide the date as a string in the format 'YYYY-MM-dd'
s = dateconverter.DateObjectToIsoFormatString(value)
p.Value = s
--- 399,410 ----
p.Value = s
p.Size = len(s)
!
elif type(value) in dateconverter.types:
if settings_known and p.Type in adoDateTimeTypes:
p.Value=dateconverter.COMDate(value)
else: #probably a string
! #Known problem with JET Provider. Date can not be specified as a COM date.
! # See for example..http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b284843
! # One workaround is to provide the date as a string in the format 'YYYY-MM-dd'
s = dateconverter.DateObjectToIsoFormatString(value)
p.Value = s
***************
*** 559,563 ****
if state.startswith('23') or state=='40002':
return IntegrityError
-
return DatabaseError
--- 564,567 ----
***************
*** 576,581 ****
--- 580,683 ----
object.__setattr__(self, name, value)
+ # # # # # classes to emulate the result of cursor.fetchxxx() as a sequence of sequences # # # # #
+ class _SQLrow(object): # a single database row
+ # class to emulate a sequence, so that a column may be retrieved by either number or name
+ def __init__(self,rows,index): # "rows" is an _SQLrows object, index is which row
+ # note: self.__setattr__ is disabled to prevent users from trying to store in a row
+ object.__setattr__(self,'rows',rows) # parent 'fetch' container object
+ object.__setattr__(self,'index',index) # row number within parent
+ def __getattr__(self,name): # used for row.columnName type of value access
+ return self._getValue(self.rows.columnNames[name])
+ def __setattr__(self,name,value):
+ raise NotSupportedError('Cannot assign value to SQL record column')
+ def _getValue(self,key): # key must be an integer
+ if onIronPython: # retrieve from two-dimensional array
+ v = self.rows.ado_results[key,self.index]
+ else: # pywin32 - retrieve from tuple of tuples
+ v = self.rows.ado_results[key][self.index]
+ return _convert_to_python(v,self.rows.converters[key])
+ def __len__(self):
+ return len(self.rows.converters)
+ def __getitem__(self,key): # used for row[key] type of value access
+ if isinstance(key,int): # normal row[1] designation
+ try:
+ return self._getValue(key)
+ except IndexError:
+ raise
+ if isinstance(key, slice):
+ indices = key.indices(len(self.rows.converters))
+ vl = [self._getValue(i) for i in range(*indices)]
+ return tuple(vl)
+ try:
+ return self._getValue(self.rows.columnNames[key]) # extension row[columnName] designation
+ except (KeyError,TypeError):
+ er, st, tr = sys.exc_info()
+ raise er,'No such key as "%s" in %s'%(repr(key),self.__repr__())
+ def __iter__(self):
+ return iter(self.__next__())
+ def __next__(self):
+ for n in range(len(self.rows.converters)):
+ yield self._getValue(n)
+ def __repr__(self): # create a human readable representation
+ try: #python 2.4 and later
+ taglist = sorted(self.rows.columnNames.items(),key=lambda x:x[1])
+ except NameError: # no such function as "sorted" on 2.3
+ taglist = list(self.rows.columnNames.iteritems())
+ taglist.sort(lambda x, y: cmp(x[1], y[1])) #deprecated on 3.0
+ s = "<SQLrow={"
+ for name, i in taglist:
+ s += name + ':' + repr(self._getValue(i)) + ', '
+ return s[:-2] + '}>'
+ def __str__(self): # create a pretty human readable representation
+ return str(tuple([str(self._getValue(i)) for i in range(len(self.rows.converters))]))
+ # # # #
+ class _SQLrows(object):
+ # class to emulate a sequence for multiple rows using a container object
+ def __init__(self,ado_results,numberOfRows,cursor):
+ self.ado_results = ado_results # raw result of SQL get
+ self.numberOfRows = numberOfRows
+ self.converters = [] # convertion function for each column
+ self.columnNames = {} # names of columns {name:number,...}
+ for i,desc in enumerate(cursor.description):
+ self.columnNames[desc[0]] = i
+ self.converters.append(variantConversions[desc[1]]) # default convertion function
+ def __len__(self):
+ return self.numberOfRows
+ def __getitem__(self,item): # used for row or row,column access
+ if isinstance(item, slice): # will return a tuple of row objects
+ indices = item.indices(self.numberOfRows)
+ l = [_SQLrow(self,k) for k in range(*indices)]
+ return tuple(l) #no generator expressions in Python 2.3
+ elif isinstance(item, tuple) and len(item)==2:
+ # d = some_rowsObject[i,j] will return a datum from a two-dimension address
+ i,j = item
+ if not isinstance(j,int):
+ try:
+ j = self.columnNames[j] # convert named column to numeric
+ except KeyError:
+ raise KeyError, 'adodbapi: no such column name as "%s"'%repr(j)
+ if onIronPython: # retrieve from two-dimensional array
+ v = self.ado_results[j,i]
+ else: # pywin32 - retrieve from tuple of tuples
+ v = self.ado_results[j][i]
+ return _convert_to_python(v,self.converters[j])
+ else:
+ row = _SQLrow(self,item) # new row descriptor
+ return row
+ def __iter__(self):
+ return iter(self.__next__())
+ def __next__(self):
+ for n in range(self.numberOfRows):
+ row = _SQLrow(self,n)
+ yield row
+ # # # # #
+ def _convert_to_python(variant, function): # convert DB value into Python value
+ if isinstance(variant,DBNull):
+ return None
+ return function(variant)
# # # # # ----- the Class that defines a cursor ----- # # # # #
class Cursor(object):
+ ## ** api required attributes:
+ ## description...
## This read-only attribute is a sequence of 7-item sequences.
## Each of these sequences contains information describing one result column:
***************
*** 584,589 ****
## cursor has not had an operation invoked via the executeXXX() method yet.
## The type_code can be interpreted by comparing it to the Type Objects specified in the section below.
! description = None
!
## This read-only attribute specifies the number of rows that the last executeXXX() produced
## (for DQL statements like select) or affected (for DML statements like update or insert).
--- 686,690 ----
## cursor has not had an operation invoked via the executeXXX() method yet.
## The type_code can be interpreted by comparing it to the Type Objects specified in the section below.
! ## rowcount...
## This read-only attribute specifies the number of rows that the last executeXXX() produced
## (for DQL statements like select) or affected (for DML statements like update or insert).
***************
*** 591,596 ****
## the rowcount of the last operation is not determinable by the interface.[7]
## NOTE: -- adodbapi returns "-1" by default for all select statements
! rowcount = -1
!
## This read/write attribute specifies the number of rows to fetch at a time with fetchmany().
## It defaults to 1 meaning to fetch a single row at a time.
--- 692,696 ----
## the rowcount of the last operation is not determinable by the interface.[7]
## NOTE: -- adodbapi returns "-1" by default for all select statements
! ## arraysize...
## This read/write attribute specifies the number of rows to fetch at a time with fetchmany().
## It defaults to 1 meaning to fetch a single row at a time.
***************
*** 598,610 ****
## but are free to interact with the database a single row at a time.
## It may also be used in the implementation of executemany().
! arraysize=1
!
def __init__(self,connection):
self.messages=[]
self.connection = connection
! self.paramstyle = connection.paramstyle
! self.rs = None
self.description = None
self.errorhandler = connection.errorhandler
if verbose:
print 'adodbapi New cursor at %X on conn %X' % (id(self),id(self.connection))
--- 698,715 ----
## but are free to interact with the database a single row at a time.
## It may also be used in the implementation of executemany().
! ## ** extension attributes:
! ## paramstyle...
! ## allows the programmer to override the connection's default paramstyle
! ## errorhandler...
! ## allows the programmer to override the connection's default error handler
!
def __init__(self,connection):
self.messages=[]
self.connection = connection
! self.paramstyle = connection.paramstyle # used for overriding the paramstyle
! self.rs = None # the ADO recordset for this cursor
self.description = None
self.errorhandler = connection.errorhandler
+ self.arraysize = 1
if verbose:
print 'adodbapi New cursor at %X on conn %X' % (id(self),id(self.connection))
***************
*** 634,643 ****
def format_description(self,d):
! """Format db_api description tuple."""
if isinstance(d,int):
d = self.description[d]
desc = "Name= %s, Type= %s, DispSize= %s, IntSize= %s, Precision= %s, Scale= %s NullOK=%s" %\
! (d[0], adc.adTypeNames.get(d[1], str(d[1])+' (unknown type)'),
! d[2], d[3], d[4], d[5], d[6])
return desc
--- 739,748 ----
def format_description(self,d):
! """Format db_api description tuple for printing."""
if isinstance(d,int):
d = self.description[d]
desc = "Name= %s, Type= %s, DispSize= %s, IntSize= %s, Precision= %s, Scale= %s NullOK=%s" %\
! (d[0], adc.adTypeNames.get(d[1], str(d[1])+' (unknown type)'),
! d[2], d[3], d[4], d[5], d[6])
return desc
***************
*** 753,757 ****
print 'with parameters=',format_parameters(self.cmd.Parameters, True)
try:
! # ----- the actual SQL is executed here ---
if onIronPython:
ra = Reference[int]()
--- 858,862 ----
print 'with parameters=',format_parameters(self.cmd.Parameters, True)
try:
! # ----- the actual SQL is executed here ---
if onIronPython:
ra = Reference[int]()
***************
*** 795,799 ****
if verbose > 2:
print 'returning=', p.Name, p.Type, p.Direction, repr(p.Value)
! pyObject=_convert_to_python(p.Value,p.Type)
if p.Direction == adc.adParamReturnValue:
self.returnValue=pyObject
--- 900,904 ----
if verbose > 2:
print 'returning=', p.Name, p.Type, p.Direction, repr(p.Value)
! pyObject=_convert_to_python(p.Value,variantConversions[p.Type])
if p.Direction == adc.adParamReturnValue:
self.returnValue=pyObject
***************
*** 829,833 ****
self.cmd.Parameters.Append(p)
if verbose > 2:
! for i in range(self.cmd.Parameters.Count):
P = self.cmd.Parameters[i]
print 'adodbapi parameter attributes=', P.Name, P.Type, P.Direction, P.Size
--- 934,938 ----
self.cmd.Parameters.Append(p)
if verbose > 2:
! for i in range(self.cmd.Parameters.Count):
P = self.cmd.Parameters[i]
print 'adodbapi parameter attributes=', P.Name, P.Type, P.Direction, P.Size
***************
*** 836,846 ****
i = 0
for value in parameters:
! ##if value is None:
! ## parameter_replacements.append('NULL')
! ## continue
! ##if isinstance(value, basestring) and value == "":
! ## parameter_replacements.append("''")
! ## continue
! ##parameter_replacements.append('?')
p=getIndexedValue(self.cmd.Parameters,i)
if p.Direction == adc.adParamReturnValue:
--- 941,951 ----
i = 0
for value in parameters:
! ##if value is None:
! ## parameter_replacements.append('NULL')
! ## continue
! ##if isinstance(value, basestring) and value == "":
! ## parameter_replacements.append("''")
! ## continue
! ##parameter_replacements.append('?')
p=getIndexedValue(self.cmd.Parameters,i)
if p.Direction == adc.adParamReturnValue:
***************
*** 851,855 ****
except (Exception), e:
_message = u'Converting Parameter %s: %s, %s <- %s\n' %\
! (p.Name, adc.ado_type_name(p.Type), p.Value, repr(value))
self._raiseCursorError(DataError, _message+'->'+repr(e.args))
i += 1
--- 956,960 ----
except (Exception), e:
_message = u'Converting Parameter %s: %s, %s <- %s\n' %\
! (p.Name, adc.ado_type_name(p.Type), p.Value, repr(value))
self._raiseCursorError(DataError, _message+'->'+repr(e.args))
i += 1
***************
*** 912,919 ****
self.rowcount = total_recordcount
! def _fetch(self, rows=None):
"""Fetch rows from the current recordset.
! rows -- Number of rows to fetch, or None (default) to fetch all rows.
"""
if self.connection is None or self.rs is None:
--- 1017,1024 ----
self.rowcount = total_recordcount
! def _fetch(self, limit=None):
"""Fetch rows from the current recordset.
! limit -- Number of rows to fetch, or None (default) to fetch all rows.
"""
if self.connection is None or self.rs is None:
***************
*** 922,953 ****
if self.rs.State == adc.adStateClosed or self.rs.BOF or self.rs.EOF:
! if rows == 1: # fetchone returns None
! return None
! else: # fetchall and fetchmany return empty lists
! return list()
! if rows:
! ado_results = self.rs.GetRows(rows)
! else:
ado_results = self.rs.GetRows()
!
! d=self.description
! returnList=[]
! i=0
! if onIronPython:
! type_codes = [descTuple[1] for descTuple in d]
! for j in range(len(ado_results)/len(d)):
! L = []
! for i in range(len(d)):
! L.append(_convert_to_python(ado_results[i,j],type_codes[i]))
! returnList.append(tuple(L))
! return tuple(returnList)
else: #pywin32
! for descTuple in d:
! # Desctuple =(name, type_code, display_size, internal_size, precision, scale, null_ok).
! type_code=descTuple[1]
! returnList.append([_convert_to_python(r,type_code) for r in ado_results[i]])
! i+=1
! return tuple(zip(*returnList))
def fetchone(self):
--- 1027,1043 ----
if self.rs.State == adc.adStateClosed or self.rs.BOF or self.rs.EOF:
! return list()
! if limit: # limit number of rows retrieved
! ado_results = self.rs.GetRows(limit)
! else: # get all rows
ado_results = self.rs.GetRows()
! if onIronPython: # result of GetRows is a two-dimension array
! length = len(ado_results)//len(self.description) # length of first dimension
! fetchObject = _SQLrows(ado_results,length,self) # new object to hold the results of the fetch
else: #pywin32
! length = len(ado_results[0]) #result of GetRows is tuples in a tuple
! fetchObject = _SQLrows(ado_results,length,self) # new object to hold the results of the fetch
! return fetchObject
def fetchone(self):
***************
*** 1085,1090 ****
return makeByteBuffer(aString)
- #v2.1 Cole comment out: BinaryType = Binary('a')
-
#SQL NULL values are represented by the Python None singleton on input and output.
--- 1175,1178 ----
***************
*** 1097,1100 ****
--- 1185,1192 ----
return typeMap[tp]
except KeyError:
+ if isinstance(d,datetime.datetime):
+ return adc.adDBTimeStamp
+ if isinstance(d,datetime.time):
+ return adc.adDBTime
if tp in dateconverter.types:
return adc.adDate
***************
*** 1177,1181 ****
return _convertNumberWithCulture(variant, decimal.Decimal)
def cvtNumeric(variant): #older name - don't break old code
! return cvtDecimal(variant)
def cvtFloat(variant):
--- 1269,1273 ----
return _convertNumberWithCulture(variant, decimal.Decimal)
def cvtNumeric(variant): #older name - don't break old code
! return cvtDecimal(variant)
def cvtFloat(variant):
***************
*** 1191,1195 ****
except (ValueError,TypeError,decimal.InvalidOperation): pass
-
def cvtInt(variant):
return int(variant)
--- 1283,1286 ----
***************
*** 1207,1215 ****
class VariantConversionMap(dict): #builds a dictionary from {[list,of,keys]function}
! #useful for difining conversion functions for groups of similar data types.
def __init__(self, aDict):
for k, v in aDict.items():
self[k] = v # we must call __setitem__
-
def __setitem__(self, adoType, cvtFn):
"don't make adoType a string :-)"
--- 1298,1305 ----
class VariantConversionMap(dict): #builds a dictionary from {[list,of,keys]function}
! #useful for defining conversion functions for groups of similar data types.
def __init__(self, aDict):
for k, v in aDict.items():
self[k] = v # we must call __setitem__
def __setitem__(self, adoType, cvtFn):
"don't make adoType a string :-)"
***************
*** 1219,1223 ****
except TypeError: # single value
dict.__setitem__(self, adoType, cvtFn)
-
def __getitem__(self, fromType):
try:
--- 1309,1312 ----
***************
*** 1226,1239 ****
return identity
! def _convert_to_python(variant, adType):
! if verbose > 3:
! print 'Converting type_code=%s, val=%s'%(adType,repr(variant))
! print 'conversion function=',repr(variantConversions[adType])
! print ' output=%s'%repr(variantConversions[adType](variant))
! if isinstance(variant,DBNull):
! return None
! return variantConversions[adType](variant)
#initialize variantConversions dictionary used to convert SQL to Python
variantConversions = VariantConversionMap( {
adoDateTimeTypes : variantConvertDate,
--- 1315,1329 ----
return identity
! ##def _convert_to_python(variant, adType):
! ## if verbose > 3:
! ## print 'Converting type_code=%s, val=%s'%(adType,repr(variant))
! ## print 'conversion function=',repr(variantConversions[adType])
! ## print ' output=%s'%repr(variantConversions[adType](variant))
! ## if isinstance(variant,DBNull):
! ## return None
! ## return variantConversions[adType](variant)
#initialize variantConversions dictionary used to convert SQL to Python
+ # this is the dictionary of default convertion functions, built by the class above.
variantConversions = VariantConversionMap( {
adoDateTimeTypes : variantConvertDate,
Index: __init__.py
===================================================================
RCS file: /cvsroot/pywin32/pywin32/adodbapi/__init__.py,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** __init__.py 4 Jan 2008 18:49:09 -0000 1.1.1.1
--- __init__.py 31 Jul 2010 05:48:09 -0000 1.2
***************
*** 1 ****
! from adodbapi import *
\ No newline at end of file
--- 1,3 ----
! import ado_consts
! from adodbapi import *
!
Index: readme.txt
===================================================================
RCS file: /cvsroot/pywin32/pywin32/adodbapi/readme.txt,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** readme.txt 3 May 2010 05:40:33 -0000 1.10
--- readme.txt 31 Jul 2010 05:48:09 -0000 1.11
***************
*** 16,24 ****
* Supports eGenix mxDateTime, Python 2.3 datetime module and Python time module.
* Supports multiple paramstyles: 'qmark' 'named' 'format'
Prerequisites:
* C Python 2.3 or higher
and pywin32 (Mark Hammond's python for windows extensions.)
! Note: as of 2.1.1, adodbapi is included in pywin32 versions 211 and later.
or
Iron Python 2.6 or higher. (works in IPy2.0 for all data types except BUFFER)
--- 16,28 ----
* Supports eGenix mxDateTime, Python 2.3 datetime module and Python time module.
* Supports multiple paramstyles: 'qmark' 'named' 'format'
+ * Supports data retrieval by column name e.g.:
+ for row in myCurser.execute("select name,age from students"):
+ print "Student", row.name, "is", row.age, "years old"
+ * Supports user-definable system-to-Python data convertion functions (selected by ADO data type, or by column)
Prerequisites:
* C Python 2.3 or higher
and pywin32 (Mark Hammond's python for windows extensions.)
! Note: adodbapi is included in pywin32 versions 211 and later.
or
Iron Python 2.6 or higher. (works in IPy2.0 for all data types except BUFFER)
***************
*** 34,49 ****
adodbapi.adodbapi.variantConversions[adodbapi.adNumeric] = write_your_own_convertion_function
............
Whats new in version 2.3.0 # note: breaking changes and default changes!
! This version is all about django support. There are two targets:
! A) MS SQL database connections for mainstream django.
! B) running django on IronPython
Someday, far in the future, this may result in:
! C) MS SQL connections from django running on IronPython on Mono on Linux. (dreams sometimes come true.)
Thanks to Adam Vandenberg for the django modifications.
- The changes are:
1. the ado constants are moved into their own module: ado_consts
This may break some old code, but Adam did it on his version and I like the improvement in readability.
Also, you get better documentation of some results, like convertion of MS data type codes to strings:
>>> ado_consts.adTypeNames[202]
'adVarWChar'
--- 38,84 ----
adodbapi.adodbapi.variantConversions[adodbapi.adNumeric] = write_your_own_convertion_function
............
+ Whats new in version 2.4.0
+ 1. The result of fetchall() and fetchmany() will be an object which emulates a sequence of sequences.
+ The result of fetchone() will be an object which emulates a sequence.
+ [This eliminates creating a tuple of return values.]
+ Also the data are not fetched and converted to Python data types untill actually referred to, therefore...
+ 2. Data can be retrieved from the result sets using the column name (as well as the number).
+ >>> cs = someConnection.cursor()
+ >>> cs.execute('select name, rank, serialNumber from soldiers')
+ >>> rows = cs.fetchall()
+ >>> for soldier in rows:
+ >>> print soldier.name, soldier['rank'], soldier[2]
+ Fred Flintstone private 333-33-3333
+ Barny Rubble sergeant 123-45-6789
+ 3. User defined conversions can be applied at the column level from the 'fetch' object:
+ (continuing the above example)...
+ >>> upcaseConverter=lambda aStringField: aStringField.upper()
+ >>> # now use a single column converter
+ >>> rows.converters[0] = upcaseConverter # convert first column as upper case
+ >>> for soldier in rows:
+ >>> print soldier.name, soldier.rank
+ FRED FLINTSTONE private
+ BARNY RUBBLE sergeant
+ 4. Data may be retrieved by a TWO DIMENSIONAL "extended slicing":
+ >>> cs.execute('select name, rank, serialNumber from soldiers')
+ >>> rows = cs.fetchall()
+ >>> print rows[1,2]
+ 123-45-6789
+ >>> print rows[0,'name']
+ Fred Flintstone
+
Whats new in version 2.3.0 # note: breaking changes and default changes!
! This version is all about django support. There are two hoped-for targets:
! ... A) MS SQL database connections for mainstream django.
! ... B) running django on IronPython
Someday, far in the future, this may result in:
! ... C) MS SQL connections from django running on IronPython on Mono on Linux. (dreams sometimes come true.)
Thanks to Adam Vandenberg for the django modifications.
+ The changes are:
1. the ado constants are moved into their own module: ado_consts
This may break some old code, but Adam did it on his version and I like the improvement in readability.
Also, you get better documentation of some results, like convertion of MS data type codes to strings:
+ >>> import adodbapi.ado_consts as ado_consts
>>> ado_consts.adTypeNames[202]
'adVarWChar'
***************
*** 61,66 ****
when 'named' format is used, the parameters must be in a dict, rather than a sequence.
>>>c = adodbapi.connect('someConnectionString',timeout=30)
! >>>c.paramstyle = 'spam'
! <<<will result in: adodbapi.NotSupportedError: paramstyle="spam" not in:('qmark', 'named', 'format')>>>
** new extension feature **
--- 96,102 ----
when 'named' format is used, the parameters must be in a dict, rather than a sequence.
>>>c = adodbapi.connect('someConnectionString',timeout=30)
! >>>c.paramstyle = 'named'
! >>>cs = c.cursor()
! >>>cs.execute('select * from sometable where firstname = :aname and age = :hisage' , {'aname':'Fred','hisage':35})
** new extension feature **
***************
*** 149,153 ****
Installation
------------
! This version will be installed as part of the win32 package.
Authors (up to version 2.0.1)
--- 185,191 ----
Installation
------------
! For CPython, this version will be installed as part of the win32 package.
! For IronPython (or to update a CPython version early), use "setup.py install"
! while using the Python version upon which you want the package installed.
Authors (up to version 2.0.1)
***************
*** 175,191 ****
-------------
The adodbapi mailing lists have been deactivated. Submit comments to the
! pywin32 lists.
!
!
! Relase history
! --------------
! 2.2.4 Ready for 2to3 convertion. Refactor to be more readable. Added function getIndexedValue() for IPy 2.0.
! 2.2.3 (withdrawn)
! 2.2.2 Iron Python support complete.
! 2.2.1 Bugfix for string truncation
! 2.2 Code cleanup. added feature: "adodbapi.variantConversions[adodbapi.adNumeric] = adodbapi.cvtString"
! 2.1.1 Bugfix to CoIninialize() and nextset()
! 2.1 Python 2.4 version
! 2.0 See what's new above.
! 1.0.1 Bug fix: Null values for numeric fields. Thanks to Tim Golden.
! 1.0 the first release
--- 213,215 ----
-------------
The adodbapi mailing lists have been deactivated. Submit comments to the
! pywin32 or IronPython mailing lists.
|