Index: trunk/src/sql/drivers/drivers.pri
===================================================================
--- trunk/src/sql/drivers/drivers.pri	(revision 651)
+++ trunk/src/sql/drivers/drivers.pri	(revision 769)
@@ -50,4 +50,5 @@
      mac:!contains( LIBS, .*odbc.* ):LIBS        *= -liodbc
      unix:!contains( LIBS, .*odbc.* ):LIBS       *= -lodbc
+     unix:DEFINES += UNICODE
 
      win32 {
Index: trunk/src/sql/drivers/mysql/qsql_mysql.cpp
===================================================================
--- trunk/src/sql/drivers/mysql/qsql_mysql.cpp	(revision 651)
+++ trunk/src/sql/drivers/mysql/qsql_mysql.cpp	(revision 769)
@@ -321,4 +321,14 @@
 }
 
+static bool qIsInteger(int t)
+{
+    return t == MYSQL_TYPE_TINY
+           || t == MYSQL_TYPE_SHORT
+           || t == MYSQL_TYPE_LONG
+           || t == MYSQL_TYPE_LONGLONG
+           || t == MYSQL_TYPE_INT24;
+}
+
+
 void QMYSQLResultPrivate::bindBlobs()
 {
@@ -369,4 +379,11 @@
             hasBlobs = true;
         } else {
+            // fieldInfo->length specifies the display width, which may be too
+            // small to hold valid integer values (see
+            // http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html ), so
+            // always use the MAX_BIGINT_WIDTH for integer types
+            if (qIsInteger(fieldInfo->type)) {
+                fieldInfo->length = MAX_BIGINT_WIDTH;
+            }
             fieldInfo->type = MYSQL_TYPE_STRING;
         }
Index: trunk/src/sql/drivers/oci/qsql_oci.cpp
===================================================================
--- trunk/src/sql/drivers/oci/qsql_oci.cpp	(revision 651)
+++ trunk/src/sql/drivers/oci/qsql_oci.cpp	(revision 769)
@@ -518,5 +518,5 @@
     else if (ocitype == QLatin1String("LONG") || ocitype == QLatin1String("NCLOB")
              || ocitype == QLatin1String("CLOB"))
-        type = QVariant::String;
+        type = QVariant::ByteArray;
     else if (ocitype == QLatin1String("RAW") || ocitype == QLatin1String("LONG RAW")
              || ocitype == QLatin1String("ROWID") || ocitype == QLatin1String("BLOB")
@@ -544,5 +544,4 @@
     case SQLT_RDD:
     case SQLT_LNG:
-    case SQLT_CLOB:
 #ifdef SQLT_INTERVAL_YM
     case SQLT_INTERVAL_YM:
@@ -582,4 +581,5 @@
     case SQLT_LVB:
     case SQLT_BLOB:
+    case SQLT_CLOB:
     case SQLT_FILE:
     case SQLT_NTY:
Index: trunk/src/sql/drivers/odbc/qsql_odbc.cpp
===================================================================
--- trunk/src/sql/drivers/odbc/qsql_odbc.cpp	(revision 651)
+++ trunk/src/sql/drivers/odbc/qsql_odbc.cpp	(revision 769)
@@ -67,5 +67,5 @@
 # undef UNICODE
 # define SQLTCHAR SQLCHAR
-# define SQL_C_WCHAR SQL_C_CHAR
+# define SQL_C_TCHAR SQL_C_CHAR
 #endif
 
@@ -79,9 +79,52 @@
 #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
 {
@@ -89,9 +132,8 @@
     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;
     }
 
@@ -99,9 +141,10 @@
     SQLHANDLE hDbc;
 
-    uint unicode :1;
-    uint useSchema :1;
+    bool unicode;
+    bool useSchema;
     int disconnectCount;
     bool isMySqlServer;
     bool isMSSqlServer;
+    bool isFreeTDSDriver;
     bool hasSQLFetchScroll;
     bool hasMultiResultSets;
@@ -130,5 +173,8 @@
     : hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false)
     {
-        unicode = false;
+        unicode = dpp->unicode;
+        useSchema = dpp->useSchema;
+        disconnectCount = dpp->disconnectCount;
+        hasSQLFetchScroll = dpp->hasSQLFetchScroll;
     }
 
