Martin Evans wrote:
> Tim Bunce wrote:
>> On Thu, Nov 26, 2009 at 07:47:45PM +0000, Martin J. Evans wrote:
>>> Martin Evans wrote:
>>>> Tim,
>>>>
>>>> I'm not sure if you are bothered by this but there appears to be a small
>>>> inconsistency between SQL_INTEGER/SQL_NUMERIC and SQL_DOUBLE handling in
>>>> sql_type_cast:
>>>>
>>>> sql_type_cast("aa", SQL_INTEGER, 0)
>>>>   returns 1 (no cast not strict)
>>>> sql_type_casr("aa", SQL_INTEGER, DBIstcf_STRICT)
>>>>   returns 0 (no cast, strict)
>>>> SQL_NUMERIC works as above (with a fix to the grok stuff)
>>>>
>>>> but
>>>>
>>>> sql_type_cast("aa", SQL_DOUBLE, 0)
>>>>   returns 2 (cast ok) I expected 1
>>>> sql_type_cast("aa", SQL_DOUBLE, DBIstcf_STRICT)
>>>>   returns 2 (cast ok) I expected 0
>>>>
>>>> As you point out in the code if warnings are enabled you get a warning
>>>> but you don't get the expected return.
>>> Would you have any objections to me changing:
>>>
>>>     case SQL_DOUBLE:
>>>         sv_2nv(sv);
>>>         /* SvNOK should be set but won't if sv is not numeric (in which
>>>          * case perl would have warn'd already if -w or warnings are in
>>> effect)
>>>          */
>>>         cast_ok = SvNOK(sv);
>>>         break;
>>>
>>> to
>>>
>>>     case SQL_DOUBLE:
>>>       if (looks_like_number(sv)) {
>>>         sv_2nv(sv);
>>>         /* SvNOK should be set but won't if sv is not numeric (in which
>>>          * case perl would have warn'd already if -w or warnings are in
>>> effect)
>>>          */
>>>         cast_ok = SvNOK(sv);
>>>       } else {
>>>           cast_ok = 0;
>>>       }
>>>         break;
>>>
>>> as this fixes the inconsistency I mentioned above i.e., sv's cast to
>>> doubles which are not numbers return 0 or 1 (depending on STRICT)
>>> instead of always returning 2 (cast ok). I worried a little about this
>>> as you end up with 0 in the NV for a non-numeric and a return of 2 which
>>> looked like the cast worked.
>> What does 
>>     perl -V:.*|grep nv_preserves_uv
>> say for you?
> 
> $ perl -V:.*|grep nv_preserves_uv
> d_nv_preserves_uv='define';
> nv_preserves_uv_bits='32';
> 
>> My reading of Perl_sv_2nv() in sv.c is that ifdef NV_PRESERVES_UV
>> then SvNOK is not set (but SvNOKp is) if grok_number() returns 0
>> into numtype.  The else NV_PRESERVES_UV branch ends with
>>         if (!numtype)
>>             SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK);
>> So either way, if grok_number() returns 0 then SvNOK() should be false.
>>
>> And since looks_like_number is just a wrapper around grok_number I'm not
>> sure what's going on.
>>
>> Perhaps check it in without the change above (so with a failing test)
>> and I might get a change to dig into it.
> 
> ok, I'll check it in as you described later this afternoon and if you
> get a chance to look at it that will be good but in the mean time I'll
> let you know if I get any further with it.

I've looked in to this a little more now and it appears this fails for
Perl < 5.10.1 and works for 5.10.1 so I'm guessing something in svc.c
has changed between those releases. Probably the code you looked at was
the latest source?

Perhaps it was something to do with:

       ยท   The public IV and NV flags are now not set if the string
value has
           trailing "garbage". This behaviour is consistent with not setting
           the public IV or NV flags if the value is out of range for the
           type.


That raises the questions of whether and how to fix this in perl <
5.10.1. The looks_like_number call I originally posted (above) does work
around the issue. I could of course skip the those tests for Perl < 5.10.1.

<snipped stuff>

Martin
-- 
Martin J. Evans
Easysoft Limited
http://www.easysoft.com

Reply via email to