[patch] odbc

Nirgal <[email protected]> Sat, 6 Aug 2011 00:53:33 +0000
Newsgroups gmane.comp.db.mdb-tools.devel
Message-ID <[email protected]>
Here's patch taken from Debian tracking system, by xsloader <[email protected]>, slightly modified to apply to git master.

http://bugs.debian.org/514986

This fixes SQLGetData() that must returns SQL_NO_DATA at end of data
This also adds support for DBQ in connection strings, and unicode API.

I have not tested it beyond the fact that it compiles.
It looks ok, however.

------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
The must-attend event for mobile developers. Connect with experts. 
Get tools for creating Super Apps. See the latest technologies.
Sessions, hands-on labs, demos & much more. Register early & save!
http://p.sf.net/sfu/rim-blackberry-1

_______________________________________________
mdbtools-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mdbtools-dev
514986.diff (text/x-patch, 16.2 KB)
Author: xsloader <[email protected]>
Bug: http://bugs.debian.org/514986
Last-Update: 2011-08-06
Description: SQLGetData() should return SQL_NO_DATA at end of data
 Also:
 Adds supports for DBQ in connection strings,
 Adds unicode API
Index: mdbtools-0.6pre1/src/odbc/connectparams.c
===================================================================
--- mdbtools-0.6pre1.orig/src/odbc/connectparams.c
+++ mdbtools-0.6pre1/src/odbc/connectparams.c
@@ -319,6 +319,43 @@
    return params->dsnName->str;   
 }
 
+gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString)
+{
+   char *p, *q, *s;
+
+   if (!params)
+      return NULL;
+   /*
+    * Position ourselves to the beginning of "DSN"
+    */
+   p = strstr (connectString, "DBQ");
+   if (!p) return NULL;
+   /*
+    * Position ourselves to the "="
+    */
+   q = strchr (p, '=');
+   if (!q) return NULL;
+   /*
+    * Skip over any leading spaces
+    */
+   q++;
+   while (isspace(*q))
+     q++;
+   /*
+    * Copy the DSN value to a buffer
+    */
+   s = line;
+   while (*q && *q != ';')
+      *s++ = *q++;
+   *s = '\0';
+   /*
+    * Save it as a string in the params object
+    */
+   params->dsnName = g_string_assign (params->dsnName, line);
+
+   return params->dsnName->str;
+}
+
 /*
  * Begin local function definitions
  */
Index: mdbtools-0.6pre1/src/odbc/connectparams.h
===================================================================
--- mdbtools-0.6pre1.orig/src/odbc/connectparams.h
+++ mdbtools-0.6pre1/src/odbc/connectparams.h
@@ -38,5 +38,6 @@
 void     DumpParams       (ConnectParams* params, FILE* output);
 
 gchar*   ExtractDSN (ConnectParams* params, const gchar* connectString);
+gchar*   ExtractDBQ (ConnectParams* params, const gchar* connectString);
 
 #endif
Index: mdbtools-0.6pre1/src/odbc/odbc.c
===================================================================
--- mdbtools-0.6pre1.orig/src/odbc/odbc.c
+++ mdbtools-0.6pre1/src/odbc/odbc.c
@@ -30,6 +30,7 @@
 static char  software_version[]   = "$Id: odbc.c,v 1.31 2007/03/18 14:11:43 brianb Exp $";
 static void *no_unused_var_warn[] = {software_version,
                                      no_unused_var_warn};
+static iconv_t iconv_in,iconv_out;
 
 static SQLSMALLINT _odbc_get_client_type(int srv_type);
 static int _odbc_fix_literals(struct _hstmt *stmt);
@@ -95,6 +96,36 @@
 #define NUM_TYPE_INFO_COLS 19
 #define MAX_TYPE_INFO 11
 
