mirror of
https://github.com/mdbtools/mdbtools.git
synced 2026-03-03 17:08:31 +08:00
Merge pull request #333 from mdbtools/odbc-sans-iconv
Remove iconv from ODBC Unicode driver
This commit is contained in:
@@ -149,6 +149,9 @@ mutually exclusive.
|
||||
causes the iODBC driver to be built.
|
||||
```
|
||||
|
||||
By default, the ODBC driver will be installed as /usr/local/lib/odbc/libmdbodbc.so,
|
||||
with a Unicode-capable driver at /usr/local/lib/odbc/libmdbodbcW.so.
|
||||
|
||||
A list of general options is available in the [INSTALL](./INSTALL) file, and
|
||||
`configure --help` will give you the list of mdbtools specific options.
|
||||
|
||||
|
||||
10
configure.ac
10
configure.ac
@@ -38,7 +38,7 @@ AC_CHECK_DECLS([program_invocation_short_name], [], [], [[
|
||||
|
||||
dnl Checks for library functions.
|
||||
VL_LIB_READLINE
|
||||
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l vasprintf vasnprintf)
|
||||
AC_CHECK_FUNCS(strptime fmemopen gmtime_r reallocf wcstombs_l mbstowcs_l vasprintf vasnprintf)
|
||||
|
||||
AM_GCC_ATTRIBUTE_ALIAS
|
||||
|
||||
@@ -97,15 +97,15 @@ AC_ARG_ENABLE(iconv,
|
||||
HAVE_ICONV_H=0
|
||||
if test "$enable_iconv" = "yes"; then
|
||||
AM_ICONV
|
||||
if test "$am_cv_func_iconv" = "yes"; then
|
||||
# Use the "working iconv" test instead of the "iconv" ($am_cv_func_iconv) test
|
||||
# so that our HAVE_ICONV_H substitution variable has the same value as the HAVE_ICONV
|
||||
# C macro
|
||||
if test "$am_func_iconv" = "yes"; then
|
||||
HAVE_ICONV_H=1
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_ICONV_H)
|
||||
|
||||
dnl Wide-char ODBC driver still requires iconv
|
||||
AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = "yes")
|
||||
|
||||
dnl Fuzz testing
|
||||
AC_ARG_ENABLE([fuzz-testing], AS_HELP_STRING([--enable-fuzz-testing], [enable fuzz testing (requires Clang 6 or later)]), [
|
||||
AC_MSG_CHECKING([whether $CC accepts -fsanitize=fuzzer])
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
|
||||
#if MDBTOOLS_H_HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#elif MDBTOOLS_H_HAVE_XLOCALE_H
|
||||
#endif
|
||||
|
||||
#if MDBTOOLS_H_HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
@@ -65,9 +67,7 @@
|
||||
// M$VC see http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
|
||||
#define MDB_DEPRECATED(type, funcname) type __attribute__((deprecated)) funcname
|
||||
|
||||
#if !MDBTOOLS_H_HAVE_ICONV_H
|
||||
typedef @LOCALE_T@ mdb_locale_t;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MDB_PAGE_DB = 0,
|
||||
|
||||
112
m4/iconv.m4
112
m4/iconv.m4
@@ -1,11 +1,18 @@
|
||||
# iconv.m4 serial 19 (gettext-0.18.2)
|
||||
dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc.
|
||||
# iconv.m4 serial 24
|
||||
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2021 Free Software Foundation,
|
||||
dnl Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
|
||||
dnl Note: AM_ICONV is documented in the GNU gettext manual
|
||||
dnl <https://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html>.
|
||||
dnl Don't make changes that are incompatible with that documentation!
|
||||
|
||||
AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
|
||||
[
|
||||
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||
@@ -85,8 +92,9 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
#endif
|
||||
]],
|
||||
[[int result = 0;
|
||||
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
||||
returns. */
|
||||
/* Test against AIX 5.1...7.2 bug: Failures are not distinguishable from
|
||||
successful returns. This is even documented in
|
||||
<https://www.ibm.com/support/knowledgecenter/ssw_aix_72/i_bostechref/iconv.html> */
|
||||
{
|
||||
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
||||
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
||||
@@ -167,15 +175,27 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
#endif
|
||||
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
||||
provided. */
|
||||
if (/* Try standardized names. */
|
||||
iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
|
||||
/* Try IRIX, OSF/1 names. */
|
||||
&& iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
|
||||
/* Try AIX names. */
|
||||
&& iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
|
||||
/* Try HP-UX names. */
|
||||
&& iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
|
||||
result |= 16;
|
||||
{
|
||||
/* Try standardized names. */
|
||||
iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
|
||||
/* Try IRIX, OSF/1 names. */
|
||||
iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
|
||||
/* Try AIX names. */
|
||||
iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
|
||||
/* Try HP-UX names. */
|
||||
iconv_t cd4 = iconv_open ("utf8", "eucJP");
|
||||
if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
|
||||
&& cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
|
||||
result |= 16;
|
||||
if (cd1 != (iconv_t)(-1))
|
||||
iconv_close (cd1);
|
||||
if (cd2 != (iconv_t)(-1))
|
||||
iconv_close (cd2);
|
||||
if (cd3 != (iconv_t)(-1))
|
||||
iconv_close (cd3);
|
||||
if (cd4 != (iconv_t)(-1))
|
||||
iconv_close (cd4);
|
||||
}
|
||||
return result;
|
||||
]])],
|
||||
[am_cv_func_iconv_works=yes], ,
|
||||
@@ -212,8 +232,7 @@ AC_DEFUN([AM_ICONV_LINK],
|
||||
AC_SUBST([LTLIBICONV])
|
||||
])
|
||||
|
||||
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
|
||||
dnl avoid warnings like
|
||||
dnl Define AM_ICONV using AC_DEFUN_ONCE, in order to avoid warnings like
|
||||
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
|
||||
dnl This is tricky because of the way 'aclocal' is implemented:
|
||||
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
|
||||
@@ -221,51 +240,44 @@ dnl Otherwise aclocal's initial scan pass would miss the macro definition.
|
||||
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
|
||||
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
|
||||
dnl warnings.
|
||||
m4_define([gl_iconv_AC_DEFUN],
|
||||
m4_version_prereq([2.64],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[m4_ifdef([gl_00GNULIB],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[[AC_DEFUN(
|
||||
[$1], [$2])]])]))
|
||||
gl_iconv_AC_DEFUN([AM_ICONV],
|
||||
AC_DEFUN_ONCE([AM_ICONV],
|
||||
[
|
||||
AM_ICONV_LINK
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL([am_cv_proto_iconv], [
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
AC_CACHE_CHECK([whether iconv is compatible with its POSIX signature],
|
||||
[gl_cv_iconv_nonconst],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
]],
|
||||
[[]])],
|
||||
[am_cv_proto_iconv_arg1=""],
|
||||
[am_cv_proto_iconv_arg1="const"])
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([
|
||||
$am_cv_proto_iconv])
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
|
||||
m4_ifdef([gl_ICONV_H_DEFAULTS],
|
||||
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
|
||||
if test -n "$am_cv_proto_iconv_arg1"; then
|
||||
ICONV_CONST="const"
|
||||
fi
|
||||
]],
|
||||
[[]])],
|
||||
[gl_cv_iconv_nonconst=yes],
|
||||
[gl_cv_iconv_nonconst=no])
|
||||
])
|
||||
else
|
||||
dnl When compiling GNU libiconv on a system that does not have iconv yet,
|
||||
dnl pick the POSIX compliant declaration without 'const'.
|
||||
gl_cv_iconv_nonconst=yes
|
||||
fi
|
||||
if test $gl_cv_iconv_nonconst = yes; then
|
||||
iconv_arg1=""
|
||||
else
|
||||
iconv_arg1="const"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$iconv_arg1],
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
|
||||
m4_ifdef([gl_ICONV_H_DEFAULTS],
|
||||
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
|
||||
if test $gl_cv_iconv_nonconst != yes; then
|
||||
ICONV_CONST="const"
|
||||
fi
|
||||
])
|
||||
])
|
||||
|
||||
@@ -7,12 +7,9 @@ AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
|
||||
libmdbodbc_la_SOURCES = odbc.c connectparams.c
|
||||
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
|
||||
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)' $(ODBC_LDFLAGS)
|
||||
if ICONV
|
||||
lib_LTLIBRARIES += libmdbodbcW.la
|
||||
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES)
|
||||
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD) @LIBICONV@
|
||||
libmdbodbcW_la_SOURCES = $(libmdbodbc_la_SOURCES) odbcw.c
|
||||
libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD)
|
||||
libmdbodbcW_la_LDFLAGS = $(libmdbodbc_la_LDFLAGS)
|
||||
libmdbodbcW_la_CFLAGS = $(AM_CFLAGS) -D ENABLE_ODBC_W=1
|
||||
endif
|
||||
LIBS = $(GLIB_LIBS)
|
||||
unittest_LDADD = libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la
|
||||
|
||||
@@ -50,10 +50,7 @@ struct _hdbc {
|
||||
GPtrArray *statements;
|
||||
char lastError[256];
|
||||
char sqlState[6];
|
||||
#ifdef ENABLE_ODBC_W
|
||||
iconv_t iconv_in;
|
||||
iconv_t iconv_out;
|
||||
#endif
|
||||
mdb_locale_t locale;
|
||||
};
|
||||
struct _hstmt {
|
||||
MdbSQL *sql;
|
||||
|
||||
311
src/odbc/odbc.c
311
src/odbc/odbc.c
@@ -16,11 +16,6 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
#define SQL_NOUNICODEMAP
|
||||
#define UNICODE
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include <string.h>
|
||||
@@ -85,64 +80,6 @@ TypeInfo type_info[] = {
|
||||
#define NUM_TYPE_INFO_COLS 19
|
||||
#define MAX_TYPE_INFO 11
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
static void _init_iconv(struct _hdbc* dbc)
|
||||
{
|
||||
TRACE("_init_iconv");
|
||||
int endian = 1;
|
||||
const char* wcharset;
|
||||
if (sizeof(SQLWCHAR) == 2)
|
||||
if (*(char*)&endian == 1)
|
||||
wcharset = "UCS-2LE";
|
||||
else
|
||||
wcharset = "UCS-2BE";
|
||||
else if (sizeof(SQLWCHAR) == 4)
|
||||
if (*(char*)&endian == 1)
|
||||
wcharset = "UCS-4LE";
|
||||
else
|
||||
wcharset = "UCS-4BE";
|
||||
else
|
||||
fprintf(stderr, "Unsupported SQLWCHAR width %zd\n", sizeof(SQLWCHAR));
|
||||
|
||||
dbc->iconv_out = iconv_open(wcharset, "UTF-8");
|
||||
dbc->iconv_in = iconv_open("UTF-8", wcharset);
|
||||
}
|
||||
|
||||
static void _free_iconv(struct _hdbc *dbc)
|
||||
{
|
||||
TRACE("_free_iconv");
|
||||
if(dbc->iconv_out != (iconv_t)-1)iconv_close(dbc->iconv_out);
|
||||
if(dbc->iconv_in != (iconv_t)-1)iconv_close(dbc->iconv_in);
|
||||
}
|
||||
|
||||
static int unicode2ascii(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
|
||||
char *in=_in, *out=_out;
|
||||
size_t lin=*_lin, lout=*_lout;
|
||||
int ret = iconv(dbc->iconv_in, &in, &lin, &out, &lout);
|
||||
*_lin -= lin;
|
||||
*_lout -= lout;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ascii2unicode(struct _hdbc* dbc, char *_in, size_t *_lin, char *_out, size_t *_lout){
|
||||
//fprintf(stderr,"ascii2unicode %08x %08x %08x %08x\n",_in,_lin,_out,_lout);
|
||||
char *in=_in, *out=_out;
|
||||
size_t lin=*_lin, lout=*_lout;
|
||||
//fprintf(stderr,"ascii2unicode %zd %zd\n",lin,lout);
|
||||
int ret = iconv(dbc->iconv_out, &in, &lin, &out, &lout);
|
||||
*_lin -= lin;
|
||||
*_lout -= lout;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sqlwlen(SQLWCHAR *p){
|
||||
int r=0;
|
||||
for(;*p;r++)
|
||||
p++;
|
||||
return r;
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
static void LogHandleError(struct _hdbc* dbc, const char* format, ...)
|
||||
{
|
||||
va_list argp;
|
||||
@@ -213,36 +150,6 @@ SQLRETURN SQL_API SQLDriverConnect(
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLDriverConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLHWND hwnd,
|
||||
SQLWCHAR *szConnStrIn,
|
||||
SQLSMALLINT cbConnStrIn,
|
||||
SQLWCHAR *szConnStrOut,
|
||||
SQLSMALLINT cbConnStrOutMax,
|
||||
SQLSMALLINT *pcbConnStrOut,
|
||||
SQLUSMALLINT fDriverCompletion)
|
||||
{
|
||||
TRACE("SQLDriverConnectW");
|
||||
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
|
||||
{
|
||||
size_t l = cbConnStrIn*sizeof(SQLWCHAR), z = (cbConnStrIn+1)*3;
|
||||
SQLCHAR *tmp = malloc(z);
|
||||
SQLRETURN ret;
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szConnStrIn, &l, (char*)tmp, &z);
|
||||
tmp[z] = 0;
|
||||
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
|
||||
free(tmp);
|
||||
if (szConnStrOut && cbConnStrOutMax>0)
|
||||
szConnStrOut[0] = 0;
|
||||
if (pcbConnStrOut)
|
||||
*pcbConnStrOut = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLBrowseConnect(
|
||||
SQLHDBC hdbc,
|
||||
SQLCHAR *szConnStrIn,
|
||||
@@ -498,8 +405,10 @@ struct _hdbc* dbc;
|
||||
dbc->params = NewConnectParams ();
|
||||
dbc->statements = g_ptr_array_new();
|
||||
dbc->sqlconn = mdb_sql_init();
|
||||
#ifdef ENABLE_ODBC_W
|
||||
_init_iconv(dbc);
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
dbc->locale = _create_locale(LC_CTYPE, ".65001");
|
||||
#else
|
||||
dbc->locale = newlocale(LC_CTYPE_MASK, "C.UTF-8", NULL);
|
||||
#endif
|
||||
*phdbc=dbc;
|
||||
|
||||
@@ -645,36 +554,6 @@ SQLRETURN SQL_API SQLConnect(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLWCHAR *szDSN,
|
||||
SQLSMALLINT cbDSN,
|
||||
SQLWCHAR *szUID,
|
||||
SQLSMALLINT cbUID,
|
||||
SQLWCHAR *szAuthStr,
|
||||
SQLSMALLINT cbAuthStr)
|
||||
{
|
||||
TRACE("SQLConnectW");
|
||||
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);
|
||||
size_t l1=cbDSN*4,z1=cbDSN*2;
|
||||
size_t l2=cbUID*4,z2=cbUID*2;
|
||||
size_t l3=cbAuthStr*4,z3=cbAuthStr*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szDSN, &z1, (char*)tmp1, &l1);
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szUID, &z2, (char*)tmp2, &l2);
|
||||
unicode2ascii((struct _hdbc *)hdbc, (char*)szAuthStr, &z3, (char*)tmp3, &l3);
|
||||
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
|
||||
free(tmp1),free(tmp2),free(tmp3);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLDescribeCol(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
@@ -743,32 +622,6 @@ SQLRETURN SQL_API SQLDescribeCol(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLDescribeColW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLWCHAR *szColName,
|
||||
SQLSMALLINT cbColNameMax,
|
||||
SQLSMALLINT *pcbColName,
|
||||
SQLSMALLINT *pfSqlType,
|
||||
SQLULEN *pcbColDef, /* precision */
|
||||
SQLSMALLINT *pibScale,
|
||||
SQLSMALLINT *pfNullable)
|
||||
{
|
||||
TRACE("SQLDescribeColW");
|
||||
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbColNameMax*4,1);
|
||||
size_t l=cbColNameMax*4;
|
||||
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, cbColNameMax*4, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
||||
ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, &l, (char*)szColName, (size_t*)pcbColName);
|
||||
*pcbColName/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLColAttributes(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
@@ -874,31 +727,6 @@ SQLRETURN SQL_API SQLColAttributes(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLColAttributesW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLUSMALLINT fDescType,
|
||||
SQLPOINTER rgbDesc,
|
||||
SQLSMALLINT cbDescMax,
|
||||
SQLSMALLINT *pcbDesc,
|
||||
SQLLEN *pfDesc)
|
||||
{
|
||||
TRACE("SQLColAttributesW");
|
||||
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);
|
||||
size_t l=cbDescMax*4;
|
||||
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,cbDescMax*4,(SQLSMALLINT*)&l,pfDesc);
|
||||
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbDesc, (size_t*)pcbDesc);
|
||||
*pcbDesc/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLDisconnect(
|
||||
SQLHDBC hdbc)
|
||||
{
|
||||
@@ -958,39 +786,6 @@ SQLRETURN SQL_API SQLError(
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLErrorW(
|
||||
SQLHENV henv,
|
||||
SQLHDBC hdbc,
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlState,
|
||||
SQLINTEGER *pfNativeError,
|
||||
SQLWCHAR *szErrorMsg,
|
||||
SQLSMALLINT cbErrorMsgMax,
|
||||
SQLSMALLINT *pcbErrorMsg)
|
||||
{
|
||||
SQLCHAR szSqlState8[6];
|
||||
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
|
||||
SQLSMALLINT pcbErrorMsg8;
|
||||
SQLRETURN result;
|
||||
|
||||
TRACE("SQLErrorW");
|
||||
|
||||
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
|
||||
if (result == SQL_SUCCESS) {
|
||||
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
||||
size_t lin=6, lout=6*sizeof(SQLWCHAR);
|
||||
ascii2unicode(dbc, (char*)szSqlState8, &lin, (char*)szSqlState, &lout);
|
||||
lin = pcbErrorMsg8;
|
||||
lout = cbErrorMsgMax;
|
||||
ascii2unicode(dbc, (char*)szErrorMsg8, &lin, (char*)szErrorMsg, &lout);
|
||||
if (pcbErrorMsg)
|
||||
*pcbErrorMsg = lout;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLExecute(SQLHSTMT hstmt)
|
||||
{
|
||||
struct _hstmt *stmt = (struct _hstmt *) hstmt;
|
||||
@@ -1021,27 +816,6 @@ SQLRETURN SQL_API SQLExecDirect(
|
||||
return SQLExecute(hstmt);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLExecDirectW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlStr,
|
||||
SQLINTEGER cbSqlStr)
|
||||
{
|
||||
TRACE("SQLExecDirectW");
|
||||
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbSqlStr*4,1);
|
||||
size_t l=cbSqlStr*4,z=cbSqlStr*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii(((struct _hstmt *)hstmt)->hdbc, (char*)szSqlStr, &z, (char*)tmp, &l);
|
||||
ret = SQLExecDirect(hstmt, tmp, l);
|
||||
TRACE("SQLExecDirectW end");
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ODBC_W
|
||||
|
||||
static void
|
||||
unbind_columns(struct _hstmt *stmt)
|
||||
{
|
||||
@@ -1111,8 +885,10 @@ SQLRETURN SQL_API SQLFreeConnect(
|
||||
FreeConnectParams(dbc->params);
|
||||
g_ptr_array_free(dbc->statements, TRUE);
|
||||
mdb_sql_exit(dbc->sqlconn);
|
||||
#ifdef ENABLE_ODBC_W
|
||||
_free_iconv(dbc);
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
if (dbc->locale) _free_locale(dbc->locale);
|
||||
#else
|
||||
if (dbc->locale) freelocale(dbc->locale);
|
||||
#endif
|
||||
g_free(dbc);
|
||||
|
||||
@@ -1382,31 +1158,6 @@ SQLRETURN SQL_API SQLColumns(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLColumnsW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szCatalogName,
|
||||
SQLSMALLINT cbCatalogName,
|
||||
SQLWCHAR *szSchemaName,
|
||||
SQLSMALLINT cbSchemaName,
|
||||
SQLWCHAR *szTableName,
|
||||
SQLSMALLINT cbTableName,
|
||||
SQLWCHAR *szColumnName,
|
||||
SQLSMALLINT cbColumnName)
|
||||
{
|
||||
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
|
||||
{
|
||||
SQLCHAR *tmp=calloc(cbTableName*4,1);
|
||||
size_t l=cbTableName*4,z=cbTableName*2;
|
||||
SQLRETURN ret;
|
||||
unicode2ascii(((struct _hstmt* )hstmt)->hdbc, (char*)szTableName, &z, (char*)tmp, &l);
|
||||
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLGetConnectOption(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fOption,
|
||||
@@ -1719,27 +1470,6 @@ SQLRETURN SQL_API SQLGetData(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLGetDataW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLSMALLINT fCType,
|
||||
SQLPOINTER rgbValue,
|
||||
SQLLEN cbValueMax,
|
||||
SQLLEN *pcbValue)
|
||||
{
|
||||
//todo: treat numbers correctly
|
||||
|
||||
SQLCHAR *tmp=calloc(cbValueMax*4,1);
|
||||
size_t l=cbValueMax*4;
|
||||
SQLRETURN ret = SQLGetData(hstmt, icol, fCType, tmp, cbValueMax*4, (SQLLEN*)&l);
|
||||
ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, &l, (char*)rgbValue, (size_t*)pcbValue);
|
||||
*pcbValue/=sizeof(SQLWCHAR);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
static void _set_func_exists(SQLUSMALLINT *pfExists, SQLUSMALLINT fFunction)
|
||||
{
|
||||
SQLUSMALLINT *mod;
|
||||
@@ -1974,31 +1704,6 @@ SQLRETURN SQL_API SQLGetInfo(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ODBC_W
|
||||
SQLRETURN SQL_API SQLGetInfoW(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fInfoType,
|
||||
SQLPOINTER rgbInfoValue,
|
||||
SQLSMALLINT cbInfoValueMax,
|
||||
SQLSMALLINT *pcbInfoValue)
|
||||
{
|
||||
TRACE("SQLGetInfoW");
|
||||
|
||||
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
|
||||
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
|
||||
|
||||
SQLCHAR *tmp=calloc(cbInfoValueMax*4,1);
|
||||
size_t l=cbInfoValueMax*4;
|
||||
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, cbInfoValueMax*4,(SQLSMALLINT*)&l);
|
||||
size_t pcb=cbInfoValueMax;
|
||||
ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, &l, (char*)rgbInfoValue, &pcb);
|
||||
pcb/=sizeof(SQLWCHAR);
|
||||
if(pcbInfoValue)*pcbInfoValue=pcb;
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif //ENABLE_ODBC_W
|
||||
|
||||
SQLRETURN SQL_API SQLGetStmtOption(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT fOption,
|
||||
|
||||
301
src/odbc/odbcw.c
Normal file
301
src/odbc/odbcw.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/* MDB Tools - A library for reading MS Access database file
|
||||
* Copyright (C) 2000-2021 Brian Bruns and others
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define SQL_NOUNICODEMAP
|
||||
#define UNICODE
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "mdbodbc.h"
|
||||
|
||||
/** \addtogroup odbc
|
||||
* @{
|
||||
*/
|
||||
|
||||
//#define TRACE(x) fprintf(stderr,"Function %s\n", x);
|
||||
#define TRACE(x)
|
||||
|
||||
static size_t unicode2ascii(struct _hdbc* dbc, const SQLWCHAR *_in, size_t _in_count, SQLCHAR *_out, size_t _out_len){
|
||||
wchar_t *w = malloc((_in_count + 1) * sizeof(wchar_t));
|
||||
size_t i;
|
||||
size_t count = 0;
|
||||
for (i=0; i<_in_count; i++) {
|
||||
w[i] = _in[i]; // wchar_t might be larger than SQLWCHAR
|
||||
}
|
||||
w[_in_count] = '\0';
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
count = _wcstombs_l((char *)_out, w, _out_len, dbc->locale);
|
||||
#elif defined(HAVE_WCSTOMBS_L)
|
||||
count = wcstombs_l((char *)_out, w, _out_len, dbc->locale);
|
||||
#else
|
||||
locale_t oldlocale = uselocale(dbc->locale);
|
||||
count = wcstombs((char *)_out, w, _out_len);
|
||||
uselocale(oldlocale);
|
||||
#endif
|
||||
free(w);
|
||||
if (count == (size_t)-1)
|
||||
return 0;
|
||||
|
||||
if (count < _out_len)
|
||||
_out[count] = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static size_t ascii2unicode(struct _hdbc* dbc, const char *_in, size_t _in_len, SQLWCHAR *_out, size_t _out_count){
|
||||
wchar_t *w = malloc(_out_count * sizeof(wchar_t));
|
||||
size_t count = 0, i;
|
||||
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || defined(WINDOWS)
|
||||
count = _mbstowcs_l(w, _in, _out_count, dbc->locale);
|
||||
#elif defined(HAVE_MBSTOWCS_L)
|
||||
count = mbstowcs_l(w, _in, _out_count, dbc->locale);
|
||||
#else
|
||||
locale_t oldlocale = uselocale(dbc->locale);
|
||||
count = mbstowcs(w, _in, _out_count);
|
||||
uselocale(oldlocale);
|
||||
#endif
|
||||
for (i=0; i<count; i++) {
|
||||
_out[i] = (SQLWCHAR)w[i];
|
||||
}
|
||||
free(w);
|
||||
if (count < _out_count)
|
||||
_out[count] = '\0';
|
||||
return count;
|
||||
}
|
||||
|
||||
static int sqlwlen(SQLWCHAR *p){
|
||||
int r=0;
|
||||
for(;*p;r++)
|
||||
p++;
|
||||
return r;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLDriverConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLHWND hwnd,
|
||||
SQLWCHAR *szConnStrIn,
|
||||
SQLSMALLINT cbConnStrIn,
|
||||
SQLWCHAR *szConnStrOut,
|
||||
SQLSMALLINT cbConnStrOutMax,
|
||||
SQLSMALLINT *pcbConnStrOut,
|
||||
SQLUSMALLINT fDriverCompletion)
|
||||
{
|
||||
TRACE("SQLDriverConnectW");
|
||||
if(cbConnStrIn==SQL_NTS)cbConnStrIn=sqlwlen(szConnStrIn);
|
||||
{
|
||||
size_t l = cbConnStrIn*4;
|
||||
SQLCHAR *tmp = malloc(l+1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii((struct _hdbc *)hdbc, szConnStrIn, cbConnStrIn, tmp, l);
|
||||
ret = SQLDriverConnect(hdbc,hwnd,tmp,SQL_NTS,NULL,0,pcbConnStrOut,fDriverCompletion);
|
||||
free(tmp);
|
||||
if (szConnStrOut && cbConnStrOutMax>0)
|
||||
szConnStrOut[0] = 0;
|
||||
if (pcbConnStrOut)
|
||||
*pcbConnStrOut = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLConnectW(
|
||||
SQLHDBC hdbc,
|
||||
SQLWCHAR *szDSN,
|
||||
SQLSMALLINT cbDSN,
|
||||
SQLWCHAR *szUID,
|
||||
SQLSMALLINT cbUID,
|
||||
SQLWCHAR *szAuthStr,
|
||||
SQLSMALLINT cbAuthStr)
|
||||
{
|
||||
TRACE("SQLConnectW");
|
||||
if(cbDSN==SQL_NTS)cbDSN=sqlwlen(szDSN);
|
||||
if(cbUID==SQL_NTS)cbUID=sqlwlen(szUID);
|
||||
if(cbAuthStr==SQL_NTS)cbAuthStr=sqlwlen(szAuthStr);
|
||||
{
|
||||
size_t l1=cbDSN*4;
|
||||
size_t l2=cbUID*4;
|
||||
size_t l3=cbAuthStr*4;
|
||||
SQLCHAR *tmp1=calloc(l1,1),*tmp2=calloc(l2,1),*tmp3=calloc(l3,1);
|
||||
SQLRETURN ret;
|
||||
l1 = unicode2ascii((struct _hdbc *)hdbc, szDSN, cbDSN, tmp1, l1);
|
||||
l2 = unicode2ascii((struct _hdbc *)hdbc, szUID, cbUID, tmp2, l2);
|
||||
l3 = unicode2ascii((struct _hdbc *)hdbc, szAuthStr, cbAuthStr, tmp3, l3);
|
||||
ret = SQLConnect(hdbc, tmp1, l1, tmp2, l2, tmp3, l3);
|
||||
free(tmp1),free(tmp2),free(tmp3);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLDescribeColW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLWCHAR *szColName,
|
||||
SQLSMALLINT cbColNameMax,
|
||||
SQLSMALLINT *pcbColName,
|
||||
SQLSMALLINT *pfSqlType,
|
||||
SQLULEN *pcbColDef, /* precision */
|
||||
SQLSMALLINT *pibScale,
|
||||
SQLSMALLINT *pfNullable)
|
||||
{
|
||||
TRACE("SQLDescribeColW");
|
||||
if(cbColNameMax==SQL_NTS)cbColNameMax=sqlwlen(szColName);
|
||||
{
|
||||
size_t l=cbColNameMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret = SQLDescribeCol(hstmt, icol, tmp, l, (SQLSMALLINT*)&l, pfSqlType, pcbColDef, pibScale, pfNullable);
|
||||
*pcbColName = ascii2unicode(((struct _hstmt*)hstmt)->hdbc, (char*)tmp, l, szColName, cbColNameMax);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLColAttributesW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLUSMALLINT fDescType,
|
||||
SQLPOINTER rgbDesc,
|
||||
SQLSMALLINT cbDescMax,
|
||||
SQLSMALLINT *pcbDesc,
|
||||
SQLLEN *pfDesc)
|
||||
{
|
||||
TRACE("SQLColAttributesW");
|
||||
if (fDescType!=SQL_COLUMN_NAME && fDescType!=SQL_COLUMN_LABEL)
|
||||
return SQLColAttributes(hstmt,icol,fDescType,rgbDesc,cbDescMax,pcbDesc,pfDesc);
|
||||
else{
|
||||
size_t l=cbDescMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret=SQLColAttributes(hstmt,icol,fDescType,tmp,l,(SQLSMALLINT*)&l,pfDesc);
|
||||
*pcbDesc = ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbDesc, cbDescMax);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLErrorW(
|
||||
SQLHENV henv,
|
||||
SQLHDBC hdbc,
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlState,
|
||||
SQLINTEGER *pfNativeError,
|
||||
SQLWCHAR *szErrorMsg,
|
||||
SQLSMALLINT cbErrorMsgMax,
|
||||
SQLSMALLINT *pcbErrorMsg)
|
||||
{
|
||||
SQLCHAR szSqlState8[6];
|
||||
SQLCHAR szErrorMsg8[3*cbErrorMsgMax+1];
|
||||
SQLSMALLINT pcbErrorMsg8;
|
||||
SQLRETURN result;
|
||||
|
||||
TRACE("SQLErrorW");
|
||||
|
||||
result = SQLError(henv, hdbc, hstmt, szSqlState8, pfNativeError, szErrorMsg8, 3*cbErrorMsgMax+1, &pcbErrorMsg8);
|
||||
if (result == SQL_SUCCESS) {
|
||||
struct _hdbc *dbc = hstmt ? ((struct _hstmt *)hstmt)->hdbc : hdbc;
|
||||
size_t pcb;
|
||||
ascii2unicode(dbc, (char*)szSqlState8, sizeof(szSqlState8), szSqlState, sizeof(szSqlState8));
|
||||
pcb = ascii2unicode(dbc, (char*)szErrorMsg8, pcbErrorMsg8, szErrorMsg, cbErrorMsgMax);
|
||||
if (pcbErrorMsg) *pcbErrorMsg = pcb;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLExecDirectW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szSqlStr,
|
||||
SQLINTEGER cbSqlStr)
|
||||
{
|
||||
TRACE("SQLExecDirectW");
|
||||
if(cbSqlStr==SQL_NTS)cbSqlStr=sqlwlen(szSqlStr);
|
||||
{
|
||||
size_t l=cbSqlStr*4;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii(((struct _hstmt *)hstmt)->hdbc, szSqlStr, cbSqlStr, tmp, l);
|
||||
ret = SQLExecDirect(hstmt, tmp, l);
|
||||
TRACE("SQLExecDirectW end");
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLColumnsW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLWCHAR *szCatalogName,
|
||||
SQLSMALLINT cbCatalogName,
|
||||
SQLWCHAR *szSchemaName,
|
||||
SQLSMALLINT cbSchemaName,
|
||||
SQLWCHAR *szTableName,
|
||||
SQLSMALLINT cbTableName,
|
||||
SQLWCHAR *szColumnName,
|
||||
SQLSMALLINT cbColumnName)
|
||||
{
|
||||
if(cbTableName==SQL_NTS)cbTableName=sqlwlen(szTableName);
|
||||
{
|
||||
size_t l=cbTableName*4;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret;
|
||||
l = unicode2ascii(((struct _hstmt* )hstmt)->hdbc, szTableName, cbTableName, tmp, l);
|
||||
ret = SQLColumns(hstmt, NULL, 0, NULL, 0, tmp, l, NULL, 0);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLGetDataW(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
SQLSMALLINT fCType,
|
||||
SQLPOINTER rgbValue,
|
||||
SQLLEN cbValueMax,
|
||||
SQLLEN *pcbValue)
|
||||
{
|
||||
//todo: treat numbers correctly
|
||||
|
||||
size_t l=cbValueMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret = SQLGetData(hstmt, icol, fCType, tmp, l, (SQLLEN*)&l);
|
||||
*pcbValue = ascii2unicode(((struct _hstmt *)hstmt)->hdbc, (char*)tmp, l, (SQLWCHAR*)rgbValue, cbValueMax);
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLGetInfoW(
|
||||
SQLHDBC hdbc,
|
||||
SQLUSMALLINT fInfoType,
|
||||
SQLPOINTER rgbInfoValue,
|
||||
SQLSMALLINT cbInfoValueMax,
|
||||
SQLSMALLINT *pcbInfoValue)
|
||||
{
|
||||
TRACE("SQLGetInfoW");
|
||||
|
||||
if(fInfoType==SQL_MAX_STATEMENT_LEN||fInfoType==SQL_SCHEMA_USAGE||fInfoType==SQL_CATALOG_LOCATION)
|
||||
return SQLGetInfo(hdbc,fInfoType,rgbInfoValue,cbInfoValueMax,pcbInfoValue);
|
||||
|
||||
size_t l=cbInfoValueMax*4+1;
|
||||
SQLCHAR *tmp=calloc(l,1);
|
||||
SQLRETURN ret = SQLGetInfo(hdbc, fInfoType, tmp, l, (SQLSMALLINT*)&l);
|
||||
size_t pcb = ascii2unicode((struct _hdbc *)hdbc, (char*)tmp, l, (SQLWCHAR*)rgbInfoValue, cbInfoValueMax);
|
||||
if(pcbInfoValue)*pcbInfoValue=pcb;
|
||||
free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
Reference in New Issue
Block a user