Обсуждение: ODBC : SQLGetData question

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

ODBC : SQLGetData question

От
Dev Kumkar
Дата:
Hi,

I have a question regarding ODBC call SQLGetData.

SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len)

In case the column value is 'PG' then the value of my_buff_length gets populated as 2 which is the expected value but in the call above in case the table's column has value NULL then value of my_buff_len gets populated as 4294967295 which is 4GB,
instead shouldn't my_buff_len get populated as SQL_NULL_DATA?

Postgres ODBC Driver version - 9.2.1
Platform - RHEL 5

Regards..

Re: ODBC : SQLGetData question

От
aihtdikh
Дата:
Hi,

SQLGetData expects the buffer length parameter to be a SQLLEN variable,
which is a signed type.
SQL_NULL_DATA is defined as -1, which is 4294967295 if you interpret it
as an unsigned type.

Your my_buff_len variable is being set to SQL_NULL_DATA correctly, but
you are looking at it wrong.
Change it to be the correct type, and it will work as you expect.

Regards,
Harun


On 14/05/14 13:23, Dev Kumkar wrote:
> Hi,
>
> I have a question regarding ODBC call SQLGetData.
>
> SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len)
>
> In case the column value is 'PG' then the value of my_buff_length gets
> populated as 2 which is the expected value but in the call above in
> case the table's column has value NULL then value of my_buff_len gets
> populated as 4294967295 which is 4GB,
> instead shouldn't my_buff_len get populated as SQL_NULL_DATA?
>
> Postgres ODBC Driver version - 9.2.1
> Platform - RHEL 5
>
> Regards..



Re: ODBC : SQLGetData question

От
Dev Kumkar
Дата:
On Wed, May 14, 2014 at 12:10 PM, aihtdikh <aihtdikh@gmail.com> wrote:
Hi,

SQLGetData expects the buffer length parameter to be a SQLLEN variable, which is a signed type.
SQL_NULL_DATA is defined as -1, which is 4294967295 if you interpret it as an unsigned type.

Your my_buff_len variable is being set to SQL_NULL_DATA correctly, but you are looking at it wrong.
Change it to be the correct type, and it will work as you expect.

Regards,
Harun

Thanks for the reply.

my_buff_len is defined as SQLLEN
      SQLLEN  my_buff_len;

      SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len)

       if (my_buff_len == SQL_NULL_DATA)
       {
            // Doesn't come here
       }

What is being missed above?

Regards...

Re: ODBC : SQLGetData question

От
Dev Kumkar
Дата:
On Wed, May 14, 2014 at 12:51 PM, Dev Kumkar <devdas.kumkar@gmail.com> wrote:
On Wed, May 14, 2014 at 12:10 PM, aihtdikh <aihtdikh@gmail.com> wrote:
Hi,

SQLGetData expects the buffer length parameter to be a SQLLEN variable, which is a signed type.
SQL_NULL_DATA is defined as -1, which is 4294967295 if you interpret it as an unsigned type.

Your my_buff_len variable is being set to SQL_NULL_DATA correctly, but you are looking at it wrong.
Change it to be the correct type, and it will work as you expect.

Regards,
Harun

Thanks for the reply.

my_buff_len is defined as SQLLEN
      SQLLEN  my_buff_len;


      SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len)

       if (my_buff_len == SQL_NULL_DATA)
       {
            // Doesn't come here
       }

What is being missed above?

Regards...

if ((int)my_buff_len == SQL_NULL_DATA)
       {
            // will come here
       }

The above casting solves the problem, please review?

Regards...

Re: ODBC : SQLGetData question

От
Nick Gorham
Дата:
On 14/05/14 08:46, Dev Kumkar wrote:
On Wed, May 14, 2014 at 12:51 PM, Dev Kumkar <devdas.kumkar@gmail.com> wrote:
On Wed, May 14, 2014 at 12:10 PM, aihtdikh <aihtdikh@gmail.com> wrote:
Hi,

SQLGetData expects the buffer length parameter to be a SQLLEN variable, which is a signed type.
SQL_NULL_DATA is defined as -1, which is 4294967295 if you interpret it as an unsigned type.

Your my_buff_len variable is being set to SQL_NULL_DATA correctly, but you are looking at it wrong.
Change it to be the correct type, and it will work as you expect.

Regards,
Harun

Thanks for the reply.

my_buff_len is defined as SQLLEN
      SQLLEN  my_buff_len;


      SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len)

       if (my_buff_len == SQL_NULL_DATA)
       {
            // Doesn't come here
       }

What is being missed above?

Regards...

if ((int)my_buff_len == SQL_NULL_DATA)
       {
            // will come here
       }

The above casting solves the problem, please review?

Regards...

Just to suggest.

I would guess the application expects sizeof( SQLLEN ) == 8 and the driver sizeof( SQLLEN ) == 4

--
Nick Gorham

Re: ODBC : SQLGetData question

От
aihtdikh
Дата:
On 14/05/14 15:46, Dev Kumkar wrote:
>
>
>     my_buff_len is defined as SQLLEN
>           SQLLEN  my_buff_len;
>
>
> if ((int)my_buff_len == SQL_NULL_DATA)
>        {
>             // will come here
>        }
>
> The above casting solves the problem, please review?
>
That will work around the issue, but I'm stumped as to why it was not
working for you already.

It seems like your platform must be 64bit, and something somewhere is
converting what should be a 64bit SQLLEN into a 32bit value, but I can't
find anywhere in the source that does anything unsafe in this regard -
it's SQLLEN all the way.

Edit: Ah, Nick may be on the right path there.
Could the driver have been compiled with a different sqltypes.h than the
application?
If so, you could try compiling the driver under the same setup as your
application to see if that fixes it.


Regards,
Harun



Re: ODBC : SQLGetData question

От
Dev Kumkar
Дата:

On Wed, May 14, 2014 at 2:17 PM, aihtdikh <aihtdikh@gmail.com> wrote:
That will work around the issue, but I'm stumped as to why it was not working for you already.

It seems like your platform must be 64bit, and something somewhere is converting what should be a 64bit SQLLEN into a 32bit value, but I can't find anywhere in the source that does anything unsafe in this regard - it's SQLLEN all the way.

Edit: Ah, Nick may be on the right path there.
Could the driver have been compiled with a different sqltypes.h than the application?
If so, you could try compiling the driver under the same setup as your application to see if that fixes it.


Regards,
Harun
Yes, the platform is 64-bit.
We are deploying the driver as it is and not compiling it in-house currently.

Do you see any issues with the (int) typecast done for SQLLEN?

Regards...

Re: ODBC : SQLGetData question

От
aihtdikh
Дата:
On 14/05/14 17:07, Dev Kumkar wrote:
> Yes, the platform is 64-bit.
> We are deploying the driver as it is and not compiling it in-house
> currently.
>
> Do you see any issues with the (int) typecast done for SQLLEN?
>
It will certainly work for this call to SQLGetData, now that you know
the workaround.
However, I can't guess where else issues may appear if there really is a
mismatch in data size between the driver, odbc manager and/or the
application. It may work right now, but for me, I would certainly be
trying to get to the bottom of it in case it causes more weird problems.

Regards,
Harun



Re: ODBC : SQLGetData question

От
Nick Gorham
Дата:
On 14/05/14 10:07, Dev Kumkar wrote:

On Wed, May 14, 2014 at 2:17 PM, aihtdikh <aihtdikh@gmail.com> wrote:
That will work around the issue, but I'm stumped as to why it was not working for you already.

It seems like your platform must be 64bit, and something somewhere is converting what should be a 64bit SQLLEN into a 32bit value, but I can't find anywhere in the source that does anything unsafe in this regard - it's SQLLEN all the way.

Edit: Ah, Nick may be on the right path there.
Could the driver have been compiled with a different sqltypes.h than the application?
If so, you could try compiling the driver under the same setup as your application to see if that fixes it.


Regards,
Harun
Yes, the platform is 64-bit.
We are deploying the driver as it is and not compiling it in-house currently.

In that case compile the application with the same setup as the driver.

Do you see any issues with the (int) typecast done for SQLLEN?

Yes, if your app ever expects the driver to return an array of results (for example) it will go badly wrong very quickly. Also, if the driver is 64 bit SQLLEN and the application 32 bit, a SQLGetData will be writing to memory that happens to be after the indicator variable, that will not end well.

--
Nick

Re: ODBC : SQLGetData question

От
Dev Kumkar
Дата:
On Wed, May 14, 2014 at 3:38 PM, Nick Gorham <nick@lurcher.org> wrote:
We are deploying the driver as it is and not compiling it in-house currently.
Yes, the platform is 64-bit.

In that case compile the application with the same setup as the driver.

Thanks again for the help here. I think as you mentioned before the application expects sizeof( SQLLEN ) == 8 and the driver sizeof( SQLLEN ) == 4 which results into this issue.

Actually tried to initialize my_buff_len = SQL_NULL_DATA;
The next printf correctly prints the value of my_buff_length as -1.

Only after SQLGetData(my_stmt, my_col_no, SQL_C_CHAR, &my_max_len, 0, &my_buff_len) the value of my_buff_len becomes 429496729.

Is it possible the ODBC header files on machine where am compiling application is having issues or as you mentioned before its the issue with the environment with which ODBC driver was compiled?

Am downloading the driver from here:  9.2.1 ODBC Driver

http://yum.postgresql.org/9.3/redhat/rhel-5.0-x86_64/

 

Regards...