Mono vs. MS .NET column type conversion options - summary

2 zobrazení
Přeskočit na první nepřečtenou zprávu

Lukasz Kosewski

nepřečteno,
14. 9. 2008 15:55:5514.09.08
komu: Avery Pennarun, Peter McCurdy, versap...@groups.google.com
Ah, my inaugural post to the Versaplex mailing list - yay!

So... as y'all may or may not know, I'm currently working on making
all of the Versaplex/VxODBC unit tests pass when running them from
Mono in Linux, and running WvDBusd + Versaplexd on a Windows XP box.

The primary (and in fact, only outstanding) issue is type conversion;
that is, Versaplexd running through Mono has a different map of SQL
types to .NET types than Mono does. A canonical example is that
'bigint' SQL columns are typed System.Decimal in Mono and System.Int64
in .NET.

I had some prior ideas on this, but the final summary after a weekend
of research is the following:
- bigint columns are, as above Decimals in Mono and Int64's in .NET.
- when returning a number (for something like "select DATALEN() ... ",
apenwarr was right, and both implementations attempt to find a
'boxing' type that fits the SQL return value:
- Mono tries to use bytes, 16-bit ints, 32-bit ints, and then Decimal.
- .NET tries to use bytes, 16-bit ints, 32-bit ints, 64-bit ints,
and *then* Decimal.
- Mono sends back the max number of *characters* for a column of type
(n)Varchar, whereas MS .NET sends back the max number of *bytes* (+ 1
for a null terminator - ??).

As a temporary patch, I've fixed up the Versaplexd unit tests to
understand this, and not freak out when they received an Int64 when
expecting a Decimal.

Leaving it this way, and not touching Versaplexd further, has the
following ramifications:
- no changes to existing code.
- Any dynamic languages talking to versaplexd will function whether we
are using Mono or .NET for versaplexd, as they will just unbox an
Int64 and a Decimal to their own internal numeric type = no real
difference to the user.
- any defensively written query code will still work (ie. if the
caller does not *assume* a particular data type for a column and runs
the returned data through a casting/demangling function).
- anything else will fail if written for a particular (Mono vs. NET)
runtime environment for versaplexd; anytime anyone assumes a
particular return type for an integer, the code could freak out.

The *correct* solution (as proposed by apenwarr), I now believe, is to
basically forget Int64's exist; when Versaplex queries the DB and
returns anything that comes back as an Int64, cast it to Decimal,
adjust the corresponding VxColumnInfo, and send the adjustment back to
the caller.

Naturally, I've got such an implementation sitting right here, also
tested, but not pushed up if people think this is overkill :)
Pros: - Versaplex will work consistently over .NET and Mono.
Cons: - Performance loss (as apenwarr points out, negligible) doing
operations on Decimals rather than Int64's, and a corresponding
increase in amount of data transferred (Int64's are all 8 bits,
Decimals are transcribed to strings and then sent over => usually more
bits).

This doesn't solve the varchar length problem; I'm inclined not to
worry about that, really, unless people say otherwise?

What do people think? I'm personally heavily in favour of checking
this in, but I thought I'd get any suggestions and/or flames first.

The proposed patch is attached below for reference.
Also attached is a patch to apply to the Linux-side unit tests in
order for them to pass :)

Luke

remove_int64t_patch.diff
make_unit_tests_pass.diff

Avery Pennarun

nepřečteno,
14. 9. 2008 18:22:4814.09.08
komu: versap...@googlegroups.com, Peter McCurdy, versap...@groups.google.com
On Sun, Sep 14, 2008 at 3:55 PM, Lukasz Kosewski <lkos...@navarra.ca> wrote:
> As a temporary patch, I've fixed up the Versaplexd unit tests to
> understand this, and not freak out when they received an Int64 when
> expecting a Decimal.
>
> Leaving it this way, and not touching Versaplexd further, has the
> following ramifications:
> [...]

> - anything else will fail if written for a particular (Mono vs. NET)
> runtime environment for versaplexd; anytime anyone assumes a
> particular return type for an integer, the code could freak out.
>
> The *correct* solution (as proposed by apenwarr), I now believe, is to
> basically forget Int64's exist; when Versaplex queries the DB and
> returns anything that comes back as an Int64, cast it to Decimal,
> adjust the corresponding VxColumnInfo, and send the adjustment back to
> the caller.

So I'm not *very* happy with either solution, but no better ones occur
to me. The solution you have now has the advantage that it's
explicitly non-uniform: your app is responsible to being defensively
written, and if it doesn't work right, it's your fault and you should
fix it. Moreover, just by writing your app's unit tests with
versaplexd on each platform, you should be able to find most of the
problems. Of course, this assumes developers will test their
applications carefully, which is a bad assumption, so the end result
is applications that won't be as portable as they want.

The second one is nicer in this it puts responsibility for portability
in *one* place (versaplexd). The down side is that if we ever change
it (eg. because mono fixes their bugs and we want the wasted
performance back), we'll potentially break end user applications that
trusted us to keep things uniform and were thus not written as
defensively.

I think both options suck :) But I am vaguely inclined to leave the
versaplexd code as is (non-uniform, but unit tests passing) just
because we can be relatively sure that mono will fix their bugs
eventually... possibly before versaplexd has any users other than me
:) In that case, we win.

Have fun,

Avery

Avery Pennarun

nepřečteno,
14. 9. 2008 18:22:4814.09.08
komu: versap...@googlegroups.com, Peter McCurdy, versap...@groups.google.com
On Sun, Sep 14, 2008 at 3:55 PM, Lukasz Kosewski <lkos...@navarra.ca> wrote:
> As a temporary patch, I've fixed up the Versaplexd unit tests to
> understand this, and not freak out when they received an Int64 when
> expecting a Decimal.
>
> Leaving it this way, and not touching Versaplexd further, has the
> following ramifications:
> [...]

> - anything else will fail if written for a particular (Mono vs. NET)
> runtime environment for versaplexd; anytime anyone assumes a
> particular return type for an integer, the code could freak out.
>
> The *correct* solution (as proposed by apenwarr), I now believe, is to
> basically forget Int64's exist; when Versaplex queries the DB and
> returns anything that comes back as an Int64, cast it to Decimal,
> adjust the corresponding VxColumnInfo, and send the adjustment back to
> the caller.

So I'm not *very* happy with either solution, but no better ones occur

Odpovědět všem
Odpověď autorovi
Přeposlat
0 nových zpráv