Bug#514986: libmdbodbc doesn't work on Mono+Unixodbc [patch]
Package: libmdbodbc
Version: 0.5.99.0.6pre1.0.20051109-4
Severity: important
I'm creating an application which reads Microsoft Database(mdb) using
Mono+Unixodbc.
Yes, odbc requires a driver, so I decided to use libmdbodbc.
Firstly, I compiled the C# source in Windows-csc and ran very well.
So I complied it in Mono-gmcs and invoke it. But the execution failed.
(SQLGetData() has to return SQL_NO_DATA if the stream had reached end
of data, but libmdbodbc's didn't)
Therefore I have created patch as follows:
1. Fixed how to return data in SQLGetData(). Works fine in Mono 1.9.1.
2. Now understands DBQ statement in conection string.
3. Implemented Unicode version functions. Works fine in Mono 2.0.
Anyway, thank you for adding Japanese support to libmdb. Without it I
could not make the converter to work on Debian.
xsloader
---
diff -r mdbtools-0.5.99.0.6pre1.0.20051109.orig/src/odbc/connectparams.c
mdbtools-0.5.99.0.6pre1.0.20051109-5/src/odbc/connectparams.c
321a322,358
> gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString)
> {
> char *p, *q, *s;
>
> if (!params)
> return NULL;
> /*
> * Position ourselves to the beginning of "DBQ"
> */
> 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 DBQ 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;
> }
>
diff -r mdbtools-0.5.99.0.6pre1.0.20051109.orig/src/odbc/connectparams.h
mdbtools-0.5.99.0.6pre1.0.20051109-5/src/odbc/connectparams.h
40a41
> gchar* ExtractDBQ (ConnectParams* params, const gchar* connectString);
diff -r mdbtools-0.5.99.0.6pre1.0.20051109.orig/src/odbc/odbc.c
mdbtools-0.5.99.0.6pre1.0.20051109-5/src/odbc/odbc.c
32a33
> static iconv_t iconv_in,iconv_out;
97a99,128
> 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;
> }
>
136c167
< SQLRETURN SQL_API SQLDriverConnect(
---
> SQLRETURN SQL_API SQLDriverConnect_(
152d182
<
157,168c187,191
< 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
< {
---
> if (dsn = ExtractDSN (params, szConnStrIn)){
> if (!LookupDSN (params, dsn)){
> LogError ("Could not find DSN in odbc.ini");
> return SQL_ERROR;
> }
170,172c193
<
< if (!(database = GetConnectParam (params, "Database")))
< {
---
> if (!(database = GetConnectParam (params, "Database"))){
175a197,198
> ret = do_connect (hdbc, database);
> return ret;
177,178c200,238
< 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;
> }
>
> 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);}
>
> 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;
> }
554c614
< SQLRETURN SQL_API SQLConnect(
---
> SQLRETURN SQL_API SQLConnect_(
589c649,686
< 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)
> {__asm__("jmp SQLConnect_");}
>
> 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_(
625a723
> *pcbColName=namelen;
627,628c725,726
< 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);
644c742,777
< 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_(
695a829
> *pcbDesc=namelen;
709a844,875
> 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;
> }
> }
>
775c941
< SQLRETURN SQL_API SQLExecDirect(
---
> SQLRETURN SQL_API SQLExecDirect_(
787a954,976
> 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;
> }
> }
>
835a1025
> stmt->icol=-1;
1013c1203
< SQLRETURN SQL_API SQLColumns(
---
> SQLRETURN SQL_API SQLColumns_(
1112a1303,1337
> 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;
> }
> }
>
1122c1347
< SQLRETURN SQL_API SQLGetData(
---
> SQLRETURN SQL_API SQLGetData_(
1160c1385,1386
<
---
>
> if(icol!=stmt->icol){stmt->icol=icol;stmt->pos=0;}
1161a1388,1393
> 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;
> }
1164a1397
> stmt->pos=1;
1168c1401,1409
< 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:strlen(str+stmt->pos);
> memcpy(rgbValue,str+stmt->pos,i);
> stmt->pos+=i;
1171c1412
< *pcbValue = col->cur_value_len;
---
> *pcbValue = i;
1183a1425,1452
> 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;
> }
> }
>
1487c1756
< SQLRETURN SQL_API SQLTables(
---
> SQLRETURN SQL_API SQLTables( //sz* not used, so Unicode API not required.
1558d1826
<
Reply to: