Обсуждение: 09.03.0100 cursor failures on various architectures

Поиск
Список
Период
Сортировка

09.03.0100 cursor failures on various architectures

От
Christoph Berg
Дата:
Hi,

I've uploaded 09.03.0100 to Debian, but the build daemons for various
architectures are reporting regression test failures for the "cursors"
test, e.g. on mipsel:

/usr/lib/postgresql/9.3/lib/pgxs/src/makefiles/../../src/test/regress/pg_regress --inputdir=./
--psqldir='/usr/lib/postgresql/9.3/bin'   --launcher=./launcher --dbname=contrib_regression sampletables connect
stmthandlesselect commands multistmt getresult prepare params notice arraybinding insertreturning dataatexecution
boolsascharcvtnulldate alter quotes cursors positioned-update catalogfunctions 
(using postmaster on localhost, port 5432)
============== dropping database "contrib_regression" ==============
HINWEIS:  Datenbank „contrib_regression“ existiert nicht, wird übersprungen
DROP DATABASE
============== creating database "contrib_regression" ==============
CREATE DATABASE
ALTER DATABASE
============== running regression test queries        ==============
[...]
test cursors                  ... FAILED
[...]

=======================
 1 of 20 tests failed.
=======================

regression.diffs:
*** /home/myon/psqlodbc-09.03.0100/test/expected/cursors.out    2013-12-17 15:16:00.000000000 +0100
--- /home/myon/psqlodbc-09.03.0100/test/results/cursors.out     2014-02-12 11:33:34.787112560 +0100
***************
*** 1,7 ****
  \! ./src/cursors-test
  connected
! SQL_CURSOR_COMMIT_BEHAVIOR: SQL_CB_PRESERVE
! SQL_CURSOR_ROLLBACK_BEHAVIOR: SQL_CB_PRESERVE

  foo1 foo2 foo3 foo4 foo5 foo6 foo7 foo8 foo9 foo10 foo11 foo12 foo13 foo14 foo15 foo16 foo17 foo18 foo19 foo20 ...
foo3207foo3208 foo3209 foo3210 
  Fetched 3210 rows altogether
--- 1,7 ----
  \! ./src/cursors-test
  connected
! SQL_CURSOR_COMMIT_BEHAVIOR: unknown (728104962)
! SQL_CURSOR_ROLLBACK_BEHAVIOR: unknown (728104962)

  foo1 foo2 foo3 foo4 foo5 foo6 foo7 foo8 foo9 foo10 foo11 foo12 foo13 foo14 foo15 foo16 foo17 foo18 foo19 foo20 ...
foo3207foo3208 foo3209 foo3210 
  Fetched 3210 rows altogether


The problem is the same on mips, mipsel, powerpc, s390x, and sparc.
(With different numbers in brackets after the "unknown".)

s390x has that problem, plus an additional diff for positioned-update:

*** /«PKGBUILDDIR»/test/expected/positioned-update.out    Tue Dec 17 14:16:00 2013
--- /«PKGBUILDDIR»/test/results/positioned-update.out    Wed Feb  5 17:09:31 2014
***************
*** 13,19 ****
  2    2
  3    3
  4    4
! 105    5
  7    7
  8    8
  9    9
--- 13,19 ----
  2    2
  3    3
  4    4
! 5    5
  7    7
  8    8
  9    9


The full build logs can be seen on
https://buildd.debian.org/status/package.php?p=psqlodbc

(ia64 is also failing, but that looks like a unixodbc problem, and
ia64 will be going away in Debian soonish anyway.)

Does anyone have an idea what's the problem here? The package was
building basically fine before; some builds were somewhat fragile due
to unixodbc problems and had to be retried manually, but these
failures are new and are reproducible.

Mit freundlichen Grüßen,
Christoph Berg
--
Senior Berater, Tel.: +49 (0)21 61 / 46 43-187
credativ GmbH, HRB Mönchengladbach 12080, USt-ID-Nummer: DE204566209
Hohenzollernstr. 133, 41061 Mönchengladbach
Geschäftsführung: Dr. Michael Meskes, Jörg Folz, Sascha Heuer
pgp fingerprint: 5C48 FE61 57F4 9179 5970  87C6 4C5A 6BAB 12D2 A7AE

Вложения

Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
On 02/12/2014 12:45 PM, Christoph Berg wrote:
> I've uploaded 09.03.0100 to Debian, but the build daemons for various
> architectures are reporting regression test failures for the "cursors"
> test, e.g. on mipsel:
>[...]
> The problem is the same on mips, mipsel, powerpc, s390x, and sparc.

It was a bug in the cursors test case. It was passing pointer to an
SQLUINTEGER variable to SQLGetInfo(..., SQL_CURSOR_COMMIT_BEHAVIOR,
...), but that property is a SQLUSMALLINT. On a little-endian system it
didn't make a difference, as SQLGetInfo set the low 2 bytes, but on
big-endian it's more visible.

