Re: 09.03.0100 cursor failures on various architectures

From: Heikki Linnakangas <hlinnakangas(at)vmware(dot)com>
To: Hiroshi Inoue <inoue(at)tpf(dot)co(dot)jp>
Cc: Christoph Berg <christoph(dot)berg(at)credativ(dot)de>, PostgreSQL ODBC <pgsql-odbc(at)postgresql(dot)org>, psqlodbc(at)packages(dot)debian(dot)org
Subject: Re: 09.03.0100 cursor failures on various architectures
Date: 2014-02-25 16:56:16
Message-ID: 530CCB30.8090606@vmware.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-odbc

On 02/25/2014 05:13 PM, Hiroshi Inoue wrote:
>> >1. Most applications are written with the assumption that SQL_C_LONG
>> >means the native C data type "long". That's clearly what SQL_C_LONG was
>> >supposed to mean when the ODBC specification was written, and that's
>> >what Microsoft's sample code does.
>> >
>> >2. That's*not* how psqlODBC or unixODBC interprets it. With unixODBC,
>> >you should use the C data type "SQLINTEGER" with SQL_C_LONG.
>> >
>> >3. For maximum portability, an application should avoid using SQL_C_xx.
>> >Instead, always use SQL_INTEGER or SQL_BIGINT, with an SQLINTEGER or
>> >SQLBIGINT variable, and cast to native C types.
>> >
>> >We should document this somewhere, like in the FAQ..
> Unfortunately I'm not happy with your summary.
>
> My point is simple.
> Use ODBC data type variables instead of native C data ones when calling
> ODBC APIs.

Hmm, isn't that the same as my point 3?

I was thinking of something like below for the docs:

----
Don't use SQL_C_xxx. They are not part of the SQL/CLI specification, and
hence not reliably portable across platforms. Instead, use the ODBC
variable data types, like SQLINTEGER and SQLBIGINT, and the
corresponding type codes (e.g. SQL_INTEGER and SQL_BIGINT).

For example, the following code is not portable:

long empID;
...
SQLBindCol(stmt, 1, SQL_C_LONG, (SQLPOINTER) &empID,
sizeof(long), &indicator);

Instead, do this:

SQLINTEGER empID;
...
SQLBindCol(stmt, 1, SQL_INTEGER, (SQLPOINTER) &empID,
sizeof(SQLINTEGER), &indicator);

And if necessary, cast to the C type:

long lEmpID = (long) empID;

SQL_C_LONG, SQL_C_SLONG and SQL_C_ULONG in particular are known to be a
problem, as the width of the C datatype "long" varies, but unixODBC and
the psqlODBC driver always maps SQL_C_LONG to a 32-bit data type,
regardless of the width of "long" on the platform. An application using
SQL_C_LONG and "long" will not work correctly on a platform where
sizeof(long) == 8. It is easily seen on big-endian systems, where the
values returned will be off by 2^32, but can also lead to difficult to
find bugs on little-endian systems, as the driver will not initialize
the high 4 bytes.
----

- Heikki

In response to

Responses

Browse pgsql-odbc by date

  From Date Subject
Next Message Ramesh Reddy 2014-02-25 23:19:08 Kerberos/GSSAPI Instructions
Previous Message Hiroshi Inoue 2014-02-25 15:13:12 Re: 09.03.0100 cursor failures on various architectures