+void __attribute__ ((constructor)) my_init(){
+	iconv_out = iconv_open("UCS-2LE", "UTF-8");
+	iconv_in = iconv_open("UTF-8", "UCS-2LE");
+}
+
+void __attribute__ ((destructor)) my_fini(){
+	if(iconv_out != (iconv_t)-1)iconv_close(iconv_out);
+	if(iconv_in != (iconv_t)-1)iconv_close(iconv_in);
+}
+
+int unicode2ascii(char *_in,unsigned int *_lin,char *_out,unsigned int *_lout){
+	char *in=_in,*out=_out;
+	unsigned lin=*_lin,lout=*_lout;
+	int ret=iconv(iconv_in,&in,&lin,&out,&lout);
+	*_lin-=lin,*_lout-=lout;
+	return ret;
+}
+
+int ascii2unicode(char *_in,unsigned int *_lin,char *_out,unsigned int *_lout){
+	char *in=_in,*out=_out;
+	unsigned lin=*_lin,lout=*_lout;
+	int ret=iconv(iconv_out,&in,&lin,&out,&lout);
+	*_lin-=lin,*_lout-=lout;
+	return ret;
+}
+
+int sqlwlen(SQLWCHAR *p){
+	 int r=0;for(;*p;r++)p++;return r;
+}
+
 /* The SQL engine is presently non-reenterrant and non-thread safe.  
    See _SQLExecute for details.
 */
@@ -133,7 +164,7 @@
    }
 }
 