@@ -140,6 +186,6 @@
     SQLHANDLE hStmt;
 
-    uint unicode :1;
-    uint useSchema :1;
+    bool unicode;
+    bool useSchema;
 
     QSqlRecord rInf;
@@ -178,16 +224,15 @@
 
     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,
@@ -203,7 +248,7 @@
             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) {
@@ -224,5 +269,5 @@
     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();
 }
 
@@ -230,5 +275,5 @@
 {
     return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ')
-             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode));
+             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode)).simplified();
 }
 
@@ -308,5 +353,7 @@
     case SQL_CHAR:
     case SQL_VARCHAR:
+#if (ODBCVER >= 0x0350)
     case SQL_GUID:
+#endif
     case SQL_LONGVARCHAR:
         type = QVariant::String;
@@ -332,43 +379,87 @@
     } 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;
         }
     }
@@ -387,8 +478,9 @@
     SQLRETURN r = SQL_ERROR;
 
-    SQLTCHAR colName[COLNAMESIZE];
+    QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE);
+
     r = SQLDescribeCol(hStmt,
                        column + 1,
-                       colName,
+                       colName.data(),
                        COLNAMESIZE,
                        &colNameLen,
@@ -523,8 +615,8 @@
     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,
@@ -552,7 +644,7 @@
 
 #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
@@ -582,5 +674,11 @@
         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
 }
 
@@ -588,5 +686,5 @@
 {
     if (!isQuoteInitialized) {
-        char driverResponse[4];
+        SQLTCHAR driverResponse[4];
         SQLSMALLINT length;
         int r = SQLGetInfo(hDbc,
@@ -595,9 +693,12 @@
                 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;
     }
@@ -643,9 +744,9 @@
             r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG,
 #ifdef UNICODE
-                                    (SQLWCHAR*) val.unicode(),
+                                    toSQLTCHAR(val).data(),
 #else
-                                    (SQLCHAR*) val.toLatin1().constData(),
-#endif
-                                    SQL_NTS);
+                                    (SQLCHAR*) val.toUtf8().data(),
+#endif
+                                    val.length()*sizeof(SQLTCHAR));
         } else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) {
             if (val.toUpper() == QLatin1String("SQL_TRUE")) {
@@ -665,9 +766,9 @@
             r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE,
 #ifdef UNICODE
-                                    (SQLWCHAR*) val.unicode(),
+                                    toSQLTCHAR(val).data(),
 #else
-                                    (SQLCHAR*) val.toLatin1().constData(),
-#endif
-                                    SQL_NTS);
+                                    (SQLCHAR*) val.toUtf8().data(),
+#endif
+                                    val.length()*sizeof(SQLTCHAR));
         } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) {
             if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) {
@@ -815,8 +916,4 @@
 {
     d = new QODBCPrivate(p);
-    d->unicode = p->unicode;
-    d->useSchema = p->useSchema;
-    d->disconnectCount = p->disconnectCount;
-    d->hasSQLFetchScroll = p->hasSQLFetchScroll;
 }
 
@@ -881,10 +978,10 @@
 #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
@@ -1232,10 +1329,10 @@
 #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
@@ -1436,15 +1533,15 @@
                 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!
@@ -1453,18 +1550,19 @@
                                             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;
                 }
@@ -1472,5 +1570,5 @@
 #endif
                 {
-                    QByteArray str = val.toString().toAscii();
+                    QByteArray str = val.toString().toUtf8();
                     if (*ind != SQL_NULL_DATA)
                         *ind = str.length();
@@ -1573,13 +1671,16 @@
             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; }
         }
