查询结果处理
QueryResult 类提供了一种处理 SQL 结果集行的便捷方式。records()
方法返回一个 Cursor 对象,该对象提供了 hasNext()
方法来遍历结果集行,并提供了多个用于从这些行中提取数据或列信息的方法。
以下代码片段演示了如何从查询select * from Person
的结果集中提取并打印出值:
void show_results(McoSqlEngine& engine)
{
QueryResult result(engine.executeQuery("select * from Person"));
Cursor * cursor = result->records();
while (cursor->hasNext())
{
Record * rec = cursor->next();
// Extract the _Person record to the corresponding struct
_Person p;
result->extract(rec, &p, sizeof(p));
printf("\tName=%s, Ordinal=%u\n", p.name, p.ordinal );
}
}
结构体 _Person
如下:
// 定义与数据库表“Person”相对应的结构。
struct _Person
{
char const* name;
uint4 ordinal;
};
C++ 的 QueryResult 的主要用途是控制查询的范围,并在查询异常终止时自动释放所有已分配的资源。如果查询的范围(QueryResult 对象实例的生命周期)不正确,将会导致运行时错误。这种情况可能会在实例超出其创建的事务范围使用时发生,或者在数据库实例关闭时该实例仍然存在。以下代码片段演示了这种错误用法可能出现的情况:
main (void)
{
McoSqlEngine engine;
engine.open( ... );
...
QueryResult result(engine.executeQuery("select * from aRecord"));
Cursor* cursor = result->records();
while (cursor->hasNext()) {
...
} /* while 循环结束 */
engine.close(); /* 数据库实例在此处被销毁。 */
return 0;
/* 由局部变量“result”表示的 QueryResult 类对象将在此处被删除。
/* 由于数据库已不存在,QueryResult 析构函数会导致应用程序崩溃。*/
}
由于创建对象的事务上下文被保存在对象内部,因此如果事务不再有效,对该对象句柄的任何操作都会导致错误。在上述代码中,当对象 result 超出作用域时,会调用 QueryResult 析构函数。但由于数据库已关闭,result
中的事务句柄不再有效,因此尝试关闭事务会导致应用程序崩溃!
为避免这种情况,任何 QueryResult 类的实例在不再需要时都必须立即删除。如果该对象是通过 new
创建的,则可以通过显式调用 delete 操作符来删除;如果该对象是作为局部变量实例化的,则可以使用花括号来删除。