[Zope-DB] CVS: Products/DCOracle2/DCOracle2 - DCOracle2.py:1.72
Matthew T. Kromer
matt@zope.com
Mon, 8 Oct 2001 10:26:02 -0400
Update of /cvs-repository/Products/DCOracle2/DCOracle2
In directory cvs.zope.org:/tmp/cvs-serv17149/DCOracle2
Modified Files:
DCOracle2.py
Log Message:
Updated patch for Christopher Jenkins; execute() with initial NULLs for non
string columns requires a reprepare on subsequent execution with same statement
handle due to type mismatches in the bind handles.
=== Products/DCOracle2/DCOracle2/DCOracle2.py 1.71 => 1.72 ===
#
+_nonullmap = []
+
class cursor:
_cursor = None
@@ -641,6 +643,7 @@
self._connection = connection
self._sizes = []
self._mapproc = {}
+ self._nullmap = None
# NONAPI
@@ -689,6 +692,7 @@
self._cursor.close()
self._cursor = None
self._connection = None
+ self._nullmap = None
# NONAPI
def isOpen(self):
@@ -698,20 +702,31 @@
def prepare(self, statement):
self._cursor.prepare(statement)
self._operation = statement
+ self._nullmap = {}
# execute
#
# the special keyword parameter is '__plist' which the stored
# procedure __call__ method uses to invoke with a list of paramters
+
+ #
+ # The _nonullmap and _nullmap business is to force a re-prepare when
+ # an initial bind was done with a NULL parameter (None) which gets bound
+ # as SQLT_STR. The nullmap maps which parameters are None -- after an
+ # initial execute, if no entries are in the map, it is replaced with
+ # _nonullmap, an empty list; which is a signal to stop checking it until
+ # the next normal prepare.
+ #
def execute(self, operation=None, *params, **kw):
if self._cursor is None:
raise InterfaceError,"cursor is closed"
if operation is None: operation = self._operation
- if self._operation != operation:
+ if self._operation != operation or self._nullmap is None:
self._cursor.prepare(operation)
self._operation = operation
+ self._nullmap = {}
if self._prefetch:
apply(self._cursor.setPrefetch, self._prefetch)
@@ -745,6 +760,8 @@
# Bind positional parameters
for p in params:
i = i + 1
+ if p is None and self._nullmap is not _nonullmap:
+ self._nullmap[i] = 1
#print "binding %d with %s" % (i, p)
if type(p) == types.InstanceType and issubclass(p.__class__,
TypeCoercion):
@@ -757,6 +774,8 @@
ck = ":" + key
#print "binding %s as %s" % (ck, kw[key])
p = kw[key]
+ if p is None and self._nullmap is not _nonullmap:
+ self._nullmap[key] = 1
if type(p) == types.InstanceType and issubclass(p.__class__,
TypeCoercion):
self._cursor.bindbyname(ck, p.value, p.type)
@@ -771,6 +790,12 @@
if self._operation != so: self._operation = so # Force rebind
if not result == 1:
self.description = None
+
+ if len(self._nullmap) > 0:
+ self._nullmap = None
+ else:
+ self._nullmap = _nonullmap
+
return result
def executemany(self, operation, params):
@@ -781,6 +806,7 @@
self._cursor.prepare(operation)
self._operation = operation
prepared = 1
+ self._nullmap = None
# Potential note for named parameters: coerce all positional
# parameters to named parameters 'by number' e.g. using the postion
@@ -826,6 +852,7 @@
for c in xrange(columns):
if notnull[c] == 0:
self._cursor.prepare(operation)
+ self._nullmap = None
self._operation = self._operation + " " # force rebind next
break