--- a/src/sql/drivers/odbc/qsql_odbc.cpp Mon Mar 15 12:43:09 2010 +0200
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp Thu Apr 08 14:19:33 2010 +0300
@@ -66,7 +66,7 @@
//crude hack to get non-unicode capable driver managers to work
# undef UNICODE
# define SQLTCHAR SQLCHAR
-# define SQL_C_WCHAR SQL_C_CHAR
+# define SQL_C_TCHAR SQL_C_CHAR
#endif
// newer platform SDKs use SQLLEN instead of SQLINTEGER
@@ -78,31 +78,74 @@
# define QSQLULEN SQLULEN
#endif
-
static const int COLNAMESIZE = 256;
//Map Qt parameter types to ODBC types
static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
+inline static QString fromSQLTCHAR(const QVarLengthArray<SQLTCHAR>& input, int size=-1)
+{
+ QString result;
+
+ int realsize = qMin(size, input.size());
+ if(realsize > 0 && input[realsize-1] == 0)
+ realsize--;
+ switch(sizeof(SQLTCHAR)) {
+ case 1:
+ result=QString::fromUtf8((const char *)input.constData(), realsize);
+ break;
+ case 2:
+ result=QString::fromUtf16((const ushort *)input.constData(), realsize);
+ break;
+ case 4:
+ result=QString::fromUcs4((const uint *)input.constData(), realsize);
+ break;
+ default:
+ qCritical() << "sizeof(SQLTCHAR) is " << sizeof(SQLTCHAR) << "Don't know how to handle this";
+ }
+ return result;
+}
+
+inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input)
+{
+ QVarLengthArray<SQLTCHAR> result;
+ result.resize(input.size());
+ switch(sizeof(SQLTCHAR)) {
+ case 1:
+ memcpy(result.data(), input.toUtf8().data(), input.size());
+ break;
+ case 2:
+ memcpy(result.data(), input.unicode(), input.size() * 2);
+ break;
+ case 4:
+ memcpy(result.data(), input.toUcs4().data(), input.size() * 4);
+ break;
+ default:
+ qCritical() << "sizeof(SQLTCHAR) is " << sizeof(SQLTCHAR) << "Don't know how to handle this";
+ }
+ result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't.
+ return result;
+}
+
class QODBCDriverPrivate
{
public:
enum DefaultCase{Lower, Mixed, Upper, Sensitive};
QODBCDriverPrivate()
- : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false),
- isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false),
- isQuoteInitialized(false), quote(QLatin1Char('"'))
+ : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), isMySqlServer(false),
+ isMSSqlServer(false), isFreeTDSDriver(false), hasSQLFetchScroll(true),
+ hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"'))
{
- unicode = false;
}
SQLHANDLE hEnv;
SQLHANDLE hDbc;
- uint unicode :1;
- uint useSchema :1;
+ bool unicode;
+ bool useSchema;
int disconnectCount;
bool isMySqlServer;
bool isMSSqlServer;
+ bool isFreeTDSDriver;
bool hasSQLFetchScroll;
bool hasMultiResultSets;
@@ -129,7 +172,10 @@
QODBCPrivate(QODBCDriverPrivate *dpp)
: hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false)
{
- unicode = false;
+ unicode = dpp->unicode;
+ useSchema = dpp->useSchema;
+ disconnectCount = dpp->disconnectCount;
+ hasSQLFetchScroll = dpp->hasSQLFetchScroll;
}
inline void clearValues()
@@ -139,8 +185,8 @@
SQLHANDLE dpDbc() const { return driverPrivate ? driverPrivate->hDbc : 0;}
SQLHANDLE hStmt;
- uint unicode :1;
- uint useSchema :1;
+ bool unicode;
+ bool useSchema;
QSqlRecord rInf;
QVector<QVariant> fieldCache;
@@ -177,19 +223,18 @@
int i = 1;
description_[0] = 0;
- r = SQLGetDiagRec(handleType,
- handle,
- i,
- state_,
- &nativeCode_,
- 0,
- NULL,
- &msgLen);
- if(r == SQL_NO_DATA)
- return QString();
- description_.resize(msgLen+1);
do {
r = SQLGetDiagRec(handleType,
+ handle,
+ i,
+ state_,
+ &nativeCode_,
+ 0,
+ NULL,
+ &msgLen);
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && msgLen > 0)
+ description_.resize(msgLen+1);
+ r = SQLGetDiagRec(handleType,
handle,
i,
state_,
@@ -202,9 +247,9 @@
*nativeCode = nativeCode_;
QString tmpstore;
#ifdef UNICODE
- tmpstore = QString((const QChar*)description_.data(), msgLen);
+ tmpstore = fromSQLTCHAR(description_, msgLen);
#else
- tmpstore = QString::fromLocal8Bit((const char*)description_.data(), msgLen);
+ tmpstore = QString::fromUtf8((const char*)description_.constData(), msgLen);
#endif
if(result != tmpstore) {
if(!result.isEmpty())
@@ -223,13 +268,13 @@
{
return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->dpEnv()) + QLatin1Char(' ')
+ qWarnODBCHandle(SQL_HANDLE_DBC, odbc->dpDbc()) + QLatin1Char(' ')
- + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode));
+ + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode)).simplified();
}
static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0)
{
return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ')
- + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode));
+ + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode)).simplified();
}
static void qSqlWarning(const QString& message, const QODBCPrivate* odbc)
@@ -307,7 +352,9 @@
#endif
case SQL_CHAR:
case SQL_VARCHAR:
+#if (ODBCVER >= 0x0350)
case SQL_GUID:
+#endif
case SQL_LONGVARCHAR:
type = QVariant::String;
break;
@@ -331,45 +378,89 @@
colSize = 65536;
} else {
colSize++; // make sure there is room for more than the 0 termination
- if (unicode) {
- colSize *= 2; // a tiny bit faster, since it saves a SQLGetData() call
- }
}
- QVarLengthArray<char> buf(colSize);
- while (true) {
+ if(unicode) {
r = SQLGetData(hStmt,
column+1,
- unicode ? SQL_C_WCHAR : SQL_C_CHAR,
- (SQLPOINTER)buf.data(),
- colSize,
+ SQL_C_TCHAR,
+ NULL,
+ 0,
&lengthIndicator);
- if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
- if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
+ QVarLengthArray<SQLTCHAR> buf(colSize);
+ memset(buf.data(), 0, colSize*sizeof(SQLTCHAR));
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_TCHAR,
+ (SQLPOINTER)buf.data(),
+ colSize*sizeof(SQLTCHAR),
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR);
+ fieldVal += fromSQLTCHAR(buf, rSize);
+ if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
+ } else {
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
fieldVal.clear();
break;
}
- // if SQL_SUCCESS_WITH_INFO is returned, indicating that
- // more data can be fetched, the length indicator does NOT
- // contain the number of bytes returned - it contains the
- // total number of bytes that CAN be fetched
- // colSize-1: remove 0 termination when there is more data to fetch
- int rSize = (r == SQL_SUCCESS_WITH_INFO) ? (unicode ? colSize-2 : colSize-1) : lengthIndicator;
- if (unicode) {
- fieldVal += QString((const QChar*) buf.constData(), rSize / 2);
+ }
+ } else {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ NULL,
+ 0,
+ &lengthIndicator);
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator + 1;
+ QVarLengthArray<SQLCHAR> buf(colSize);
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ (SQLPOINTER)buf.data(),
+ colSize,
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator;
+ fieldVal += QString::fromUtf8((const char *)buf.constData(), rSize);
+ if (lengthIndicator < (unsigned int)colSize) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
} else {
- fieldVal += QString::fromAscii(buf.constData(), rSize);
- }
- memset(buf.data(), 0, colSize);
- if (lengthIndicator < colSize) {
- // workaround for Drivermanagers that don't return SQL_NO_DATA
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
+ fieldVal.clear();
break;
}
- } else if (r == SQL_NO_DATA) {
- break;
- } else {
- qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
}
}
return fieldVal;
@@ -386,10 +477,11 @@
QSQLLEN lengthIndicator = 0;
SQLRETURN r = SQL_ERROR;
- SQLTCHAR colName[COLNAMESIZE];
+ QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE);
+
r = SQLDescribeCol(hStmt,
column + 1,
- colName,
+ colName.data(),
COLNAMESIZE,
&colNameLen,
&colType,
@@ -522,10 +614,10 @@
SQLSMALLINT colScale;
SQLSMALLINT nullable;
SQLRETURN r = SQL_ERROR;
- SQLTCHAR colName[COLNAMESIZE];
+ QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE);
r = SQLDescribeCol(p->hStmt,
i+1,
- colName,
+ colName.data(),
(SQLSMALLINT)COLNAMESIZE,
&colNameLen,
&colType,
@@ -551,9 +643,9 @@
}
#ifdef UNICODE
- QString qColName((const QChar*)colName, colNameLen);
+ QString qColName(fromSQLTCHAR(colName, colNameLen));
#else
- QString qColName = QString::fromLocal8Bit((const char*)colName);
+ QString qColName = QString::fromUtf8((const char *)colName.constData());
#endif
// nullable can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
int required = -1;
@@ -581,24 +673,33 @@
if (connOpts.contains(QLatin1String("SQL_ATTR_ODBC_VERSION=SQL_OV_ODBC3"), Qt::CaseInsensitive))
return SQL_OV_ODBC3;
#endif
+ if (connOpts.contains(QLatin1String("SQL_ATTR_ODBC_VERSION=SQL_OV_ODBC2"), Qt::CaseInsensitive))
+ return SQL_OV_ODBC2;
+#ifdef _IODBCUNIX_H
+ return SQL_OV_ODBC3;
+#else
return SQL_OV_ODBC2;
+#endif
}
QChar QODBCDriverPrivate::quoteChar()
{
if (!isQuoteInitialized) {
- char driverResponse[4];
+ SQLTCHAR driverResponse[4];
SQLSMALLINT length;
int r = SQLGetInfo(hDbc,
SQL_IDENTIFIER_QUOTE_CHAR,
&driverResponse,
sizeof(driverResponse),
&length);
- if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
+#ifdef UNICODE
+ quote = QChar(driverResponse[0]);
+#else
quote = QLatin1Char(driverResponse[0]);
- } else {
+#endif
+ else
quote = QLatin1Char('"');
- }
isQuoteInitialized = true;
}
return quote;
@@ -642,11 +743,11 @@
val.utf16(); // 0 terminate
r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG,
#ifdef UNICODE
- (SQLWCHAR*) val.unicode(),
+ toSQLTCHAR(val).data(),
#else
- (SQLCHAR*) val.toLatin1().constData(),
+ (SQLCHAR*) val.toUtf8().data(),
#endif
- SQL_NTS);
+ val.length()*sizeof(SQLTCHAR));
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) {
if (val.toUpper() == QLatin1String("SQL_TRUE")) {
v = SQL_TRUE;
@@ -664,11 +765,11 @@
val.utf16(); // 0 terminate
r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE,
#ifdef UNICODE
- (SQLWCHAR*) val.unicode(),
+ toSQLTCHAR(val).data(),
#else
- (SQLCHAR*) val.toLatin1().constData(),
+ (SQLCHAR*) val.toUtf8().data(),
#endif
- SQL_NTS);
+ val.length()*sizeof(SQLTCHAR));
} else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) {
if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) {
v = SQL_OPT_TRACE_OFF;
@@ -814,10 +915,6 @@
: QSqlResult(db)
{
d = new QODBCPrivate(p);
- d->unicode = p->unicode;
- d->useSchema = p->useSchema;
- d->disconnectCount = p->disconnectCount;
- d->hasSQLFetchScroll = p->hasSQLFetchScroll;
}
QODBCResult::~QODBCResult()
@@ -880,12 +977,12 @@
#ifdef UNICODE
r = SQLExecDirect(d->hStmt,
- (SQLWCHAR*) query.unicode(),
+ toSQLTCHAR(query).data(),
(SQLINTEGER) query.length());
#else
- QByteArray query8 = query.toLocal8Bit();
+ QByteArray query8 = query.toUtf8();
r = SQLExecDirect(d->hStmt,
- (SQLCHAR*) query8.constData(),
+ (SQLCHAR*) query8.data(),
(SQLINTEGER) query8.length());
#endif
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) {
@@ -1231,12 +1328,12 @@
#ifdef UNICODE
r = SQLPrepare(d->hStmt,
- (SQLWCHAR*) query.unicode(),
+ toSQLTCHAR(query).data(),
(SQLINTEGER) query.length());
#else
- QByteArray query8 = query.toLocal8Bit();
+ QByteArray query8 = query.toUtf8();
r = SQLPrepare(d->hStmt,
- (SQLCHAR*) query8.constData(),
+ (SQLCHAR*) query8.data(),
(SQLINTEGER) query8.length());
#endif
@@ -1435,43 +1532,44 @@
#ifndef Q_ODBC_VERSION_2
if (d->unicode) {
QString str = val.toString();
- str.utf16();
if (*ind != SQL_NULL_DATA)
- *ind = str.length() * sizeof(QChar);
- int strSize = str.length() * sizeof(QChar);
+ *ind = str.length() * sizeof(SQLTCHAR);
+ int strSize = str.length() * sizeof(SQLTCHAR);
if (bindValueType(i) & QSql::Out) {
- QByteArray ba((char*)str.constData(), str.capacity() * sizeof(QChar));
+ QVarLengthArray<SQLTCHAR> ba(toSQLTCHAR(str));
+ ba.reserve(str.capacity());
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
- SQL_C_WCHAR,
+ SQL_C_TCHAR,
strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
0, // god knows... don't change this!
0,
(void *)ba.constData(),
ba.size(),
ind);
- tmpStorage.append(ba);
+ tmpStorage.append(QByteArray((const char *)ba.constData(), ba.size()*sizeof(SQLTCHAR)));
break;
}
-
+ QByteArray strba((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
- SQL_C_WCHAR,
+ SQL_C_TCHAR,
strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
strSize,
0,
- (void *)str.constData(),
- strSize,
+ (SQLPOINTER)strba.constData(),
+ strba.size(),
ind);
+ tmpStorage.append(strba);
break;
}
else
#endif
{
- QByteArray str = val.toString().toAscii();
+ QByteArray str = val.toString().toUtf8();
if (*ind != SQL_NULL_DATA)
*ind = str.length();
int strSize = str.length();
@@ -1572,15 +1670,18 @@
break;
case QVariant::String:
if (d->unicode) {
- if (bindValueType(i) & QSql::Out)
- values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData());
+ if (bindValueType(i) & QSql::Out) {
+ QByteArray first = tmpStorage.takeFirst();
+ QVarLengthArray<SQLTCHAR> array;
+ array.append((SQLTCHAR *)first.constData(), first.size());
+ values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR*));
+ }
break;
}
// fall through
default: {
- QByteArray ba = tmpStorage.takeFirst();
if (bindValueType(i) & QSql::Out)
- values[i] = QString::fromAscii(ba.constData());
+ values[i] = tmpStorage.takeFirst();
break; }
}
if (indicators[i] == SQL_NULL_DATA)
@@ -1789,19 +1890,21 @@
connQStr += QLatin1String(";PWD=") + password;
SQLSMALLINT cb;
- SQLTCHAR connOut[1024];
+ QVarLengthArray<SQLTCHAR> connOut(1024);
+ memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
r = SQLDriverConnect(d->hDbc,
NULL,
#ifdef UNICODE
- (SQLWCHAR*)connQStr.unicode(),
+ toSQLTCHAR(connQStr).data(),
#else
- (SQLCHAR*)connQStr.toLatin1().constData(),
+ (SQLCHAR*)connQStr.toUtf8().data(),
#endif
(SQLSMALLINT)connQStr.length(),
- connOut,
+ connOut.data(),
1024,
&cb,
- SQL_DRIVER_NOPROMPT);
+ /*SQL_DRIVER_NOPROMPT*/0);
+
if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
setOpenError(true);
@@ -1886,6 +1989,7 @@
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1895,6 +1999,7 @@
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1904,7 +2009,25 @@
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
unicode = true;
+ return;
}
+ SQLHANDLE hStmt;
+ r = SQLAllocHandle(SQL_HANDLE_STMT,
+ hDbc,
+ &hStmt);
+
+ r = SQLExecDirect(hStmt, toSQLTCHAR(QLatin1String("select 'test'")).data(), SQL_NTS);
+ if(r == SQL_SUCCESS) {
+ r = SQLFetch(hStmt);
+ if(r == SQL_SUCCESS) {
+ QVarLengthArray<SQLWCHAR> buffer(10);
+ r = SQLGetData(hStmt, 1, SQL_C_WCHAR, buffer.data(), buffer.size() * sizeof(SQLWCHAR), NULL);
+ if(r == SQL_SUCCESS && fromSQLTCHAR(buffer) == QLatin1String("test")) {
+ unicode = true;
+ }
+ }
+ }
+ r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
bool QODBCDriverPrivate::checkDriver() const
@@ -1977,24 +2100,40 @@
void QODBCDriverPrivate::checkSqlServer()
{
SQLRETURN r;
- char serverString[200];
+ QVarLengthArray<SQLTCHAR> serverString(200);
SQLSMALLINT t;
+ memset(serverString.data(), 0, serverString.size() * sizeof(SQLTCHAR));
r = SQLGetInfo(hDbc,
SQL_DBMS_NAME,
- serverString,
- sizeof(serverString),
+ serverString.data(),
+ serverString.size() * sizeof(SQLTCHAR),
&t);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
QString serverType;
#ifdef UNICODE
- serverType = QString(reinterpret_cast<const QChar*>(serverString), t/sizeof(QChar));
+ serverType = fromSQLTCHAR(serverString, t/sizeof(SQLTCHAR));
#else
- serverType = QString::fromLocal8Bit(serverString, t);
+ serverType = QString::fromUtf8((const char *)serverString.constData(), t);
#endif
isMySqlServer = serverType.contains(QLatin1String("mysql"), Qt::CaseInsensitive);
isMSSqlServer = serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive);
}
+ r = SQLGetInfo(hDbc,
+ SQL_DRIVER_NAME,
+ serverString.data(),
+ serverString.size() * sizeof(SQLTCHAR),
+ &t);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ QString serverType;
+#ifdef UNICODE
+ serverType = fromSQLTCHAR(serverString, t/sizeof(SQLTCHAR));
+#else
+ serverType = QString::fromUtf8((const char *)serverString.constData(), t);
+#endif
+ isFreeTDSDriver = serverType.contains(QLatin1String("tdsodbc"), Qt::CaseInsensitive);
+ unicode = isFreeTDSDriver == false;
+ }
}
void QODBCDriverPrivate::checkHasSQLFetchScroll()
@@ -2009,18 +2148,18 @@
void QODBCDriverPrivate::checkHasMultiResults()
{
- char driverResponse[4];
+ QVarLengthArray<SQLTCHAR> driverResponse(2);
SQLSMALLINT length;
SQLRETURN r = SQLGetInfo(hDbc,
SQL_MULT_RESULT_SETS,
- driverResponse,
- sizeof(driverResponse),
+ driverResponse.data(),
+ driverResponse.size() * sizeof(SQLTCHAR),
&length);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
#ifdef UNICODE
- hasMultiResultSets = QString(reinterpret_cast<const QChar*>(driverResponse), length/sizeof(QChar)).startsWith(QLatin1Char('Y'));
+ hasMultiResultSets = fromSQLTCHAR(driverResponse, length/sizeof(SQLTCHAR)).startsWith(QLatin1Char('Y'));
#else
- hasMultiResultSets = QString::fromLocal8Bit(driverResponse, length).startsWith(QLatin1Char('Y'));
+ hasMultiResultSets = QString::fromUtf8((const char *)driverResponse.constData(), length).startsWith(QLatin1Char('Y'));
#endif
}
@@ -2134,9 +2273,9 @@
NULL,
0,
#ifdef UNICODE
- (SQLWCHAR*)joinedTableTypeString.unicode(),
+ toSQLTCHAR(joinedTableTypeString).data(),
#else
- (SQLCHAR*)joinedTableTypeString.toLatin1().constData(),
+ (SQLCHAR*)joinedTableTypeString.toUtf8().data(),
#endif
joinedTableTypeString.length() /* characters, not bytes */);
@@ -2150,6 +2289,11 @@
else
r = SQLFetch(hStmt);
+ if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r != SQL_NO_DATA) {
+ qWarning() << "QODBCDriver::tables failed to retrieve table/view list: (" << r << "," << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ")";
+ return QStringList();
+ }
+
while (r == SQL_SUCCESS) {
QString fieldVal = qGetStringData(hStmt, 2, -1, false);
tl.append(fieldVal);
@@ -2208,21 +2352,21 @@
SQL_IS_UINTEGER);
r = SQLPrimaryKeys(hStmt,
#ifdef UNICODE
- catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(),
+ catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
#else
- catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(),
+ catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(),
#endif
catalog.length(),
#ifdef UNICODE
- schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(),
+ schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
#else
- schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(),
+ schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(),
#endif
schema.length(),
#ifdef UNICODE
- (SQLWCHAR*)table.unicode(),
+ toSQLTCHAR(table).data(),
#else
- (SQLCHAR*)table.toLatin1().constData(),
+ (SQLCHAR*)table.toUtf8().data(),
#endif
table.length() /* in characters, not in bytes */);
@@ -2233,21 +2377,21 @@
r = SQLSpecialColumns(hStmt,
SQL_BEST_ROWID,
#ifdef UNICODE
- catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(),
+ catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
#else
- catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(),
+ catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(),
#endif
catalog.length(),
#ifdef UNICODE
- schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(),
+ schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
#else
- schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(),
+ schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(),
#endif
schema.length(),
#ifdef UNICODE
- (SQLWCHAR*)table.unicode(),
+ toSQLTCHAR(table).data(),
#else
- (SQLCHAR*)table.toLatin1().constData(),
+ (SQLCHAR*)table.toUtf8().data(),
#endif
table.length(),
SQL_SCOPE_CURROW,
@@ -2333,21 +2477,21 @@
SQL_IS_UINTEGER);
r = SQLColumns(hStmt,
#ifdef UNICODE
- catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(),
+ catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
#else
- catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(),
+ catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(),
#endif
catalog.length(),
#ifdef UNICODE
- schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(),
+ schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
#else
- schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(),
+ schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(),
#endif
schema.length(),
#ifdef UNICODE
- (SQLWCHAR*)table.unicode(),
+ toSQLTCHAR(table).data(),
#else
- (SQLCHAR*)table.toLatin1().constData(),
+ (SQLCHAR*)table.toUtf8().data(),
#endif
table.length(),
NULL,