Re: Problem retrieving a numeric(38,0) value as SQL_NUMERIC_STRUCT if value needs to use all 16 SQLCHAR elements of the val array - Mailing list pgsql-odbc

From Hiroshi Inoue
Subject Re: Problem retrieving a numeric(38,0) value as SQL_NUMERIC_STRUCT if value needs to use all 16 SQLCHAR elements of the val array
Date
Msg-id 539845FE.30107@tpf.co.jp
Whole thread Raw
In response to Re: Problem retrieving a numeric(38,0) value as SQL_NUMERIC_STRUCT if value needs to use all 16 SQLCHAR elements of the val array  (Heikki Linnakangas <hlinnakangas@vmware.com>)
Responses Re: Problem retrieving a numeric(38,0) value as SQL_NUMERIC_STRUCT if value needs to use all 16 SQLCHAR elements of the val array  (Heikki Linnakangas <hlinnakangas@vmware.com>)
List pgsql-odbc
Thanks for your investigation.

I don't object to the change.
Probably few people used SQL_C_NUMERIC extensively.

regards,
Hiroshi Inoue

(2014/06/10 17:34), Heikki Linnakangas wrote:
> Ugh, the decimal->binary conversion algorithm is really ugly even before
> this patch, and the patch doesn't make it any prettier. It took me quite
> a while to understand how it works: it repeatedly divides the base-10
> representation by two, and outputs the reminder bit. There are much
> better and faster ways to convert from decimal to binary, and they're
> not really any more complicated either.
>
> The binary->decimal conversion in ResolveNumericParam is even more ugly.
> To be honest, I still don't understand the algorithm behind it, but it
> looks complicated and slow. There's a fast-path for small numbers that
> fit in an UInt4, which doesn't make it any simpler.
>
> Aside from ugly and slow, the binary->decimal conversion is also buggy:
>
> 1.The following input creates a core dump with "Floating point exception":
>
> precision=3, scale=50, val=0x02 0x03
>
> 2. Building the final output string is broken if scale is large, e.g.
> this produces garbage output:
>
> precision=25, scale=80
>
> ERROR: invalid input syntax for type numeric:
> "p.000`000H0000000000000000000000aT000000000000000000000000000000000000000000000770";
>
>
> 3. The param_string buffer allocated for the result of the
> binary->decimal conversion is too small. The buffer is 128 bytes, but a
> numeric can have a scale as large as 127. That won't fit, as the sign
> and decimal dot use two more bytes.
>
> I propose the attached patch to fix all of the above, rewriting the
> binary->decimal and decimal->binary conversions altogether. It fixes all
> of the known issues, the ones listed above and the one Walter reported.
> It also adds a regression test for all of them.
>
> Can anyone come up with some more special cases that this patched or the
> old conversion might handle incorrectly, for adding to the regression
> suite?
>
>
> One more thing: The precision works in a funny way, if you pass a "val"
> with more bits than fit in precision. I filled the val-bytes with 0x9F
> 0x86 0x01, which corresponds to 99999 in decimal. I passed that as a
> param with different precisions:
>
> sign 1 prec 1 scale 0 val 9F8601:
>      159
> sign 1 prec 2 scale 0 val 9F8601:
>      159
> sign 1 prec 3 scale 0 val 9F8601:
>      34463
> sign 1 prec 4 scale 0 val 9F8601:
>      34463
> sign 1 prec 5 scale 0 val 9F8601:
>      99999
> sign 1 prec 6 scale 0 val 9F8601:
>      99999
>
> The conversion algorithm seems to assume that there are no extra bits in
> the val-array that don't fit within the precision. Perhaps that's a
> reasonable assumption, but I think it would be more robust to ignore any
> extra bits if they are there, rather than sometimes take some of them
> into account. (Or, always parse all the bits, ignoring the precision.) I
> did that in the attached patch.
>
> However, according to this article I found from Microsoft:
> https://support.microsoft.com/kb/222831
>
> "The precision and scale fields of the numeric structure are never used
> for input from an application, only for output from the driver to the
> application."
>
> So we probably should be ignoring them completely, and get the precision
> and scale from elsewhere.
>
>
> PS. ResolveNumericParam always returns TRUE. That's fortunate, because
> the caller would incorrectly fall through the switch-case if it didn't..
> When the code was added, it fell through to the "default" case, but the
> interval-cases were later added in between, breaking it. But it's not a
> live bug, since ResolveNumericParam always returns TRUE. Fixed that too
> in the attached patch.
>
> - Heikki
>



pgsql-odbc by date:

Previous
From: Hiroshi Inoue
Date:
Subject: Re: Need new psqlODBC release to update OpenSSL again
Next
From: Hiroshi Saito
Date:
Subject: Re: Need new psqlODBC release to update OpenSSL again