summaryrefslogtreecommitdiffstats
path: root/src/sql
diff options
context:
space:
mode:
Diffstat (limited to 'src/sql')
-rw-r--r--src/sql/drivers/drivers.pri1
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp17
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp269
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.h1
-rw-r--r--src/sql/kernel/qsqlquery.cpp11
-rw-r--r--src/sql/kernel/qsqlresult.cpp13
6 files changed, 204 insertions, 108 deletions
diff --git a/src/sql/drivers/drivers.pri b/src/sql/drivers/drivers.pri
index aac0267..8dfc50f 100644
--- a/src/sql/drivers/drivers.pri
+++ b/src/sql/drivers/drivers.pri
@@ -46,6 +46,7 @@ contains(sql-drivers, odbc) {
mac:!contains( LIBS, .*odbc.* ):LIBS *= -liodbc
unix:!contains( LIBS, .*odbc.* ):LIBS *= -lodbc
+ unix:DEFINES += UNICODE
win32 {
!win32-borland:LIBS *= -lodbc32
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index c0f866e..2261887 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -320,6 +320,16 @@ static bool qIsBlob(int t)
|| t == MYSQL_TYPE_LONG_BLOB;
}
+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()
{
int i;
@@ -368,6 +378,13 @@ bool QMYSQLResultPrivate::bindInValues()
fieldInfo->length = 0;
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;
}
bind = &inBinds[i];
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index 9f7d267..ee22bc3 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -71,11 +71,54 @@ QT_BEGIN_NAMESPACE
# 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:
@@ -91,8 +134,8 @@ public:
SQLHANDLE hEnv;
SQLHANDLE hDbc;
- uint unicode :1;
- uint useSchema :1;
+ bool unicode;
+ bool useSchema;
int disconnectCount;
bool isMySqlServer;
bool isMSSqlServer;
@@ -132,8 +175,8 @@ public:
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;
@@ -170,19 +213,18 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode
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_,
@@ -195,9 +237,9 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode
*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())
@@ -216,13 +258,13 @@ static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0)
{
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)
@@ -322,17 +364,22 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
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);
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_TCHAR,
+ NULL,
+ 0,
+ &lengthIndicator);
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
+ QVarLengthArray<SQLTCHAR> buf(colSize);
while (true) {
r = SQLGetData(hStmt,
column+1,
- unicode ? SQL_C_WCHAR : SQL_C_CHAR,
+ SQL_C_TCHAR,
(SQLPOINTER)buf.data(),
- colSize,
+ colSize*sizeof(SQLTCHAR),
&lengthIndicator);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
@@ -344,14 +391,9 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
// 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 {
- fieldVal += QString::fromAscii(buf.constData(), rSize);
- }
- memset(buf.data(), 0, colSize);
- if (lengthIndicator < colSize) {
+ 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;
}
@@ -377,10 +419,11 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column)
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,
@@ -513,10 +556,10 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i )
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,
@@ -542,9 +585,9 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i )
}
#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;
@@ -576,18 +619,21 @@ static int qGetODBCVersion(const QString &connOpts)
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;
@@ -631,11 +677,11 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
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;
@@ -653,11 +699,11 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
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;
@@ -867,12 +913,12 @@ bool QODBCResult::reset (const QString& query)
#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) {
@@ -1218,12 +1264,12 @@ bool QODBCResult::prepare(const QString& query)
#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
@@ -1421,42 +1467,43 @@ bool QODBCResult::exec()
case QVariant::String:
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
{
- QByteArray str = val.toString().toAscii();
+ QByteArray str = val.toString().toUtf8();
if (*ind != SQL_NULL_DATA)
*ind = str.length();
int strSize = str.length();
@@ -1557,15 +1604,18 @@ bool QODBCResult::exec()
break;
case QVariant::String:
if (d->unicode) {
- if (bindValueType(i) & QSql::Out)
- values[i] = QString((QChar *)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)
@@ -1774,19 +1824,20 @@ bool QODBCDriver::open(const QString & db,
connQStr += QLatin1String(";PWD=") + password;
SQLSMALLINT cb;
- SQLTCHAR connOut[1024];
+ QVarLengthArray<SQLTCHAR> connOut(1024);
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);
@@ -1957,20 +2008,21 @@ void QODBCDriverPrivate::checkSchemaUsage()
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);
@@ -1989,18 +2041,18 @@ void QODBCDriverPrivate::checkHasSQLFetchScroll()
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
}
@@ -2114,9 +2166,9 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
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 */);
@@ -2130,6 +2182,11 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
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);
@@ -2188,21 +2245,21 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const
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 */);
@@ -2213,21 +2270,21 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const
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,
@@ -2313,21 +2370,21 @@ QSqlRecord QODBCDriver::record(const QString& tablename) const
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,
diff --git a/src/sql/drivers/odbc/qsql_odbc.h b/src/sql/drivers/odbc/qsql_odbc.h
index 836dbd6..e739a38 100644
--- a/src/sql/drivers/odbc/qsql_odbc.h
+++ b/src/sql/drivers/odbc/qsql_odbc.h
@@ -68,7 +68,6 @@
# undef _MSC_VER
#endif
-#include <sqlucode.h>
#include <sqlext.h>
QT_BEGIN_HEADER
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index 6c6436f..f253c82 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -822,6 +822,9 @@ bool QSqlQuery::isForwardOnly() const
scrollable. isForwardOnly() will always return the correct status of
the result set.
+ \note Calling setForwardOnly after execution of the query will result
+ in unexpected results at best, and crashes at worst.
+
\sa isForwardOnly(), next(), seek(), QSqlResult::setForwardOnly()
*/
void QSqlQuery::setForwardOnly(bool forward)
@@ -999,10 +1002,18 @@ bool QSqlQuery::execBatch(BatchExecutionMode mode)
must be included when specifying the placeholder name. If \a
paramType is QSql::Out or QSql::InOut, the placeholder will be
overwritten with data from the database after the exec() call.
+ In this case, sufficient space must be pre-allocated to store
+ the result into.
To bind a NULL value, use a null QVariant; for example, use
\c {QVariant(QVariant::String)} if you are binding a string.
+ Values cannot be bound to multiple locations in the query, eg:
+ \code
+ INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name)
+ \endcode
+ Binding to name will bind to the first :name, but not the second.
+
\sa addBindValue(), prepare(), exec(), boundValue() boundValues()
*/
void QSqlQuery::bindValue(const QString& placeholder, const QVariant& val,
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 3d63f88..6382b42 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -564,6 +564,9 @@ bool QSqlResult::isForwardOnly() const
scrollable. isForwardOnly() will always return the correct status of
the result set.
+ \note Calling setForwardOnly after execution of the query will result
+ in unexpected results at best, and crashes at worst.
+
\sa isForwardOnly(), fetchNext(), QSqlQuery::setForwardOnly()
*/
void QSqlResult::setForwardOnly(bool forward)
@@ -707,7 +710,15 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param
Binds the value \a val of parameter type \a paramType to the \a
placeholder name in the current record (row).
- Note that binding an undefined placeholder will result in undefined behavior.
+ Values cannot be bound to multiple locations in the query, eg:
+ \code
+ INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name)
+ \endcode
+ Binding to name will bind to the first :name, but not the second.
+
+ \note Binding an undefined placeholder will result in undefined behavior.
+
+ \sa QSqlQuery::bindValue()
*/
void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
QSql::ParamType paramType)