Fixed, thanks for the report!

> s390x has that problem, plus an additional diff for positioned-update:
>
> *** /«PKGBUILDDIR»/test/expected/positioned-update.out    Tue Dec 17 14:16:00 2013
> --- /«PKGBUILDDIR»/test/results/positioned-update.out    Wed Feb  5 17:09:31 2014
> ***************
> *** 13,19 ****
>    2    2
>    3    3
>    4    4
> ! 105    5
>    7    7
>    8    8
>    9    9
> --- 13,19 ----
>    2    2
>    3    3
>    4    4
> ! 5    5
>    7    7
>    8    8
>    9    9

Hmm. I'll take a look..

- Heikki


Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
On 02/12/2014 12:45 PM, Christoph Berg wrote:
> s390x has that problem, plus an additional diff for positioned-update:
>
> *** /«PKGBUILDDIR»/test/expected/positioned-update.out    Tue Dec 17 14:16:00 2013
> --- /«PKGBUILDDIR»/test/results/positioned-update.out    Wed Feb  5 17:09:31 2014
> ***************
> *** 13,19 ****
>    2    2
>    3    3
>    4    4
> ! 105    5
>    7    7
>    8    8
>    9    9
> --- 13,19 ----
>    2    2
>    3    3
>    4    4
> ! 5    5
>    7    7
>    8    8
>    9    9

This is also an issue related to endianess and mismatched datatypes. The
problem is with the SQLBindCol call. Positioned-update test does this:

long    colvalue;
...
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, &colvalue, 0, &indColvalue);

And SQLBindCol does this:

case SQL_C_SLONG:
case SQL_C_LONG:
   len = 4;
   if (bind_size > 0)
     *((SQLINTEGER *) rgbValueBindRow) = atol(neut_str);
   else
     *((SQLINTEGER *) rgbValue + bind_row) = atol(neut_str);
   break;

So, SQLBindPos assumes that the target variable is of type SQLINTEGER,
when the caller indicated that it's SQL_C_LONG. My gut reaction is that
that's bogus - if the caller said that it's of C-type long, by passing
SQL_C_LONG, we should believe that, rather than assume that SQL_C_LONG
means SQLINTEGER. I found a brief thread on this on the unixodbc-dev
mailing list:

http://mailman.unixodbc.org/pipermail/unixodbc-dev/2005-March/000396.html

The same author raised the issue also on the psqlodbc mailing list:

http://www.postgresql.org/message-id/flat/4224F80D.2080103@kkcsm.net#4224F80D.2080103@kkcsm.net

Microsoft has a table of SQL_C_* codes and which C types they correspond
to (http://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx),
but that's not taking into account other operating systems where the
widths of C integer types are different. We didn't explicitly discuss in
that psqlodbc mailing list thread if it's sane that SQL_C_LONG means a
32-bit integer regardless of how wide the C "long" type actually is.
While I think the way the code currently works is wrong, it's probably
too late to change that. It would be interesting to know how other ODBC
drivers have interpreted that.

Conclusion: I've committed a patch to change the test case to use
SQLINTEGER instead of long as the variable's datatype. I also added an
explicit test case for SQLBindCol.

- Heikki


Re: 09.03.0100 cursor failures on various architectures

От
Christoph Berg
Дата:
Re: Heikki Linnakangas 2014-02-14 <52FE1220.9050205@vmware.com>
> Conclusion: I've committed a patch to change the test case to use
> SQLINTEGER instead of long as the variable's datatype. I also added
> an explicit test case for SQLBindCol.

Oh cool. Thanks for looking into this :)

I had already uploaded your first fix a few minutes before you posted
the second message, and the results look promising, with s390x (and
ia64) still failing.

https://buildd.debian.org/status/package.php?p=psqlodbc

Will try the other patch as well now.

Christoph
--
cb@df7cb.de | http://www.df7cb.de/

Вложения

Re: 09.03.0100 cursor failures on various architectures

От
Christoph Berg
Дата:
Re: To Heikki Linnakangas 2014-02-14 <20140214135452.GC15607@msgid.df7cb.de>
> Will try the other patch as well now.

Works, thanks again for the patches.

Christoph
--
cb@df7cb.de | http://www.df7cb.de/

Вложения

Re: 09.03.0100 cursor failures on various architectures

