@@ -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
979992void 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
984998void ADriverOdbc::commit (const std::shared_ptr<ADriver> &db, QObject *receiver, ACoroDataRef cb)
0 commit comments