[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: