Bug #33643 SQLGetInfo - does not fully report cursor attributes
Submitted: 3 Jan 2008 0:38 Modified: 9 Apr 2008 18:25
Reporter: Cristian Tarsoaga Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / ODBC Severity:S2 (Serious)
Version:3.51.22r857, 5.1.8 OS:Any (sourcecode: driver/info.c)
Assigned to: Assigned Account CPU Architecture:Any
Tags: SQLGetInfo cursor attributes
Triage: D4 (Minor)

[3 Jan 2008 0:38] Cristian Tarsoaga
Description:
SQLGetInfo does report an incomplete set of cursor properties.
I tested the static cursor, but while browsing the sourcecode I saw that this is a general problem. SQLGetInfo does not return any of the concurrency flags (read-only / updatable) for the cursors attributes.

//this is just an example, using a static cursor for the test:
SQLGetInfo(hdbc, SQL_STATIC_CURSOR_ATTRIBUTES2, &res, sizeof(res), &t)

does never return the following flags in "res":
SQL_CA2_READ_ONLY_CONCURRENCY
SQL_CA2_LOCK_CONCURRENCY
SQL_CA2_OPT_ROWVER_CONCURRENCY
SQL_CA2_OPT_VALUES_CONCURRENCY

Even if I try to use a dynamic cursor, the concurrency flags are still not set (even though they are "supported" !?). It's perfectly possible that other flags are missed too. I can only use a forward only cursor with read-only concurrency.

I am attaching a c++ sourcecode to test the  behavior and a SAMPLE patch for the driver/info.c sourcefile to fix the read-only concurrency flag for a static cursor (note that other flags might also be missing!!)

Thanks, Chris

How to repeat:
//
//myodbctest.cpp
//
//compile with: g++ -lmyodbc3 myodbctest.cpp -o myodbctest
//
//tested on myodbc version 3.51.12

#include "sql.h"
#include "sqlext.h"
#include "sqltypes.h"
#include "sqlucode.h"

#include <iostream>

#define CHECK_RES(res)                                                 \
  if (res != SQL_SUCCESS)                                              \
    {                                                                  \
      std::cout << "Error at " << __LINE__ << __FILE__ << std::endl;   \
      exit(1);                                                         \
    }

/*
 * simple tests for a db connection using myodbc driver (odbc over mysql)
 *
 * we're interested in a scrollable cursor (no matter what concurrency it supports)....but does it support some??
 */
int main()
{
  SQLHENV    henv;
  SQLHDBC    hdbc; 

  
  //open the test connection
  SQLRETURN r = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
  CHECK_RES(r);
    
  r = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0);
  CHECK_RES(r);

  r = SQLAllocHandle(SQL_HANDLE_DBC,henv, &hdbc);   
  CHECK_RES(r);

  SQLCHAR * dsn = (SQLCHAR*) "someDSN";
  SQLCHAR * uid = (SQLCHAR*) "someUSER";
  SQLCHAR * pwd = (SQLCHAR*) "somePASSWORD";
  r = SQLConnect(hdbc, dsn, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  CHECK_RES(r);

  //check some connection attributes
  SQLCHAR dbms[30];  
  r = SQLGetInfo(hdbc, SQL_DBMS_NAME, &dbms, 40, NULL);
  std::cout << "DBMS: " << dbms << std::endl;

  //check if static cursor supports read-only concurrency
  SQLRETURN res1 = 0;
  SQLSMALLINT t;
  r = SQLGetInfo(hdbc, SQL_STATIC_CURSOR_ATTRIBUTES2, &res1, sizeof(res1), &t); //static cursor options
  CHECK_RES(r);
  std::cout << "Supports static2 - read only: " << (res1 & SQL_CA2_READ_ONLY_CONCURRENCY) << std::endl;

  //check if static cursor supports updatable concurrency
  SQLRETURN res2 = 0;
  bool updatable = false;
  r = SQLGetInfo(hdbc, SQL_STATIC_CURSOR_ATTRIBUTES2, &res2, sizeof(res2), &t); //static cursor options
  CHECK_RES(r);
  std::cout << "Supports static2 - lock: " << (res2 & SQL_CA2_LOCK_CONCURRENCY) << std::endl;
  updatable |= (res2 & SQL_CA2_LOCK_CONCURRENCY);
  r = SQLGetInfo(hdbc, SQL_STATIC_CURSOR_ATTRIBUTES2, &res2, sizeof(res2), &t); //static cursor options
  CHECK_RES(r);
  std::cout << "Supports static2 - rowver: " << (res2 & SQL_CA2_OPT_ROWVER_CONCURRENCY) << std::endl;
  updatable |= (res2 & SQL_CA2_OPT_ROWVER_CONCURRENCY);
  r = SQLGetInfo(hdbc, SQL_STATIC_CURSOR_ATTRIBUTES2, &res2, sizeof(res2), &t); //static cursor options
  CHECK_RES(r);
  std::cout << "Supports static2 - values: " << (res2 & SQL_CA2_OPT_VALUES_CONCURRENCY) << std::endl;
  updatable |= (res2 & SQL_CA2_OPT_VALUES_CONCURRENCY);

  std::cout << "Supports static2 - updatable: " << updatable << std::endl;

  //close connection
  r = SQLDisconnect(hdbc);
  CHECK_RES(r);
        
  r = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
  CHECK_RES(r);
      
  r = SQLFreeHandle(SQL_HANDLE_ENV, henv);
  CHECK_RES(r);

  return 0;
}

Suggested fix:
--- info.c	2005-10-09 22:33:40.000000000 +0300
+++ info.c	2008-01-02 22:21:47.000000000 +0200
@@ -447,6 +447,7 @@
                                               SQL_CA2_MAX_ROWS_INSERT |
                                               SQL_CA2_MAX_ROWS_DELETE |
                                               SQL_CA2_MAX_ROWS_UPDATE |
+                                              SQL_CA2_READ_ONLY_CONCURRENCY | /* fill concurrency info too !? */
                                               SQL_CA2_CRC_EXACT);
             *pcbInfoValue= sizeof(SQLUINTEGER);
             break;
[3 Jan 2008 0:58] Cristian Tarsoaga
also applies in myodbc driver version 3.51.22r857
[13 Dec 2010 8:06] Bogdan Degtyariov
Both 3.51 and 5.1 are affected