📄 qsql_odbc.cpp
字号:
r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], SQL_C_BINARY, SQL_LONGVARBINARY, val.toByteArray().size(), 0, (void *) val.toByteArray().constData(), val.toByteArray().size(), ind); break;#ifndef Q_ODBC_VERSION_2 case QVariant::String: if (d->unicode) { QString str = val.toString(); str.utf16(); if (*ind != SQL_NULL_DATA) *ind = str.length() * sizeof(QChar); if (bindValueType(i) & QSql::Out) { QByteArray ba((char*)str.constData(), str.capacity() * sizeof(QChar)); r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], SQL_C_WCHAR, str.length() > 4000 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, 0, // god knows... don't change this! 0, (void *)ba.constData(), ba.size(), ind); tmpStorage.append(ba); break; } r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], SQL_C_WCHAR, str.length() > 4000 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, str.length() * sizeof(QChar), 0, (void *)str.constData(), str.length() * sizeof(QChar), ind); break; }#endif // fall through default: { QByteArray ba = val.toString().toAscii(); if (*ind != SQL_NULL_DATA) *ind = ba.size(); r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], SQL_C_CHAR, ba.length() > 4000 ? SQL_LONGVARCHAR : SQL_VARCHAR, ba.length() + 1, 0, (void *) ba.constData(), ba.length() + 1, ind); tmpStorage.append(ba); break; } } if (r != SQL_SUCCESS) { qWarning("QODBCResult::exec: unable to bind variable: %s", qODBCWarn(d).toLocal8Bit().constData()); setLastError(qMakeError(QCoreApplication::translate("QODBCResult", "Unable to bind variable"), QSqlError::StatementError, d)); return false; } } r = SQLExecute(d->hStmt); if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { qWarning("QODBCResult::exec: Unable to execute statement: %s", qODBCWarn(d).toLocal8Bit().constData()); setLastError(qMakeError(QCoreApplication::translate("QODBCResult", "Unable to execute statement"), QSqlError::StatementError, d)); return false; } SQLSMALLINT count; r = SQLNumResultCols(d->hStmt, &count); if (count) { setSelect(true); for (int i = 0; i < count; ++i) { d->rInf.append(qMakeFieldInfo(d, i)); } d->fieldCache.resize(count); } else { setSelect(false); } setActive(true); //get out parameters if (!hasOutValues()) return true; for (i = 0; i < values.count(); ++i) { switch (values.at(i).type()) { case QVariant::Date: { DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData()); values[i] = QVariant(QDate(ds.year, ds.month, ds.day)); break; } case QVariant::Time: { TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData()); values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second)); break; } case QVariant::DateTime: { TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*) tmpStorage.takeFirst().constData()); values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day), QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000))); break; } case QVariant::Int: case QVariant::Double: case QVariant::ByteArray: //nothing to do break; case QVariant::String: if (d->unicode) { if (bindValueType(i) & QSql::Out) values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData()); break; } // fall through default: { QByteArray ba = tmpStorage.takeFirst(); if (bindValueType(i) & QSql::Out) values[i] = QString::fromAscii(tmpStorage.takeFirst().constData()); break; } } if (indicators[i] == SQL_NULL_DATA) values[i] = QVariant(values[i].type()); } return true;}QSqlRecord QODBCResult::record() const{ if (!isActive() || !isSelect()) return QSqlRecord(); return d->rInf;}QVariant QODBCResult::handle() const{ return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt);}////////////////////////////////////////QODBCDriver::QODBCDriver(QObject *parent) : QSqlDriver(parent){ init();}QODBCDriver::QODBCDriver(SQLHANDLE env, SQLHANDLE con, QObject * parent) : QSqlDriver(parent){ init(); d->hEnv = env; d->hDbc = con; if (env && con) { setOpen(true); setOpenError(false); }}void QODBCDriver::init(){ d = new QODBCDriverPrivate();}QODBCDriver::~QODBCDriver(){ cleanup(); delete d;}bool QODBCDriver::hasFeature(DriverFeature f) const{ switch (f) { case Transactions: { if (!d->hDbc) return false; SQLUSMALLINT txn; SQLSMALLINT t; int r = SQLGetInfo(d->hDbc, (SQLUSMALLINT)SQL_TXN_CAPABLE, &txn, sizeof(txn), &t); if (r != SQL_SUCCESS || txn == SQL_TC_NONE) return false; else return true; } case Unicode: return d->unicode; case PreparedQueries: case BLOB: case PositionalPlaceholders: return true; case QuerySize: case NamedPlaceholders: case LastInsertId: case BatchOperations: return false; } return false;}bool QODBCDriver::open(const QString & db, const QString & user, const QString & password, const QString &, int, const QString& connOpts){ if (isOpen()) close(); SQLRETURN r; r = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &d->hEnv); if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { qSqlWarning(QLatin1String("QODBCDriver::open: Unable to allocate environment"), d); setOpenError(true); return false; } r = SQLSetEnvAttr(d->hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, SQL_IS_UINTEGER); r = SQLAllocHandle(SQL_HANDLE_DBC, d->hEnv, &d->hDbc); if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { qSqlWarning(QLatin1String("QODBCDriver::open: Unable to allocate connection"), d); setOpenError(true); return false; } if (!d->setConnectionOptions(connOpts)) return false; // Create the connection string QString connQStr; // support the "DRIVER={SQL SERVER};SERVER=blah" syntax if (db.contains(QLatin1String(".dsn"))) connQStr = QLatin1String("FILEDSN=") + db; else if (db.contains(QLatin1String("DRIVER")) || db.contains(QLatin1String("SERVER"))) connQStr = db; else connQStr = QLatin1String("DSN=") + db; connQStr += QLatin1String(";UID=") + user + QLatin1String(";PWD=") + password; SQLSMALLINT cb; SQLTCHAR connOut[1024]; r = SQLDriverConnect(d->hDbc, NULL,#ifdef UNICODE (SQLWCHAR*)connQStr.unicode(),#else (SQLCHAR*)connQStr.toLatin1().constData(),#endif (SQLSMALLINT)connQStr.length(), connOut, 1024, &cb, SQL_DRIVER_NOPROMPT); if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d)); setOpenError(true); return false; } if (!d->checkDriver()) { setLastError(qMakeError(tr("Unable to connect - Driver doesn't support all " "needed functionality"), QSqlError::ConnectionError, d)); setOpenError(true); return false; } d->checkUnicode(); d->checkSchemaUsage(); setOpen(true); setOpenError(false); return true;}void QODBCDriver::close(){ cleanup(); setOpen(false); setOpenError(false);}void QODBCDriver::cleanup(){ SQLRETURN r; if (!d) return; if(d->hDbc) { // Open statements/descriptors handles are automatically cleaned up by SQLDisconnect if (isOpen()) { r = SQLDisconnect(d->hDbc); if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver::disconnect: Unable to disconnect datasource"), d); } r = SQLFreeHandle(SQL_HANDLE_DBC, d->hDbc); if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver::cleanup: Unable to free connection handle"), d); d->hDbc = 0; } if (d->hEnv) { r = SQLFreeHandle(SQL_HANDLE_ENV, d->hEnv); if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver::cleanup: Unable to free environment handle"), d); d->hEnv = 0; }}// checks whether the server can return char, varchar and longvarchar// as two byte unicode charactersvoid QODBCDriverPrivate::checkUnicode(){#if defined(Q_WS_WIN) QT_WA( {}, { unicode = false; return; })#endif SQLRETURN r; SQLUINTEGER fFunc; unicode = false; r = SQLGetInfo(hDbc, SQL_CONVERT_CHAR, (SQLPOINTER)&fFunc, sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) { sql_char_type = QVariant::String; unicode = true; } r = SQLGetInfo(hDbc, SQL_CONVERT_VARCHAR, (SQLPOINTER)&fFunc, sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) { sql_varchar_type = QVariant::String; unicode = true; } r = SQLGetInfo(hDbc, SQL_CONVERT_LONGVARCHAR, (SQLPOINTER)&fFunc, sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) { sql_longvarchar_type = QVariant::String; unicode = true; }}bool QODBCDriverPrivate::checkDriver() const{#ifdef ODBC_CHECK_DRIVER // do not query for SQL_API_SQLFETCHSCROLL because it can't be used at this time static const SQLUSMALLINT reqFunc[] = { SQL_API_SQLDESCRIBECOL, SQL_API_SQLGETDATA, SQL_API_SQLCOLUMNS, SQL_API_SQLGETSTMTATTR, SQL_API_SQLGETDIAGREC, SQL_API_SQLEXECDIRECT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -