Skip to content

Commit c102487

Browse files
committed
ODBC fixes
1 parent 8357794 commit c102487

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

src/ADriverOdbc.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,17 @@ void AOdbcThread::fetchResults(SQLHSTMT stmt, OdbcQueryPromise &promise)
410410
return;
411411
}
412412

413+
// Non-row statements (BEGIN/COMMIT/ROLLBACK, DML) have no result columns.
414+
// SQLFetch on them yields "Invalid cursor state" on SQL Server.
415+
if (numCols == 0) {
416+
SQLLEN rowCount = 0;
417+
SQLRowCount(stmt, &rowCount);
418+
if (rowCount >= 0) {
419+
promise.result->m_numRowsAffected = static_cast<qint64>(rowCount);
420+
}
421+
return;
422+
}
423+
413424
// Fetch column names and types
414425
QVector<SQLSMALLINT> colTypes(numCols);
415426
for (SQLSMALLINT i = 1; i <= numCols; ++i) {
@@ -484,13 +495,14 @@ void AOdbcThread::bindParameters(SQLHSTMT stmt,
484495
SQLRETURN ret = SQL_SUCCESS;
485496

486497
if (val.isNull()) {
498+
// SQL Server rejects SQL_C_DEFAULT for untyped NULLs; WCHAR/VARCHAR is portable.
487499
indicators[i] = SQL_NULL_DATA;
488500
ret = SQLBindParameter(stmt,
489501
paramNum,
490502
SQL_PARAM_INPUT,
491-
SQL_C_DEFAULT,
492-
SQL_VARCHAR,
493-
0,
503+
SQL_C_WCHAR,
504+
SQL_WVARCHAR,
505+
1,
494506
0,
495507
nullptr,
496508
0,
@@ -499,9 +511,10 @@ void AOdbcThread::bindParameters(SQLHSTMT stmt,
499511
switch (val.typeId()) {
500512
case QMetaType::Bool:
501513
{
514+
// Fixed-length BIT: StrLen_or_Ind must be 0 (not sizeof), same as INTEGER.
502515
SQLCHAR bval = val.toBool() ? 1 : 0;
503516
buffers[i] = QByteArray(reinterpret_cast<const char *>(&bval), sizeof(bval));
504-
indicators[i] = sizeof(SQLCHAR);
517+
indicators[i] = 0;
505518
ret = SQLBindParameter(stmt,
506519
paramNum,
507520
SQL_PARAM_INPUT,
@@ -978,7 +991,8 @@ ADatabase::State ADriverOdbc::state() const
978991

979992
void ADriverOdbc::begin(const std::shared_ptr<ADriver> &db, QObject *receiver, ACoroDataRef cb)
980993
{
981-
exec(db, u8"BEGIN", receiver, std::move(cb));
994+
// SQL Server rejects bare BEGIN; BEGIN TRANSACTION is portable across ODBC backends.
995+
exec(db, u8"BEGIN TRANSACTION", receiver, std::move(cb));
982996
}
983997

984998
void ADriverOdbc::commit(const std::shared_ptr<ADriver> &db, QObject *receiver, ACoroDataRef cb)

0 commit comments

Comments
 (0)