从 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 开关,因为我真的不想深入研究它,而且这似乎不是我的问题,所以我保留了原样。
我有一些查询应该 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 开关,因为我真的不想深入研究它,而且这似乎不是我的问题,所以我保留了原样。