[Zope] DateTime bug (and ZSybase buglet)
Brian Takashi Hooper
brian@garage.co.jp
Tue, 22 Feb 2000 00:00:19 +0900
Hi there -
(I've taken the liberty of also submitting these bugs to the Collector...)
I think I found a bug with ZSybaseDA (the newest version) - here's the
deal:
I have a table in Sybase with a DateTime field.
When I get a time back from it, the value of the field gets set in
sy_occbf.c to something like:
(2000, 2, 21, 22, 31, 59.63)
The second value is being set to double (on purpose, looking at the
sy_occbf.c code).
The problem with this is that DateTime doesn't correctly validate
floating point hour/min/seconds. The documentation string seems to say
that DateTime can take (from the DateTime 1.43 doc string)
"floating point, positive or negative offsets in units of hours, minutes,
and days,"
for the fourth, fifth and sixth arguments - should this instead be
"positive integer values for hours, minutes, and positive floating point
values for seconds"?
I think the latter might be simpler and easier to understand...
Anyways, right now what DateTime is closer to this anyway - it validates
times by calling self._validTime(h, m, s), which is defined:
def _validTime(self,h,m,s):
return h>=0 and h<=23 and m>=0 and m<=59 and s>=0 and s<=59
I was lucky enough to stumble on the case where 59 < s < 60; this could
be taken care of by:
def _validTime(self,h,m,s):
return h>=0 and h<=23 and m>=0 and m<=59 and s>=0 and s<60.0
Of course, it's obvious that negative hour or minute offsets are also
not going to work...
The Sybase DA end of the thing - as I started out by saying, I noticed
all this because the results that Sybase returned didn't convert
correctly. Specifically, an exception was raised where SybaseDA was in
the middle of handling a fetched result set:
(in db.py, DA.query()...)
if type(v) is TupleType:
v=apply(converters[t], v)
Because an exception is raised in the middle of fetching a result set,
the command structure still has results left to fetch - this makes the
next call to cm.ct_command() fail - Sybase says, on the next query:
ct_command(): user api layer: external error: This routine cannot
be called while results are pending for a command that has been sent to
the server.
Which happens because we never got to cancel the previous result set.
How about running the conversions in a try/except, for safety, like:
try:
if type(v) is TupleType:
v=apply(converters[t], v)
except:
cm.ct_cancel(sy_occ.CS_CANCEL_ALL)
raise Error("Results field conversion error: converter=%s, v=%s" % \
(str(converters[t]), str(v)))
I don't think there is anything else, but anything that might throw an
exception in the error processing loop should also probably be wrapped
to call ct_cancel so that the command structure is ready to go on the
next call.
Well, that's all. This'll be in the Collector as soon as I can write it,
too.
-Brian Hooper