[R-sig-DB] NULL data not mapped to NA with RODBC on 64-bit Mac OS X
Harlan Harris
h@r|@n @end|ng |rom h@rr|@@n@me
Tue Mar 22 18:31:43 CET 2011
Hello,
I seem to have hit a bug in RODBC on 64-bit versions of R on Mac OS X. I'm
running R 2.12.1, and using R to talk to Oracle and other databases using
RODBC 1.3-2. In 32-bit mode (R32), everything works. (The ODBC drivers are
the ones from Actual.) In 64-bit mode (R), it seems as if NULL data is not
being treated as missing. For example, a NULL value in an integer column is
being returned as a 0 instead, which is wrong/bad.
Diving into the code and Google a bit, it seems like an issue that's been
seen before in other contexts. Here's the relevant C code, from
RODBCFetchRows:
for(row = thisHandle->rowsUsed;
row < thisHandle->rowsFetched && j <= maximum;
j++, row++)
{
thisHandle->rowsUsed++;
if(j > blksize) {
blksize *= 2;
for (i = 0; i < nc; i++)
SET_VECTOR_ELT(data, i,
lengthgets(VECTOR_ELT(data, i), blksize));
}
for (i = 0; i < nc; i++) {
SQLLEN len = thisHandle->ColData[i].IndPtr[row];
switch(thisHandle->ColData[i].DataType) {
case SQL_DOUBLE:
REAL(VECTOR_ELT(data, i))[j-1] =
len == SQL_NULL_DATA ? NA_REAL :
thisHandle->ColData[i].RData[row];
break;
etc...
Googling for SQL_NULL_DATA and related terms finds this page, about the same
issue in a Python driver:
http://code.google.com/p/pyodbc/issues/detail?id=51
It appears as if SQLLEN might be unsigned in 64-bit builds, while
SQL_NULL_DATA is -1. Casting len to be an int rather than an unsigned int
seems to solve the problem for them.
On my machine, /usr/include/sqltypes.h starts like this:
/*
* sqltypes.h
*
* $Id: sqltypes.h,v 1.23 2007/10/07 13:27:13 source Exp $
*
* ODBC typedefs
*
* The iODBC driver manager.
and defines SQLLEN as follows:
#ifdef _WIN64
typedef INT64 SQLLEN;
typedef UINT64 SQLULEN;
typedef UINT64 SQLSETPOSIROW;
#elif defined(STRICT_ODBC_TYPES)
typedef long SQLLEN;
typedef unsigned long SQLULEN;
typedef unsigned short SQLSETPOSIROW;
#else
#define SQLLEN long
#define SQLULEN unsigned long
#define SQLSETPOSIROW unsigned short
#endif
Seems to me like SQLLEN should be signed, but apparently not?
Can anyone help? Thank you!
-Harlan
[[alternative HTML version deleted]]
More information about the R-sig-DB
mailing list