От
"Inoue, Hiroshi"
Дата:
(2014/02/14 21:54), Heikki Linnakangas wrote:
> On 02/12/2014 12:45 PM, Christoph Berg wrote:
>> s390x has that problem, plus an additional diff for positioned-update:
>>
>> *** /«PKGBUILDDIR»/test/expected/positioned-update.out    Tue Dec 17
>> 14:16:00 2013
>> --- /«PKGBUILDDIR»/test/results/positioned-update.out    Wed Feb  5
>> 17:09:31 2014
>> ***************
>> *** 13,19 ****
>>    2    2
>>    3    3
>>    4    4
>> ! 105    5
>>    7    7
>>    8    8
>>    9    9
>> --- 13,19 ----
>>    2    2
>>    3    3
>>    4    4
>> ! 5    5
>>    7    7
>>    8    8
>>    9    9
>
> This is also an issue related to endianess and mismatched datatypes. The
> problem is with the SQLBindCol call. Positioned-update test does this:
>
> long    colvalue;
> ...
> rc = SQLBindCol(hstmt, 1, SQL_C_LONG, &colvalue, 0, &indColvalue);
>
> And SQLBindCol does this:
>
> case SQL_C_SLONG:
> case SQL_C_LONG:
>    len = 4;
>    if (bind_size > 0)
>      *((SQLINTEGER *) rgbValueBindRow) = atol(neut_str);
>    else
>      *((SQLINTEGER *) rgbValue + bind_row) = atol(neut_str);
>    break;
>
> So, SQLBindPos assumes that the target variable is of type SQLINTEGER,
> when the caller indicated that it's SQL_C_LONG. My gut reaction is that
> that's bogus - if the caller said that it's of C-type long, by passing
> SQL_C_LONG, we should believe that, rather than assume that SQL_C_LONG
> means SQLINTEGER. I found a brief thread on this on the unixodbc-dev
> mailing list:
>
> http://mailman.unixodbc.org/pipermail/unixodbc-dev/2005-March/000396.html
>
> The same author raised the issue also on the psqlodbc mailing list:
>
> http://www.postgresql.org/message-id/flat/4224F80D.2080103@kkcsm.net#4224F80D.2080103@kkcsm.net
>
> Microsoft has a table of SQL_C_* codes and which C types they correspond
> to (http://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx),
> but that's not taking into account other operating systems where the
> widths of C integer types are different. We didn't explicitly discuss in
> that psqlodbc mailing list thread if it's sane that SQL_C_LONG means a
> 32-bit integer regardless of how wide the C "long" type actually is.

I don't think so.
Where do you find references to OS native C types in ODBC's spec?
ODBC uses its own SQL types in its spec and each SQL_C_xxxxxxx
stands for one of them not a native one.

For 32bit integers, use SQL_C_LONG (SQLINTEGER).
For 64bit integers, use SQL_C_BIGINT (SQLBIGINT).
There's no type named SQLxxLONGxx.

I can see the following line in sqlext.h provided by Microsoft or unixODBC.

#define SQL_C_LONG    SQL_INTEGER          /* INTEGER
    */

It means that those driver manager think SQL_C_LONG means SQLINTEGER.
What meaning does it have to take different way from the driver manager
whose APIs ODBC applications call?

regards,
Hiroshi Inoue




--
I am using the free version of SPAMfighter.
SPAMfighter has removed 5285 of my spam emails to date.
Get the free SPAMfighter here: http://www.spamfighter.com/len

Do you have a slow PC? Try a Free scan
http://www.spamfighter.com/SLOW-PCfighter?cid=sigen



Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
On 02/25/2014 06:09 AM, Inoue, Hiroshi wrote:
> (2014/02/14 21:54), Heikki Linnakangas wrote:
>> Microsoft has a table of SQL_C_* codes and which C types they correspond
>> to (http://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx),
>> but that's not taking into account other operating systems where the
>> widths of C integer types are different. We didn't explicitly discuss in
>> that psqlodbc mailing list thread if it's sane that SQL_C_LONG means a
>> 32-bit integer regardless of how wide the C "long" type actually is.
>
> I don't think so.
> Where do you find references to OS native C types in ODBC's spec?
> ODBC uses its own SQL types in its spec and each SQL_C_xxxxxxx
> stands for one of them not a native one.

See the page I linked to above. It has a table with a one-to-one-to-one
relationship between the SQL_C_xxx, ODBC C typedef, and the native C
type. For example, for SQL_C_LONG, it says that the corresponding ODBC
type is SQLINTEGER, which equals to C "long int".

Such a one-to-one-to-one relationship is clear as far as Microsoft is
concerned, as in Windows "long int" is always a 32-bit integer. From the
SQL_C_xxx names it's quite clear that SQL_C_LONG refers to the native C
type, "long". And as long as you're working in a Microsoft environment,
there's no confusion because sizeof(long) == sizeof(SQLINTEGER). But on
other platforms, it's a different story.

Looking at my draft copy of the SQL 2011 standard, "Part 3: Call-Level
Interface (SQL/CLI)", I don't see any mention of the SQL_C_* data types.
It was probably left out of the standard, precisely because it would've
caused confusion on non-Microsoft platforms.

> For 32bit integers, use SQL_C_LONG (SQLINTEGER).
> For 64bit integers, use SQL_C_BIGINT (SQLBIGINT).
> There's no type named SQLxxLONGxx.
>
> I can see the following line in sqlext.h provided by Microsoft or unixODBC.
>
> #define SQL_C_LONG    SQL_INTEGER          /* INTEGER
>      */
>
> It means that those driver manager think SQL_C_LONG means SQLINTEGER.
> What meaning does it have to take different way from the driver manager
> whose APIs ODBC applications call?

Yeah, that's how unixODBC has resolved the situation, but it's not
obvious. In fact, I'd argue that most applications are *not* written
that way. For example, look at this code example from Microsoft:

http://technet.microsoft.com/en-us/library/aa177876%28v=sql.80%29.aspx

It does this:

long        lEmpID;
...
SQLBindCol(hStmt, 1, SQL_C_LONG, (SQLPOINTER) &lEmpID, sizeof(long),
      &pIndicators[0]);

That sample code will *not* work with unixodbc on a big-endian platform
where sizeof(long) == 8.

See also
http://mailman.unixodbc.org/pipermail/unixodbc-support/2008-June/001756.html.
According to that post, while unixODBC takes the stance that SQL_C_LONG
corresponds to a 32-bit SQLINTEGER, iodbc has taken a different view. On
iodbc, SQL_C_LONG means C native type "long", whether it's 32-bits or
64-bits wide. That's reasonable; thanks to that decision, the above
sample code would work on iodbc without modifications. (However, now
that I actually look at the iODBC code in their git repository, ISTM
they're also defining SQL_C_LONG to bit 32-bits, ie. the same as
unixODBC. Weird, maybe they changed their mind at some point..)

Just to be clear, I agree with the decision that SQL_C_LONG means a
32-bit type, regardless of sizeof(long). But it's not obvious! That
decision will break applications.

In summary:

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..

- Heikki


Re: 09.03.0100 cursor failures on various architectures

От
Hiroshi Inoue
Дата:
(2014/02/25 20:05), Heikki Linnakangas wrote:
> On 02/25/2014 06:09 AM, Inoue, Hiroshi wrote:
>> (2014/02/14 21:54), Heikki Linnakangas wrote:
>>> Microsoft has a table of SQL_C_* codes and which C types they correspond
>>> to (http://msdn.microsoft.com/en-us/library/ms714556%28v=vs.85%29.aspx),
>>> but that's not taking into account other operating systems where the
>>> widths of C integer types are different. We didn't explicitly discuss in
>>> that psqlodbc mailing list thread if it's sane that SQL_C_LONG means a
>>> 32-bit integer regardless of how wide the C "long" type actually is.
>>
>> I don't think so.
>> Where do you find references to OS native C types in ODBC's spec?
>> ODBC uses its own SQL types in its spec and each SQL_C_xxxxxxx
>> stands for one of them not a native one.
>
> See the page I linked to above. It has a table with a one-to-one-to-one
> relationship between the SQL_C_xxx, ODBC C typedef, and the native C
> type. For example, for SQL_C_LONG, it says that the corresponding ODBC
> type is SQLINTEGER, which equals to C "long int".
>
> Such a one-to-one-to-one relationship is clear as far as Microsoft is
> concerned, as in Windows "long int" is always a 32-bit integer. From the
> SQL_C_xxx names it's quite clear that SQL_C_LONG refers to the native C
> type, "long". And as long as you're working in a Microsoft environment,
> there's no confusion because sizeof(long) == sizeof(SQLINTEGER). But on
> other platforms, it's a different story.
>
> Looking at my draft copy of the SQL 2011 standard, "Part 3: Call-Level
> Interface (SQL/CLI)", I don't see any mention of the SQL_C_* data types.
> It was probably left out of the standard, precisely because it would've
> caused confusion on non-Microsoft platforms.
>
>> For 32bit integers, use SQL_C_LONG (SQLINTEGER).
>> For 64bit integers, use SQL_C_BIGINT (SQLBIGINT).
>> There's no type named SQLxxLONGxx.
>>
>> I can see the following line in sqlext.h provided by Microsoft or
>> unixODBC.
>>
>> #define SQL_C_LONG    SQL_INTEGER          /* INTEGER
>>      */
>>
>> It means that those driver manager think SQL_C_LONG means SQLINTEGER.
>> What meaning does it have to take different way from the driver manager
>> whose APIs ODBC applications call?
>
> Yeah, that's how unixODBC has resolved the situation, but it's not
> obvious.

ISTM unixODBC team was only bothering about what SQLINTEGER is.
They were not bothering about what ODBC data type SQL_C_LONG
corresponds to.

  In fact, I'd argue that most applications are *not* written
> that way. For example, look at this code example from Microsoft:

We sometimes see such inappropriate examples in Mircorsoft document.
ODBC applications should use ODBC data type variables to insulate
the app from platform-specific requirements.

> http://technet.microsoft.com/en-us/library/aa177876%28v=sql.80%29.aspx
>
> It does this:
>
> long        lEmpID;
> ...
> SQLBindCol(hStmt, 1, SQL_C_LONG, (SQLPOINTER) &lEmpID, sizeof(long),
>       &pIndicators[0]);
>
> That sample code will *not* work with unixodbc on a big-endian platform
> where sizeof(long) == 8.
>
> See also
> http://mailman.unixodbc.org/pipermail/unixodbc-support/2008-June/001756.html.
> According to that post, while unixODBC takes the stance that SQL_C_LONG
> corresponds to a 32-bit SQLINTEGER, iodbc has taken a different view. On
> iodbc, SQL_C_LONG means C native type "long", whether it's 32-bits or
> 64-bits wide.

Didn't SQL_C_LONG stand for SQLINTEGER anyway?

 > That's reasonable; thanks to that decision, the above
> sample code would work on iodbc without modifications. (However, now
> that I actually look at the iODBC code in their git repository, ISTM
> they're also defining SQL_C_LONG to bit 32-bits, ie. the same as
> unixODBC. Weird, maybe they changed their mind at some point..)
>
> Just to be clear, I agree with the decision that SQL_C_LONG means a
> 32-bit type, regardless of sizeof(long). But it's not obvious! That
> decision will break applications.
>
> In summary:
>
> 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.

regards,
Hiroshi Inoue


Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
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


Re: 09.03.0100 cursor failures on various architectures

От
"Inoue, Hiroshi"
Дата:
(2014/02/26 1:56), Heikki Linnakangas wrote:
> 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.

Why does using SQL_C_XXXX lose portablity?
Even though SQL/CLI is a standard, ODBC also has been a (defact?)
standard which is older than CLI and widely used.
They are different standard.
We should begin a project e.g. pgsqlcli when we are to stop
using SQL_C_XXXX.

 > 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);

Though the code works well, the code is wrong as an ODBC application
in principle.
The code works as expected simply because SQL_INTEGER has the same
value as SQL_C_LONG has fortunately.

> 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,

I see no problem except the naming which should have been SQL_C_INTEGER.

regards,
Hiroshi Inoue



--
I am using the free version of SPAMfighter.
SPAMfighter has removed 5330 of my spam emails to date.
Get the free SPAMfighter here: http://www.spamfighter.com/len

Do you have a slow PC? Try a Free scan
http://www.spamfighter.com/SLOW-PCfighter?cid=sigen



Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
On 02/26/2014 03:19 AM, Inoue, Hiroshi wrote:
> (2014/02/26 1:56), Heikki Linnakangas wrote:
>> 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.
>
> Why does using SQL_C_XXXX lose portablity?

SQL_C_xxx is a Microsoft-only extension, so it's not guaranteed to work
with all SQL/CLI implementations. In practice, unixODBC defines
SQL_C_xxx too, so in practice an application using them will work.

I think you're advocating for this:

SQLINTEGER        lEmpID;
...
SQLBindCol(hStmt, 1, SQL_C_LONG, (SQLPOINTER) &lEmpID, sizeof(SQLINTEGER),
       &pIndicators[0]);

 From a readability point of view, IMHO that's just bizarre. The
SQLBindCall call is claiming to the driver that the variable is of type
"long", by specifying SQL_C_LONG. But in reality, the variable is of
type SQLINTEGER. You can argue that SQL_C_LONG doesn't mean that the
variable is of type "long", but "SQLINTEGER", but that's just bizarre.
The name SQL_C_LONG very clearly says "long", just like SQL_C_SHORT says
"short".

It works on Windows, because sizeof(long) == sizeof(SQLINTEGER) on
Windows, and it works with unixODBC because unixODBC defines SQL_C_LONG
as 32-bits regardless of the actual width of "long". But it's not a good
way to write an application. Why use the ODBC extension SQL_C_LONG
instead of the SQL_INTEGER type code specified by SQL/CLI? SQL_INTEGER
is more clear, and as a bonus, it also complies with SQL/CLI.

So while the combination of SQL_C_LONG type code and SQLINTEGER variable
works, I would not recommend that. The SQL_INTEGER type code and
SQLINTEGER variable combination is more clear.

> Even though SQL/CLI is a standard, ODBC also has been a (defact?)
> standard which is older than CLI and widely used.
> They are different standard.
> We should begin a project e.g. pgsqlcli when we are to stop
> using SQL_C_XXXX.

ODBC is a superset of SQL/CLI [1]. An application written for SQL/CLI
works with ODBC libraries and drivers. But not the other way round; an
application that's written to the ODBC spec does not necessarily work
with other SQL/CLI implementations.

The driver already works with both ODBC and SQL/CLI, so there's no need
to start a new project for that.

Of course, if you don't care about portability of your application, you
can write it relying purely on ODBC, and use SQL_C_LONG type code and
"long" variables. But if you want to maximize portability, you should
stick to the SQL/CLI spec and use SQL_INTEGER type code and SQLINTEGER
variables.

>   > 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);
>
> Though the code works well, the code is wrong as an ODBC application
> in principle.
> The code works as expected simply because SQL_INTEGER has the same
> value as SQL_C_LONG has fortunately.

That is not an accident. The ODBC specification is a superset of the
SQL/CLI specification. An application written for the SQL/CLI
specification also works with ODBC, so for maximum portability you
should use the SQL/CLI type codes (SQL_INTEGER etc.).

[1] http://msdn.microsoft.com/en-us/library/ms712622%28v=vs.85%29.aspx

- Heikki


Re: 09.03.0100 cursor failures on various architectures

От
Hiroshi Inoue
Дата:
(2014/02/26 17:51), Heikki Linnakangas wrote:
> On 02/26/2014 03:19 AM, Inoue, Hiroshi wrote:
>> (2014/02/26 1:56), Heikki Linnakangas wrote:
>>> 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.
>>
>> Why does using SQL_C_XXXX lose portablity?
>
> SQL_C_xxx is a Microsoft-only extension, so it's not guaranteed to work
> with all SQL/CLI implementations. In practice, unixODBC defines
> SQL_C_xxx too, so in practice an application using them will work.
>
> I think you're advocating for this:
>
> SQLINTEGER        lEmpID;
> ...
> SQLBindCol(hStmt, 1, SQL_C_LONG, (SQLPOINTER) &lEmpID, sizeof(SQLINTEGER),
>        &pIndicators[0]);
>
>  From a readability point of view, IMHO that's just bizarre. The
> SQLBindCall call is claiming to the driver that the variable is of type
> "long", by specifying SQL_C_LONG. But in reality, the variable is of
> type SQLINTEGER. You can argue that SQL_C_LONG doesn't mean that the
> variable is of type "long", but "SQLINTEGER", but that's just bizarre.
> The name SQL_C_LONG very clearly says "long",just like SQL_C_SHORT says
> "short".

> It works on Windows, because sizeof(long) == sizeof(SQLINTEGER) on
> Windows, and it works with unixODBC because unixODBC defines SQL_C_LONG
> as 32-bits regardless of the actual width of "long".

The ODBC spec clearly mentiones that SQL_C_LONG corresponds to
SQLINTEGER from the first. Why do you often skip SQLINTEGER?
It's a result that Microsoft, unixODBC or iODBC defines SQLINTEGER
as 32-bit integers. The problem for unixODBC or iODBC was whether
SQLINTEGER means 32-bits or 64-bits.

 > But it's not a good
> way to write an application. Why use the ODBC extension SQL_C_LONG
> instead of the SQL_INTEGER type code specified by SQL/CLI? SQL_INTEGER
> is more clear, and as a bonus, it also complies with SQL/CLI.

Aren't you forgetting ODBC is very old?
Though ODBC and sql/cli are closely related, ODBC is older than
sql/cli. When ODBC was introduced more than 20 years ago,
Microsoft didn't have 32-bit OS yet. That's why SQLINTEGER was
was denoted as *long int* not *int*. It meant 32-bit integrs for
both their working 16-bit OS and coming 32-bit OS.
Of cource the spec was only for 16/32bit. There was no guarantee
how the 64-bit spec would be in the future. At the time pretty many
people expected that int in future 64-bit OSes would be 64-bit integers.
So I don't surprize even if SQLINTEGER means 64-bit integers sometime
somewhere. But I don't believe SQL_C_LONG stands for the type other than
SQLINTEGER. Please tell me where I can find such a fact.

Now int still means 32-bit integers in many 64-bit platforms. People
still needs 32-bit integers as well as 64-bit integers. So ODBC also
needed 32-bit integers.

> So while the combination of SQL_C_LONG type code and SQLINTEGER variable
> works, I would not recommend that. The SQL_INTEGER type code and
> SQLINTEGER variable combination is more clear.
>
>> Even though SQL/CLI is a standard, ODBC also has been a (defact?)
>> standard which is older than CLI and widely used.
>> They are different standard.
>> We should begin a project e.g. pgsqlcli when we are to stop
>> using SQL_C_XXXX.
>
> ODBC is a superset of SQL/CLI [1]. An application written for SQL/CLI
> works with ODBC libraries and drivers. But not the other way round; an
> application that's written to the ODBC spec does not necessarily work
> with other SQL/CLI implementations.

Though you emphasize ODBC is a superset, ODBC was not a superset
of sql/cli from the first. In the first place SQL/CLI didn't exist
when ODBC was introduced. Of cource SQL_C_XXXX was not an extension
of sql/cli spec then. You can't find SQL_C_XXXX because SQL_C_XXXX
is a C-specific concept and maybe sql/cli shrinked the spec so as
to avoid language-specific concept. As a result the spec uses the
same notations SQL_xxxx for different kind of concepts. ODBC uses
different notations for different kind of concepts.
Which do you prefer?

When ODBC was introduced more than 20 years ago, working OSs of
Mirosoft was 16-bit ones. 32-bit integers must have been denoted
as *long int*. They used SQL_C_LONG because *long* was the most
portable data type which means 32-bit integers then.

Now I'm examining what SQLINTEGER means in SQL/CLI spec though
it may be an old one.
Hmmm, could you please tell me SQLINTEGER is a 32-bit integer,
64-bit one or platform-dependent one on 64-bit platforms?
I find a line
    SQLINTEGER long  Length of buffers for column data and ...
Is it right in the latest spec?

regards,
Hiroshi Inoue


Re: 09.03.0100 cursor failures on various architectures

От
Heikki Linnakangas
Дата:
On 02/27/2014 01:30 PM, Hiroshi Inoue wrote:
> (2014/02/26 17:51), Heikki Linnakangas wrote:
>> It works on Windows, because sizeof(long) == sizeof(SQLINTEGER) on
>> Windows, and it works with unixODBC because unixODBC defines SQL_C_LONG
>> as 32-bits regardless of the actual width of "long".
>
> The ODBC spec clearly mentiones that SQL_C_LONG corresponds to
> SQLINTEGER from the first.

It also clearly says that the native C type corresponding SQL_C_LONG and
SQL_INTEGER is "long". That's all true in the Microsoft world, but on a
platform where sizeof(long) == 8, one of the equivalences must be
broken. SQL_C_LONG has to correspong to either SQLINTEGER, or "long".
The ODBC spec naturally doesn't say which one, because it's not
concerned with other platforms.

>   > But it's not a good
>> way to write an application. Why use the ODBC extension SQL_C_LONG
>> instead of the SQL_INTEGER type code specified by SQL/CLI? SQL_INTEGER
>> is more clear, and as a bonus, it also complies with SQL/CLI.
>
> Aren't you forgetting ODBC is very old?
> Though ODBC and sql/cli are closely related, ODBC is older than
> sql/cli. When ODBC was introduced more than 20 years ago,
> Microsoft didn't have 32-bit OS yet. That's why SQLINTEGER was
> was denoted as *long int* not *int*. It meant 32-bit integrs for
> both their working 16-bit OS and coming 32-bit OS.
> Of cource the spec was only for 16/32bit. There was no guarantee
> how the 64-bit spec would be in the future. At the time pretty many
> people expected that int in future 64-bit OSes would be 64-bit integers.

Yeah, I understand the history.

> So I don't surprize even if SQLINTEGER means 64-bit integers sometime
> somewhere.
> But I don't believe SQL_C_LONG stands for the type other than
> SQLINTEGER. Please tell me where I can find such a fact.

Surely, in the early ODBC versions, SQL_C_LONG clearly meant "long", not
SQLINTEGER. That's why it's called SQL_C_*LONG*.

When 64-bit operating systems arrived, that became confusing because it
was no longer a given that "long" is 32-bits. It was not a problem for
Microsoft and the ODBC spec, because on Windows, "long" is indeed
32-bits. So in the ODBC spec, SQL_C_LONG stands for both SQLINTEGER and
"long", because they are the same.

But for the cross-platform CLI specification, that was not good enough.
To resolve the situation, they didn't bring in the SQL_C_* type codes.
Instead, you use the SQL_INTEGER type code, and it refers to an
SQLINTEGER variable.

>>> Even though SQL/CLI is a standard, ODBC also has been a (defact?)
>>> standard which is older than CLI and widely used.
>>> They are different standard.
>>> We should begin a project e.g. pgsqlcli when we are to stop
>>> using SQL_C_XXXX.
>>
>> ODBC is a superset of SQL/CLI [1]. An application written for SQL/CLI
>> works with ODBC libraries and drivers. But not the other way round; an
>> application that's written to the ODBC spec does not necessarily work
>> with other SQL/CLI implementations.
>
> Though you emphasize ODBC is a superset, ODBC was not a superset
> of sql/cli from the first. In the first place SQL/CLI didn't exist
> when ODBC was introduced. Of cource SQL_C_XXXX was not an extension
> of sql/cli spec then. You can't find SQL_C_XXXX because SQL_C_XXXX
> is a C-specific concept and maybe sql/cli shrinked the spec so as
> to avoid language-specific concept. As a result the spec uses the
> same notations SQL_xxxx for different kind of concepts. ODBC uses
> different notations for different kind of concepts.

Yeah.

> Which do you prefer?

I would recommend applications to not use SQL_C_xxx type codes. I would
recommend using a SQLINTEGER variable with SQL_INTEGER type code. That's
the most readable, and most portable option.

(I actually like the idea of separate SQL_C_xxx type codes, to refer to
the native types. I agree it's slightly confusing to use the same
SQL_INTEGER code to refer to the SQL data type, and the C variable's
datatype. But alas, if SQL_C_LONG doesn't in fact mean "long", then
that's even more confusing, and it's better to stay away from that. With
SQL_INTEGER, at least it's clear that it refers to an SQLINTEGER
variable. I wish unixOdbc had chosen differently, and decided that
SQL_C_LONG != SQL_INTEGER, and it refers to "long", whatever "long" is
on your platform. IMHO that would've been more clear. But it's too late
to worry about that.)

> When ODBC was introduced more than 20 years ago, working OSs of
> Mirosoft was 16-bit ones. 32-bit integers must have been denoted
> as *long int*. They used SQL_C_LONG because *long* was the most
> portable data type which means 32-bit integers then.
>
> Now I'm examining what SQLINTEGER means in SQL/CLI spec though
> it may be an old one.
> Hmmm, could you please tell me SQLINTEGER is a 32-bit integer,
> 64-bit one or platform-dependent one on 64-bit platforms?
> I find a line
>     SQLINTEGER long  Length of buffers for column data and ...
> Is it right in the latest spec?

Hmm, I don't see that line in my copy. But it does include a sample
sqlcli.h header file that has this in Annex H:

typedef long SQLINTEGER;
typedef long long SQLBIGINT;

That probably assumes that "long" is 32-bits wide. The Annex has been
marked as "informative", so it's only meant as an example, though.

It's worth noting that if you use SQL_INTEGER type code and SQLINTEGER
variable consistently, and avoid SQL_C_LONG and "long", it doesn't
matter whether SQLINTEGER is 32- or 64-bits wide. It also doesn't matter
if SQL_C_LONG == SQL_INTEGER. Your application will work regardless of that.

- Heikki


Re: 09.03.0100 cursor failures on various architectures

От
Hiroshi Inoue
Дата:
(2014/02/28 18:53), Heikki Linnakangas wrote:
> On 02/27/2014 01:30 PM, Hiroshi Inoue wrote:
>> (2014/02/26 17:51), Heikki Linnakangas wrote:
>>> It works on Windows, because sizeof(long) == sizeof(SQLINTEGER) on
>>> Windows, and it works with unixODBC because unixODBC defines SQL_C_LONG
>>> as 32-bits regardless of the actual width of "long".
>>
>> The ODBC spec clearly mentiones that SQL_C_LONG corresponds to
>> SQLINTEGER from the first.
>
> It also clearly says that the native C type corresponding SQL_C_LONG and
> SQL_INTEGER is "long".

It's foramtive as you taught me about SQLINTEGER in SQL/CLI.
Microsoft gave an example which can be used in their working
16-bit OSs and comimg 32-bit OSs.

Please note that at that time neither SQL/CLI nor ODBC guaranteed
that the spec would be valid under 64-bit paltforms.
It was not so long ago the spec of 64-bit ODBC was determined.

>> Though you emphasize ODBC is a superset, ODBC was not a superset
>> of sql/cli from the first. In the first place SQL/CLI didn't exist
>> when ODBC was introduced. Of cource SQL_C_XXXX was not an extension
>> of sql/cli spec then. You can't find SQL_C_XXXX because SQL_C_XXXX
>> is a C-specific concept and maybe sql/cli shrinked the spec so as
>> to avoid language-specific concept. As a result the spec uses the
>> same notations SQL_xxxx for different kind of concepts. ODBC uses
>> different notations for different kind of concepts.
>
> Yeah.
>
>> Which do you prefer?
>
> I would recommend applications to not use SQL_C_xxx type codes. I would
> recommend using a SQLINTEGER variable with SQL_INTEGER type code. That's
> the most readable, and most portable option.

> (I actually like the idea of separate SQL_C_xxx type codes, to refer to
> the native types.

Unfortunately such a use is inappropriate in database programing.
For example I can find the following in SQL/CLI spec.

2.2.2 Data type for C
   For binary compatibility of object modules, applications must use
   symbolic data types defined ...

It's very important and you are saying the opposite of SQL/CLI
recommendation from the first.
What you have to discuss with is the Open Group not unixODBC.

>> Now I'm examining what SQLINTEGER means in SQL/CLI spec though
>> it may be an old one.
>> Hmmm, could you please tell me SQLINTEGER is a 32-bit integer,
>> 64-bit one or platform-dependent one on 64-bit platforms?
>> I find a line
>>     SQLINTEGER long  Length of buffers for column data and ...
>> Is it right in the latest spec?
>
> Hmm, I don't see that line in my copy. But it does include a sample
> sqlcli.h header file that has this in Annex H:
>
> typedef long SQLINTEGER;
> typedef long long SQLBIGINT;
>
> That probably assumes that "long" is 32-bits wide.

It's very important whether SQLINTEGER means 32-bit or 64-bit
in 64-bit platforms. If SQLINTEGER means 64-bit integers in
SQL/CLI, I have to tell members of this list not to use it.

> The Annex has been
> marked as "informative", so it's only meant as an example, though.

Yes it's formative. And so is for ODBC. As you emphasized many times
ODBC became a superset of SQL/CLI conseqently.

regards,
Hiroshi Inoue