[Zope-Checkins] CVS: Products/DCOracle2/DCOracle2 - DCOracle2.py:1.79
Matthew T. Kromer
matt@zope.com
Thu, 31 Jan 2002 11:52:42 -0500
Update of /cvs-repository/Products/DCOracle2/DCOracle2
In directory cvs.zope.org:/tmp/cvs-serv21509/DCOracle2
Modified Files:
DCOracle2.py
Log Message:
Apply changes from Marc Wilhelm at Apollis Interactive AG (Mark dot Wilhelm AT
ai dot AG)
=== Products/DCOracle2/DCOracle2/DCOracle2.py 1.78 => 1.79 ===
import types
import time
-from string import split, join, upper, find
+from string import split, join, upper, find, replace
version = "$Revision$" [11:-2] + " (dco2: %s %s)" % (
dco2.__version__, dco2.buildDefs)
@@ -53,6 +53,7 @@
paramstyle = 'numeric' # We do 'named' too
DEFAULTPROCSIZE=256
+DEFAULTSIZE_SQL_STR=32000
def connect(dsn=None, user=None, password=None, database=None):
@@ -651,6 +652,7 @@
arraysize = 200
rowcount = -1
description = None
+ _fetch_out_of_sequence = 0
__allow_access_to_unprotected_subobjects__ = 1 # For Zope
def __init__(self, c, connection):
@@ -736,6 +738,8 @@
if self._cursor is None:
raise InterfaceError,"cursor is closed"
+ self._fetch_out_of_sequence = 0
+
if operation is None: operation = self._operation
if self._operation != operation or self._nullmap is None:
@@ -795,7 +799,21 @@
else:
self._cursor.bindbyname(ck, p)
- result = self._cursor.execute()
+ # AI-Patch: Workaround for oracle error ORA-0468 after
+ # updating of existing packages or procedures
+ # via "create or replace package..." without restarting
+ # the python script.
+ #
+ # [MK -- does the procedure need to be redescribed?]
+ try:
+ result = self._cursor.execute()
+ except dco2.DatabaseError, e:
+ # ORA-0468: exsting state of packages has been discarded
+ if int(e[0])== 4068:
+ result = self._cursor.execute() # Try again
+ else:
+ raise
+
self.rowcount = self._cursor.rowcount()
self.description = self.describe()
if result == 8:
@@ -814,6 +832,10 @@
def executemany(self, operation, params):
if self._cursor is None:
raise InterfaceError,"cursor is closed"
+
+ # AI-Patch: mark that we haven't fetched any result yet
+ self._fetch_out_of_sequence = 0
+
prepared = 0
if self._operation != operation:
self._cursor.prepare(operation)
@@ -942,7 +964,16 @@
def fetchone(self,skip=0):
if self._cursor is None:
raise InterfaceError,"cursor is closed"
- if self._result is not None and self._rcount >= len(self._result[0]):
+
+ # AI-Patch: after we have once detected that there
+ # no more data, return directly None
+ if self._fetch_out_of_sequence:
+ return None
+
+ # AI-Patch: only clear the buffer when we have passed all results
+ # and when the result buffer was completely filled
+ # <self._rcount==self.arraysize>
+ if self._result is not None and self._rcount >= len(self._result[0]) and self._rcount==self.arraysize:
self._result = None
self._rcount = -1
@@ -967,6 +998,11 @@
try:
v = col[self._rcount].value()
except IndexError:
+ # AI-Patch: Mark the end of data so that we don't
+ # try to fetch again data out of the cursor
+ # which could result in hanging cursors in a
+ # multithreading environment
+ self._fetch_out_of_sequence = 1
self._result = None
return None
# Note that if we got back a dco2.cursor, we need to wrap it
@@ -1140,7 +1176,15 @@
#print "Binding argument %s= %s" % (v, keymap[v])
else:
if len(args) <= argsused:
- raise ValueError, "Not enough arguments"
+
+ # AI-Patch: Handling optional IN-Parameters
+ # for stored procedures by ignoring missing
+ # params and inform user.
+ # Hmm, should we also check if the params
+ # has had a default value??
+ #print "DCOracle2> Warning: not enough arguments! Treat them as optional IN param"
+ continue
+ #raise ValueError, "Not enough arguments"
argmap.append([args[argsused], d[3][5], d[3]])
#print "Binding argument %s= %s" % (v, args[argsused])
argsused = argsused + 1
@@ -1166,17 +1210,28 @@
# doesn't properly handle IN OUT
if 'OUT' in a[1] and type(a[0]) is not dco2.BindingArrayObjectType:
# BindingArrays are made with count, size, type
+ dty = a[2][0]
l = a[2][2]
if cursor is not None:
try:
l = cursor._sizes[i]
except IndexError: pass
- if l is None or l == 0: l = DEFAULTPROCSIZE
+ if l is None or l == 0:
+ # AI-PATCH: use a greater result buffer
+ # for varchar2 out params
+ if dty == 1:
+ l = DEFAULTSIZE_SQL_STR
+ else:
+ l = DEFAULTPROCSIZE
+
# Need to use the setoutputsize parameter
if l == 0:
- l = DEFAULTPROCSIZE
-
- dty = a[2][0]
+ # AI-PATCH: use a greater result buffer
+ # for varchar2 out params
+ if dty == 1:
+ l = DEFAULTSIZE_SQL_STR
+ else:
+ l = DEFAULTPROCSIZE
# Based on the data type, we may need to do some special
# transforms (e.g. sending numbers through as strings)
@@ -1296,7 +1351,10 @@
if (desc.has_key(sname) and desc[sname][2] == 'package'):
(schema, uname, type, pdesc) = desc[sname]
- if uname is None: uname = name
+
+ # AI-Patch: for python2.2 we need an
+ # additional condition <uname==''>
+ if uname is None or uname=='': uname = name
# Set up the package
if self._schema is None: sname = name
else: sname = "%s.%s" % (self._schema, name)
@@ -1378,7 +1436,15 @@
LONG = "long"
FLOAT = "float"
for i in xrange(len(ba)):
- f = float(ba[i])
+
+ # AI-Patch: if you run oracle in a german environment
+ # you get a float as string in a german format with
+ # a "," for the fraction
+ try:
+ f = float(ba[i])
+ except ValueError:
+ f = float(replace(ba[i],",","."))
+
l = long(f)
try:
n = int(f)