-SQLRETURN SQL_API SQLDriverConnect(
+SQLRETURN SQL_API SQLDriverConnect_(
     SQLHDBC            hdbc,
     SQLHWND            hwnd,
     SQLCHAR FAR       *szConnStrIn,
@@ -143,39 +174,71 @@
     SQLSMALLINT FAR   *pcbConnStrOut,
     SQLUSMALLINT       fDriverCompletion)
 {
-   SQLCHAR FAR* dsn = NULL;
-   SQLCHAR FAR* database = NULL;
-   ConnectParams* params;
-   SQLRETURN ret;
+	SQLCHAR FAR* dsn = NULL;
+	SQLCHAR FAR* database = NULL;
+	ConnectParams* params;
+	SQLRETURN ret;
 
 	TRACE("SQLDriverConnect");
+	strcpy (lastError, "");
 
-   strcpy (lastError, "");
+	params = ((ODBCConnection*) hdbc)->params;
 
-   params = ((ODBCConnection*) hdbc)->params;
+	if (dsn = ExtractDSN (params, szConnStrIn)){
+		if (!LookupDSN (params, dsn)){
+			LogError ("Could not find DSN in odbc.ini");
+			return SQL_ERROR;
+		}
+		SetConnectString (params, szConnStrIn);
+		if (!(database = GetConnectParam (params, "Database"))){
+			LogError ("Could not find Database parameter");
+			return SQL_ERROR;
+		}
+		ret = do_connect (hdbc, database);
+		return ret;
+	}
+	if (database = ExtractDBQ (params, szConnStrIn)){
+		ret = do_connect (hdbc, database);
+		return ret;
+	}
+	LogError ("Could not find DSN nor DBQ in connect string");
+	return SQL_ERROR;
+}
 
-   if (!(dsn = ExtractDSN (params, szConnStrIn)))
-   {
-      LogError ("Could not find DSN in connect string");
-      return SQL_ERROR;
-   }
-   else if (!LookupDSN (params, dsn))
-   {
-      LogError ("Could not find DSN in odbc.ini");
-      return SQL_ERROR;
-   }
-   else 
-   {
-      SetConnectString (params, szConnStrIn);
+SQLRETURN SQL_API SQLDriverConnect(
+    SQLHDBC            hdbc,
+    SQLHWND            hwnd,
+    SQLCHAR FAR       *szConnStrIn,
+    SQLSMALLINT        cbConnStrIn,
+    SQLCHAR FAR       *szConnStrOut,
+    SQLSMALLINT        cbConnStrOutMax,
+    SQLSMALLINT FAR   *pcbConnStrOut,
+    SQLUSMALLINT       fDriverCompletion)
+{
+	return SQLDriverConnect_(hdbc,hwnd,szConnStrIn,cbConnStrIn,szConnStrOut,cbConnStrOutMax,pcbConnStrOut,fDriverCompletion);
+}
 
-      if (!(database = GetConnectParam (params, "Database")))
-      {
-	 LogError ("Could not find Database parameter");
-	 return SQL_ERROR;
-      }
-   }
-   ret = do_connect (hdbc, database);
-   return ret;
+SQLRETURN SQL_API SQLDriverConnectW(
+    SQLHDBC            hdbc,
+    SQLHWND            hwnd,
+    SQLWCHAR FAR       *szConnStrIn,
+    SQLSMALLINT        cbConnStrIn,
+    SQLWCHAR FAR       *szConnStrOut,
+    SQLSMALLINT        cbConnStrOutMax,
+    SQLSMALLINT FAR   *pcbConnStrOut,
+    SQLUSMALLINT       fDriverCompletion)
+{
+	if(cbConnStrIn==SQL_NTS)
+		cbConnStrIn=sqlwlen(szConnStrIn);
+	{
+		SQLCHAR *tmp=calloc(cbConnStrIn*4,1);
+		int l=cbConnStrIn*4,z=cbConnStrIn*2;
+		SQLRETURN ret;
+		unicode2ascii(szConnStrIn, &z, tmp, &l);
+		ret=SQLDriverConnect_(hdbc,hwnd,tmp,l,NULL,0,pcbConnStrOut,fDriverCompletion);
+		free(tmp);
+		return ret;
+	}
 }
 
 SQLRETURN SQL_API SQLBrowseConnect(
@@ -551,7 +614,7 @@
 	return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLConnect(
+SQLRETURN SQL_API SQLConnect_(
     SQLHDBC            hdbc,
     SQLCHAR FAR       *szDSN,
     SQLSMALLINT        cbDSN,
@@ -586,7 +649,46 @@
       return ret;
 }
 
-SQLRETURN SQL_API SQLDescribeCol(
+SQLRETURN SQL_API SQLConnect(
+    SQLHDBC            hdbc,
+    SQLCHAR FAR       *szDSN,
+    SQLSMALLINT        cbDSN,
+    SQLCHAR FAR       *szUID,
+    SQLSMALLINT        cbUID,
+    SQLCHAR FAR       *szAuthStr,
+    SQLSMALLINT        cbAuthStr)
+{
+	return SQLConnect_(hdbc,szDSN,cbDSN,szUID,cbUID,szAuthStr,cbAuthStr);
+}
+
+SQLRETURN SQL_API SQLConnectW(
+    SQLHDBC            hdbc,
+    SQLWCHAR FAR       *szDSN,
+    SQLSMALLINT        cbDSN,
+    SQLWCHAR FAR       *szUID,
+    SQLSMALLINT        cbUID,
+    SQLWCHAR FAR       *szAuthStr,
+    SQLSMALLINT        cbAuthStr)
+{
+	if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
+	if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
+	if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
+	{
+		SQLCHAR *tmp1=calloc(cbDSN*4,1),*tmp2=calloc(cbUID*4,1),*tmp3=calloc(cbAuthStr*4,1);
+		int l1=cbDSN*4,z1=cbDSN*2;
+		int l2=cbUID*4,z2=cbUID*2;
+		int l3=cbAuthStr*4,z3=cbAuthStr*2;
+		SQLRETURN ret;
+		unicode2ascii(szDSN, &z1, tmp1, &l1);
+		unicode2ascii(szUID, &z2, tmp2, &l2);
+		unicode2ascii(szAuthStr, &z3, tmp3, &l3);
+		ret=SQLConnect_(hdbc,tmp1,l1,tmp2,l2,tmp3,l3);
+		free(tmp1),free(tmp2),free(tmp3);
+		return ret;
+	}
+}
+
+SQLRETURN SQL_API SQLDescribeCol_(
     SQLHSTMT           hstmt,
     SQLUSMALLINT       icol,
     SQLCHAR FAR       *szColName,
@@ -623,9 +725,10 @@
 		namelen = MIN(cbColNameMax,strlen(sqlcol->name));
 		strncpy(szColName, sqlcol->name, namelen);
 		szColName[namelen]='\0';
+              *pcbColName=namelen;
 	}
-	if (pfSqlType) {
-		*pfSqlType = _odbc_get_client_type(col->col_type);
+	if (pfSqlType) { //Currently libmdbodbc.so returns values as string in SQLGetData() even though it is a number.
+		*pfSqlType = SQL_VARCHAR;//_odbc_get_client_type(col->col_type);
 	}
 	if (pcbColDef) {
 		*pcbColDef = col->col_size;
@@ -641,7 +744,45 @@
 	return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLColAttributes(
+SQLRETURN SQL_API SQLDescribeCol(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLCHAR FAR       *szColName,
+    SQLSMALLINT        cbColNameMax,
+    SQLSMALLINT FAR   *pcbColName,
+    SQLSMALLINT FAR   *pfSqlType,
+    SQLUINTEGER FAR   *pcbColDef, /* precision */
+    SQLSMALLINT FAR   *pibScale,
+    SQLSMALLINT FAR   *pfNullable)
+{
+	return SQLDescribeCol_(hstmt,icol,szColName,cbColNameMax,pcbColName,pfSqlType,pcbColDef,pibScale,pfNullable);
+}
+
+SQLRETURN SQL_API SQLDescribeColW(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLWCHAR FAR       *szColName,
+    SQLSMALLINT        cbColNameMax,
+    SQLSMALLINT FAR   *pcbColName,
+    SQLSMALLINT FAR   *pfSqlType,
+    SQLUINTEGER FAR   *pcbColDef, /* precision */
+    SQLSMALLINT FAR   *pibScale,
+    SQLSMALLINT FAR   *pfNullable)
+{
+	if(cbColNameMax==SQL_NTS)
+		cbColNameMax=sqlwlen(szColName);
+	{
+		SQLCHAR *tmp=calloc(cbColNameMax*4,1);
+		int l=cbColNameMax*4;
+		SQLRETURN ret=SQLDescribeCol_(hstmt,icol,tmp,cbColNameMax*4,&l,pfSqlType,pcbColDef,pibScale,pfNullable);
+		ascii2unicode(tmp, &l, szColName, pcbColName);
+		*pcbColName/=2;
+		free(tmp);
+		return ret;
+	}
+}
+
+SQLRETURN SQL_API SQLColAttributes_(
     SQLHSTMT           hstmt,
     SQLUSMALLINT       icol,
     SQLUSMALLINT       fDescType,
@@ -707,6 +848,39 @@
 	return SQL_SUCCESS;
 }
 
+SQLRETURN SQL_API SQLColAttributes(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLUSMALLINT       fDescType,
+    SQLPOINTER         rgbDesc,
+    SQLSMALLINT        cbDescMax,
+    SQLSMALLINT FAR   *pcbDesc,
+    SQLINTEGER FAR    *pfDesc)
+{
+	return SQLColAttributes_(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
+}
+
+SQLRETURN SQL_API SQLColAttributesW(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLUSMALLINT       fDescType,
+    SQLPOINTER         rgbDesc,
+    SQLSMALLINT        cbDescMax,
+    SQLSMALLINT FAR   *pcbDesc,
+    SQLINTEGER FAR    *pfDesc)
+{
+	if(fDescType!=SQL_COLUMN_NAME&&fDescType!=SQL_COLUMN_LABEL)
+		return SQLColAttributes_(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
+	else{
+		SQLCHAR *tmp=calloc(cbDescMax*4,1);
+		int l=cbDescMax*4;
+		SQLRETURN ret=SQLColAttributes_(hstmt,icol,fDescType,tmp,cbDescMax*4,l,pfDesc);
+		ascii2unicode(tmp, &l, rgbDesc, pcbDesc);
+		*pcbDesc/=2;
+		free(tmp);
+		return ret;
+	}
+}
 
 SQLRETURN SQL_API SQLDisconnect(
     SQLHDBC            hdbc)
@@ -780,7 +954,7 @@
    }
 }
 
-SQLRETURN SQL_API SQLExecDirect(
+SQLRETURN SQL_API SQLExecDirect_(
     SQLHSTMT           hstmt,
     SQLCHAR FAR       *szSqlStr,
     SQLINTEGER         cbSqlStr)
@@ -793,6 +967,32 @@
 	return _SQLExecute(hstmt);
 }
 
+SQLRETURN SQL_API SQLExecDirect(
+    SQLHSTMT           hstmt,
+    SQLCHAR FAR       *szSqlStr,
+    SQLINTEGER         cbSqlStr)
+{
+	return SQLExecDirect_(hstmt,szSqlStr,cbSqlStr);
+}
+
+SQLRETURN SQL_API SQLExecDirectW(
+    SQLHSTMT           hstmt,
+    SQLWCHAR FAR       *szSqlStr,
+    SQLINTEGER         cbSqlStr)
+{
+	if(cbSqlStr==SQL_NTS)
+		cbSqlStr=sqlwlen(szSqlStr);
+	{
+		SQLCHAR *tmp=calloc(cbSqlStr*4,1);
+		int l=cbSqlStr*4,z=cbSqlStr*2;
+		SQLRETURN ret;
+		unicode2ascii(szSqlStr, &z, tmp, &l);
+		ret=SQLExecDirect_(hstmt,tmp,l);
+		free(tmp);
+		return ret;
+	}
+}
+
 SQLRETURN SQL_API SQLExecute(
     SQLHSTMT           hstmt)
 {
@@ -1018,7 +1218,7 @@
 	return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLColumns(
+SQLRETURN SQL_API SQLColumns_(
     SQLHSTMT           hstmt,
     SQLCHAR FAR       *szCatalogName,
     SQLSMALLINT        cbCatalogName,
@@ -1118,6 +1318,43 @@
 	return SQL_SUCCESS;
 }
 
+SQLRETURN SQL_API SQLColumns(
+    SQLHSTMT           hstmt,
+    SQLCHAR FAR       *szCatalogName,
+    SQLSMALLINT        cbCatalogName,
+    SQLCHAR FAR       *szSchemaName,
+    SQLSMALLINT        cbSchemaName,
+    SQLCHAR FAR       *szTableName,
+    SQLSMALLINT        cbTableName,
+    SQLCHAR FAR       *szColumnName,
+    SQLSMALLINT        cbColumnName)
+{
+	return SQLColumns_(hstmt,szCatalogName,cbCatalogName,szSchemaName,cbSchemaName,szTableName,cbTableName,szColumnName,cbColumnName);
+}
+
+SQLRETURN SQL_API SQLColumnsW(
+    SQLHSTMT           hstmt,
+    SQLWCHAR FAR       *szCatalogName,
+    SQLSMALLINT        cbCatalogName,
+    SQLWCHAR FAR       *szSchemaName,
+    SQLSMALLINT        cbSchemaName,
+    SQLWCHAR FAR       *szTableName,
+    SQLSMALLINT        cbTableName,
+    SQLWCHAR FAR       *szColumnName,
+    SQLSMALLINT        cbColumnName)
+{
+	if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
+	{
+		SQLCHAR *tmp=calloc(cbTableName*4,1);
+		int l=cbTableName*4,z=cbTableName*2;
+		SQLRETURN ret;
+		unicode2ascii(szTableName, &z, tmp, &l);
+		ret=SQLColumns_(hstmt,NULL,0,NULL,0,tmp,l,NULL,0);
+		free(tmp);
+		return ret;
+	}
+}
+
 SQLRETURN SQL_API SQLGetConnectOption(
     SQLHDBC            hdbc,
     SQLUSMALLINT       fOption,
@@ -1127,13 +1364,13 @@
 	return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLGetData(
+SQLRETURN SQL_API SQLGetData_(
     SQLHSTMT           hstmt,
     SQLUSMALLINT       icol,
     SQLSMALLINT        fCType,
     SQLPOINTER         rgbValue,
-    SQLLEN             cbValueMax,
-    SQLLEN FAR        *pcbValue)
+    SQLINTEGER         cbValueMax,
+    SQLINTEGER FAR    *pcbValue)
 {
 	struct _hstmt *stmt;
 	struct _hdbc *dbc;
@@ -1165,18 +1402,35 @@
 			break;
 		}
 	}
-	
+
+	if(icol!=stmt->icol){stmt->icol=icol;stmt->pos=0;}
 	if (col->col_type == MDB_BOOL) {
+	    if(cbValueMax==0){if(pcbValue)*pcbValue=1;return SQL_SUCCESS_WITH_INFO;}
+		if(stmt->pos>=1)return SQL_NO_DATA;
+		if(!rgbValue){
+		  strcpy(sqlState,"HY009");
+		  return SQL_ERROR;
+		}
 		strcpy(rgbValue, (col->cur_value_len)?"0":"1");
 		if (pcbValue)
 			*pcbValue = 1;
+		stmt->pos=1;
 	} else if (col->cur_value_len) {
 		char *str = mdb_col_to_string(mdb,mdb->pg_buf,
 			col->cur_value_start,col->col_type,col->cur_value_len);
-		strcpy(rgbValue, str);
+		if(cbValueMax==0){if(pcbValue)*pcbValue=strlen(str);g_free(str);return SQL_SUCCESS_WITH_INFO;}
+		if(stmt->pos>=strlen(str))return SQL_NO_DATA;
+		if(!rgbValue){
+		  strcpy(sqlState,"HY009");
+		  return SQL_ERROR;
+		}
+		i=cbValueMax<=strlen(str+stmt->pos)?cbValueMax-1:strlen(str+stmt->pos);
+		memcpy(rgbValue,str+stmt->pos,i);
+		*((char*)(rgbValue)+i)=0;
+		stmt->pos+=i;
 		g_free(str);
 		if (pcbValue)
-			*pcbValue = col->cur_value_len;
+			*pcbValue = i;
 	} else {
 		/* When NULL data is retrieved, non-null pcbValue is required */
 		if (pcbValue) {
@@ -1189,6 +1443,34 @@
 	return SQL_SUCCESS;
 }
 
+SQLRETURN SQL_API SQLGetData(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLSMALLINT        fCType,
+    SQLPOINTER         rgbValue,
+    SQLINTEGER         cbValueMax,
+    SQLINTEGER FAR    *pcbValue)
+{
+	return SQLGetData_(hstmt,icol,fCType,rgbValue,cbValueMax,pcbValue);
+}
+
+SQLRETURN SQL_API SQLGetDataW(
+    SQLHSTMT           hstmt,
+    SQLUSMALLINT       icol,
+    SQLSMALLINT        fCType,
+    SQLPOINTER         rgbValue,
+    SQLINTEGER         cbValueMax,
+    SQLINTEGER FAR    *pcbValue)
+{
+	SQLCHAR *tmp=calloc(cbValueMax*4,1);
+	int l=cbValueMax*4;
+	SQLRETURN ret=SQLGetData_(hstmt,icol,fCType,tmp,cbValueMax*4,l);
+	ascii2unicode(tmp, &l, rgbValue, pcbValue);
+	*pcbValue/=2;
+	free(tmp);
+	return ret;
+}
+
 static void _set_func_exists(SQLUSMALLINT FAR *pfExists, SQLUSMALLINT fFunction)
 {
 SQLUSMALLINT FAR *mod;
@@ -1519,7 +1801,7 @@
 	return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLTables(
+SQLRETURN SQL_API SQLTables( //sz* not used, so Unicode API not required.
     SQLHSTMT           hstmt,
     SQLCHAR FAR       *szCatalogName,
     SQLSMALLINT        cbCatalogName,
Index: mdbtools-0.6pre1/include/mdbodbc.h
===================================================================
--- mdbtools-0.6pre1.orig/include/mdbodbc.h
+++ mdbtools-0.6pre1/include/mdbodbc.h
@@ -53,6 +53,8 @@
 	char query[4096];
 	struct _sql_bind_info *bind_head;
 	int rows_affected;
+	int icol;
+	int pos;
 };
 
 struct _sql_bind_info {