@@ -1790,17 +1891,19 @@
 
     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));
@@ -1887,4 +1990,5 @@
     if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
         unicode = true;
+        return;
     }
 
@@ -1896,4 +2000,5 @@
     if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
         unicode = true;
+        return;
     }
 
@@ -1905,5 +2010,23 @@
     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);
 }
 
@@ -1978,21 +2101,37 @@
 {
     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;
     }
 }
@@ -2010,16 +2149,16 @@
 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
 }
@@ -2135,7 +2274,7 @@
                    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,4 +2289,9 @@
     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) {
@@ -2209,19 +2353,19 @@
     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 */);
@@ -2234,19 +2378,19 @@
                         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(),
@@ -2334,19 +2478,19 @@
     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(),
Index: trunk/src/sql/drivers/odbc/qsql_odbc.h
===================================================================
--- trunk/src/sql/drivers/odbc/qsql_odbc.h	(revision 651)
+++ trunk/src/sql/drivers/odbc/qsql_odbc.h	(revision 769)
@@ -74,8 +74,4 @@
 #if defined(Q_CC_BOR)
 #  undef _MSC_VER
-#endif
-
-#ifndef Q_ODBC_VERSION_2
-#include <sqlucode.h>
 #endif
 
Index: trunk/src/sql/drivers/sqlite/qsql_sqlite.cpp
===================================================================
--- trunk/src/sql/drivers/sqlite/qsql_sqlite.cpp	(revision 651)
+++ trunk/src/sql/drivers/sqlite/qsql_sqlite.cpp	(revision 769)
@@ -246,7 +246,7 @@
                 break;
             default:
-                values[i + idx] = QString::fromUtf16(static_cast<const ushort *>(
+                values[i + idx] = QString(reinterpret_cast<const QChar *>(
                             sqlite3_column_text16(stmt, i)),
-                            sqlite3_column_bytes16(stmt, i) / sizeof(ushort));
+                            sqlite3_column_bytes16(stmt, i) / sizeof(QChar));
                 break;
             }
@@ -260,4 +260,5 @@
         sqlite3_reset(stmt);
         return false;
+    case SQLITE_CONSTRAINT:
     case SQLITE_ERROR:
         // SQLITE_ERROR is a generic error code and we must call sqlite3_reset()
@@ -501,30 +502,4 @@
 }
 
-static int qGetSqliteTimeout(QString opts)
-{
-    enum { DefaultTimeout = 5000 };
-
-    opts.remove(QLatin1Char(' '));
-    foreach(QString option, opts.split(QLatin1Char(';'))) {
-        if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
-            bool ok;
-            int nt = option.mid(21).toInt(&ok);
-            if (ok)
-                return nt;
-        }
-    }
-    return DefaultTimeout;
-}
-
-static int qGetSqliteOpenMode(QString opts)
-{
-    opts.remove(QLatin1Char(' '));
-    foreach(QString option, opts.split(QLatin1Char(';'))) {
-        if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
-                return SQLITE_OPEN_READONLY;
-    }
-    return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
-}
-
 /*
    SQLite dbs have no user name, passwords, hosts or ports.
@@ -538,7 +513,24 @@
     if (db.isEmpty())
         return false;
-
-    if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) {
-        sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
+    bool sharedCache = false;
+    int openMode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, timeOut=5000;
+    QStringList opts=QString(conOpts).remove(QLatin1Char(' ')).split(QLatin1Char(';'));
+    foreach(const QString &option, opts) {
+        if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
+            bool ok;
+            int nt = option.mid(21).toInt(&ok);
+            if (ok)
+                timeOut = nt;
+        }
+        if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
+            openMode = SQLITE_OPEN_READONLY;
+        if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE"))
+            sharedCache = true;
+    }
+
+    sqlite3_enable_shared_cache(sharedCache);
+
+    if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) {
+        sqlite3_busy_timeout(d->access, timeOut);
         setOpen(true);
         setOpenError(false);
