从 freetds 处理多个 dbcount?

Handing multiple dbcount from freetds?

我有一些查询应该 return 多个 'affected rows' (当 运行 宁通过 SQL Server Management Studio 时这样做),但我似乎无法弄清楚如何正确调用 dbcount 不止一次。

这是我使用 FreeTDS library:

的测试函数
- (BOOL) testCommand: (NSString*) queryToExecute
{
    RETCODE retcode;

    // Set our command
    retcode = dbcmd(dbProc, [queryToExecute UTF8String]);
    if(SUCCEED != retcode)
    {
        return NO;
    } // End of failed to set command

    retcode = dbsqlexec(dbProc);
    if(SUCCEED != retcode)
    {
        NSLog(@"Query failure, retcode was: %d", retcode);

        // Error handling goes here

        return NO;
    } // End of failed to sqlexec

    while(SUCCEED == (retcode = dbresults(dbProc)))
    {
        if(SUCCEED == (retcode = dbrows(dbProc)))
        {
            // Loop though our records
            NSUInteger rowCount = 0;
            while (NO_MORE_ROWS != (retcode = dbnextrow(dbProc)))
            {
                ++rowCount;
            } // End of records loop

            NSLog(@"Command completed successfully. (%ld results).", rowCount);
        } // End dbrows succeeded
        else
        {
            NSNumber * numberOfRowsAffected = [NSNumber numberWithInt: dbcount(dbProc)];
            bool isCountReal = dbiscount(dbProc);
            NSLog(@"Command completed successfully. (%@ rows affected). (%@).",
                  numberOfRowsAffected,
                  isCountReal ? @"YES" : @"NO");
        }
    } // End of dbresults loop

    return YES;
}

如果我 运行 通过此代码与 SSMS 进行查询,我会得到不同的结果:

update actor set [first_name] = 'PENELOPE' where first_name = 'PENELOPE';
SELECT * FROM actor;
update actor set [first_name] = 'NICK' where first_name = 'NICK';
SELECT * FROM actor;

SSMS:

(4 row(s) affected)
(200 row(s) affected)
(3 row(s) affected)
(200 row(s) affected)

FreeTDS:

Command completed successfully. (4 rows affected).
Command completed successfully. (200 results).
Command completed successfully. (200 results).

查询:

SELECT * FROM actor;
update actor set [first_name] = 'PENELOPE' where first_name = 'PENELOPE';

SSMS:

(200 row(s) affected)
(4 row(s) affected)

FreeTDS:

Command completed successfully. (200 results).

查询:

update actor set [first_name] = 'PENELOPE' where first_name = 'PENELOPE';
SELECT * FROM actor;

SSMS:

(4 row(s) affected)
(200 row(s) affected)

FreeTDS:

Command completed successfully. (4 rows affected).
Command completed successfully. (200 results).

我已经通过 SQL Server Profiler 确认命令在 SSMS 和我的 FreeTDS 代码中执行的相同。

正如您从 FreeTDS code/output 中看到的那样,我永远无法获得超过一次的受影响行数。我假设我在某个地方做错了什么或者我遗漏了什么,但到目前为止我一直无法弄清楚。我经历了 FreeTDS documentation 多次。

谁能给我指出正确的方向?

原来这是 FreeTDS 中的一个问题(问题 IMO,但对于其他一些人来说,这可能是必需的行为)。

我的解决方法是替换 _dbresults 方法中的以下代码:

            switch (dbproc->dbresults_state) {

            case _DB_RES_INIT:
            case _DB_RES_NEXT_RESULT:
                dbproc->dbresults_state = _DB_RES_NEXT_RESULT;
                if (done_flags & TDS_DONE_ERROR)
                    return FAIL;
                break;

与:

            switch (dbproc->dbresults_state) {

            case _DB_RES_INIT:
                dbproc->dbresults_state = _DB_RES_NEXT_RESULT;
                if (done_flags & TDS_DONE_ERROR)
                    return FAIL;
                break;

            case _DB_RES_NEXT_RESULT:
                dbproc->dbresults_state = _DB_RES_NEXT_RESULT;
                if (done_flags & TDS_DONE_ERROR)
                    return FAIL;

                return SUCCEED;
                break;

在前面的代码中,循环会一直持续到找到结果集或结果结尾为止。就我而言,我希望能够匹配 SSMS 输出。到目前为止,在我的测试中,这似乎有效,如果我确定一切正常,我将考虑向 FreeTDS 提交补丁。

我没有弄乱 _DB_RES_INIT 开关,因为我真的不想深入研究它,而且这似乎不是我的问题,所以我保留了原样。