[Zope-DB] DCOracle2.1.1 problems

Matthew T. Kromer matt@zope.com
Mon, 15 Jul 2002 10:59:10 -0400

DA Loeffler wrote:

>>>A select query of an empty string field in the Oracle Database
>>>returns the string text "None" (!!!) instead of a None object or an empty string!!!
>>>Could you please tell me, if I have made something wrong or if this is a bug
>>>(known or unknown or probably yet solved)?
>>I'm not aware of anything like that -- it sounds like something is doing 
>>a str() on a value of None.  I'd double-check the invoking code to see 
>>if it's turning results into strings before printing -- nothing in the 
>>DCOracle2 code does that.
>Of course, when you _print_ a None, it prints the string 'None', which
>is what appears in your web page.
>To some extent, isn't this a problem with Python, not with DCOracle2 at
>all? Inasmuch as str(None) makes sense at all, shouldn't it be an empty
>However, one other thing I noticed when I upgraded from DCO1 to DCO2 was
>that for an integer number field, it will return the value in floating
>point form, returning 1 as 1.0; then if you call int() on it, it will
>die on NULL values, as Python quite understandably doesn't like
>int(None). So one has to write a tedious conversion routine whenever one
>wishes to use numbers from a query! I would be keen to see this returned
>to its DCO1 state, where if a number field has its scale
>parameter 0, its value is returned as a Python integer, not a float.

DCO2 should (emphasis on Should) do number conversion to INT when 
precision is 9 digits or less and scale is zero.  If both precision and 
scale are zero, the underlying C module converts to float.  

Here's the relevant code snippet from src/dco2.c:

        if (scale != 0 || (precision == 0 && scale == 0)) {
                sscanf((char *) data, "%lf", &d);
                result = PyFloat_FromDouble(d);
        } else if (precision < 10) {
                sscanf((char *) data, "%ld", &l);
                result = PyInt_FromLong(l);
        } else {
                result = PyLong_FromString((char *)data, NULL, 10);

There's some ugliness with the way DCO2 currently handles numbers that I 
intend to fix at some time in the future (all numbers are fetched from 
the database as SQLT_STR and then converted afterwards).  It isnt 
terribly ugly for regular queries but its AWFUL for stored procedure 
invocation, because it requires the invoking module (DCOracle2) to be 
aware that conversions are taking place.

The reason the precision ==0 and scale == 0 check is there is that my 
experience is that some Oracle connections return zero for both scale 
and precision for NUMBER columns; as such, it isn't known what the real 
scale and precision are.  I just ran a simple test query, and this is 
the case... if you create a NUMBER column, the scale and precision are 
zero.  If you create a column as INTEGER you'll get a precision of 38, 
scale of 0 -- which will turn the result into a python long.

If you want,  you can just change the logic in that section and you will 
be back to the old behavior.  Alternatively, define your columns to be 
NUMBER(9) if you want them to be integers.  I recommend the latter.

Matt Kromer
Zope Corporation  http://www.zope.com/