[Zope-DB] CVS: Products/DCOracle2/DCOracle2 - DCOracle2.py:1.71

Matthew T. Kromer matt@zope.com
Fri, 5 Oct 2001 10:41:46 -0400


Update of /cvs-repository/Products/DCOracle2/DCOracle2
In directory cvs.zope.org:/tmp/cvs-serv29767/DCOracle2

Modified Files:
	DCOracle2.py 
Log Message:
NULL column handling fixes for problems reported by Christopher Jenkins.
dco2 will keep datatypes on Nulls for rebinds, instead of snaping to SQLT_STR.
DCOracle2 scans columns on executemany() to determine to reprepare the statement
and get the a non-None value for making a type determination.


=== Products/DCOracle2/DCOracle2/DCOracle2.py 1.70 => 1.71 ===
         if self._cursor is None:
             raise InterfaceError,"cursor is closed"
+        prepared = 0
         if self._operation != operation:
                 self._cursor.prepare(operation)
                 self._operation = operation
+                prepared = 1
 
         # Potential note for named parameters:  coerce all positional 
         # parameters to named parameters 'by number' e.g. using the postion
@@ -795,11 +797,15 @@
         first = 1
 
         BATCHSZ = 1000
+        notnull = []
+
+        for c in xrange(columns): notnull.append(0)
 
         # First, figure out the maximum column widths
         for r in xrange(rows):
             for c in xrange(columns):
                 p = params[r][c]
+                if p is not None: notnull[c] = 1
                 try:
                     if type(p) == types.InstanceType and issubclass(p.__class__,                        TypeCoercion):
                         # Allow type override
@@ -811,11 +817,26 @@
                 if r == 0: size.append(l)
                 elif size[c] < l: size[c] = l
 
+        # if any columns were all None, we force a prepare to flush out
+        # old bindings -- note that a duplicate prepare can result when
+        # execute() does a prepare, then calls executemany() with a column
+        # of all NULLs
+
+        if prepared == 0:
+            for c in xrange(columns):
+                if notnull[c] == 0:
+                    self._cursor.prepare(operation)
+                    self._operation = self._operation + " " # force rebind next
+                    break
 
         # Second, create a binding array for each column
         baoa = []
         for c in xrange(columns):
-            p = params[0][c]
+            # Don't try to use None as a type -- keep going for non None
+            # to get real type
+            for i in xrange(rows):
+                p = params[i][c]
+                if p is not None: break
             if type(p) == types.InstanceType and issubclass(p.__class__,
                 TypeCoercion):