在本节中,我将首先介绍MYSQL++中的查询的几个简单例子用法,然后看一下mysqlpp::Query中的几个与查询相关的方法原型(重点关注返回值),最后对几个关键类型进行解释。
1. MYSQL++的查询实例
下面的两个例子分别是STORE(所有数据一次性从服务器拉到本地缓存)和USE(将数据一条一条从服务器拉到本地)的使用方式,其中STORE内部实质就是mysql_store( ),而USE实质就是调用了mysql_use( )。
说明,下面的例子虽然使用的都是最为基本的查询过程(即没有使用template sql或者SSQLS),但是这个并不影响我们的讨论,因为遍历结果集的过程是一致的。
STORE
mysqlpp::Query query = conn.query("select item from stock"); mysqlpp::StoreQueryResult res = query.store(); mysqlpp::StoreQueryResult::const_iterator it; for (it = res.begin(); it != res.end(); ++it) { mysqlpp::Row row = *it; // 第一列 row[0] // 第二列 row[1] }
USE
mysqlpp::Query query = conn.query("select * from stock"); mysqlpp::UseQueryResult res = query.use(); while (mysqlpp::Row row = res.fetch_row()) { row["item"]; row["num"]; } // Check for error: // can't distinguish "end of results" and // error cases in return from fetch_row() otherwise if (conn.errnum()) { cout << "Error in fetch_row"; }
从上面的两个例子中我们大致可以看出来,整个结果集的查询过程就是针对相匹配的Result类型,找到ROW,然后逐行或者跳跃着查找。
2. Result相关类型的使用场合
首先让我们回顾mysqlpp::Query中提到的几个方法,以及他们的返回值。以下部分内容直接摘自关于mysqlpp::Query的介绍的内容。
为了讲述方便,我们先来看一下在result.h(Declares classes for holding information about SQL query)中所定义的各种类型的关系。这几个类型后面会仔细说明。
1)
bool mysqlpp::Query::exec(const std::string& str);
这里返回的是bool,表示的是“语句是否执行成功”,我认为适合于那种update, delete,insert,且都不关心有多少rows被touch的情况。
2)
SimpleResult mysqlpp::Query::execute();
这里的SimpleResult正如其名,其中只有如下信息
the last value used for an AUTO_INCREMENT field(ulonglong insert_id() const)
the number of rows affected by the query(ulonglong rows( ) const)
any additional information about the query returned by the server(const char* info( ) const)
3)
UseQueryResult mysqlpp::Query::use();
由于use的语义类似于使用游标,也就是支持一行一行地拉出内容,所以UseQueryResult 也就自然而然地支持一些关于fetch row的功能。
4)
StoreQueryResult mysqlpp::Query::store();
StoreQueryResult它本身就是从vector<Row>继承而来,所以它就是vector。所以用户程序可以直接使用下标的形式来获取所有的ROW。这也就是说在这个store之后,所有的ROW的内容都在了这个vecor<Row>里面了。
3. Result相关类型解析
与Result相关的类型主要集中在result.h和result.cpp。
1) SimpleResult
这个类型非常简单,是一个比较单纯的类型,并没有父类。主要的成员变量有3个,分别是
// last value used for an AUTO_INCREMENT field ulonglong insert_id_; // the number of rows affected by the query ulonglong rows_; // any additional information about the query returned by the server std::string info_;
成员方法也比较单纯,就是对上述几个字段的GET,构造函数就是对上述几个字段的SET。
以SimpleResult mysqlpp::Query::execute();为例,让我们来看一下MYSQL++是如何设置这个SimpleResult。
再来看一下Query::insert_id( ), Query::affected_rows( ), Query::info( ),这几个方法都直接delegate DBDriver的相关函数,直接返回了结果而已。
2) ResultBase
这个类型是StoreQueryResult和UseQueryResult的父类型,该类型其实没有特别的含义,只是作为一个common methods的container而已。但是该类型提供的几乎所有的public methods都是和fields有关的,包括了
该类型的核心成员有如下几个
其中FieldNames和FieldTypes都是被RefCountedPointer包裹着,估计这样做能够节省空间。关于Field类型在后续进行介绍。至于刚才说的几个找field的操作,看着这几个核心成员的类型还是比较好理解的。不就是在vector中不找。
需要额外关注的是以下这个最主要的构造函数
以下几点需要注意,
explicit std::vector::vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());
3) StoreQueryResult
该类型是同时集成了ResultBase和vecor<Row>类型(请注意了,这个Result居然是一个vecor<Row>!)文档中说,该类型hold results from a SQL query that returns rows: a specialization of std::vector holding Row objects in memory so you get random-access semantics.
说白了,该类型在继承了ResultBase之后,只有以下这个构造函数是比较要紧的了。
有以下几点需要说明
如此一来,所有我们需要的信息都通过构造一个mysqlpp::Row对象来实现了。关于mysqlpp::Row的具体说明请看下文。
4) UseQueryResult
该类型拓展于ResultBase类型。根据MYSQL++ user document的说法,UseQueryResule适用于For these large result sets,a “use” query tells the database server to send the results back one row at a time, to be processed linearly.
该类型的方法比StoreQueryResult丰富多了,主要体现在:
值得注意的是,UseQueryResult有一个成员变量
mutable RefCountedPointer<MYSQL_RES> result_;
需要强调的有两点
很显然,这个是为了在ref count为0时自动调用析构器而准备的,该Destroyer使用mysql_free_result来销毁这里的result_,从而代替默认的delete操作。
接下来,我们来具体看几个函数的实现。
请注意,这个result_是一个RefCountedPointer<MYSQL_RES>,所以调用的raw方法将会返回MYSQL_RES*
核心的做法就是利用MYSQL_ROW DBDriver::fetch_row(MYSQL_RES* res) const。其实质也就是调用了mysql_fetch_one_row( )这个C API。然后直接生成一个mysqlpp::Row对象,返回。