2011年(15)
分类: SQLite/嵌入式数据库
2011-07-28 19:00:26
由于sqlite 2和sqlite 3有很多借口函数都改动了,比如sqlite_open()的参数变了,sqlite_freemem()没有了,可以用sqlite3_free()来替换,而sqlite_get_table_printf和sqlite_exec_printf函数都没有了,而且也没有函数可以替换。,如果将2升级到3会有许多要改动的地方,所以我在这里实现一个sqlite3_get_table_printf()函数,首先由于没有很多时间去研究sqlite3的代码结构,我只是经过参考对比sqlite 2和sqlite 3的代码,然后封装出这个函数。暂时还没发现问题。
由于sqlite 2中sqlite_get_table_printf调用sqlite_get_table_vprintf,sqlite_get_table_vprintf调用sqlite_vmprintf,而sqlite_vmprintf和sqlite3_vmprintf函数的接口是一样的,功能也一样。由此只要模仿sqlite3_vmprintf的实现流程,就可以很容易构造出我们需要的函数。
1. 在sqlite3.h中添加函数声明
首先在sqlite3.h中,在SQLITE_API char *sqlite3_vmprintf(int,char*,const char*, va_list);下,加上函数声明:
SQLITE_API int sqlite3_get_table_printf(
sqlite3*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
);
SQLITE_API int sqlite3_get_table_vprintf(
sqlite3*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string */
);
2. 在sqlite3.c中加上函数定义以及在有关结构中
1)在struct sqlite3_api_routines结构体中加上函数指针,可仿照sqlite3_vmprintf()函数写:
我们在整个结构体的最后来写,为了向后的兼容性,不至于函数填多了,太乱了
int (*get_table_vprintf)(sqlite3*,const char *,char ***,int *,int *,char **,va_list);
int (*get_table_printf)(sqlite3*,const char *,char ***,int *,int *,char **,...);
2)在SQLITE_CORE最后增加宏定义
#define sqlite3_get_table_vprintf sqlite3_api->get_table_vprintf
#define sqlite3_get_table_printf sqlite3_api->get_table_printf
3)在 static const sqlite3_api_routines sqlite3Apis定义的最后添加函数名
sqlite3_get_table_vprintf,
sqlite3_get_table_printf,
3. 添加函数实现
SQLITE_API int sqlite3_get_table_printf(
sqlite3 *db, /* An open database */
const char *zFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncol, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
){
va_list ap;
int rc;
va_start(ap, errmsg);
rc = sqlite3_get_table_vprintf(db, zFormat, resultp, nrow, ncol, errmsg, ap);
va_end(ap);
return rc;
}
SQLITE_API int sqlite3_get_table_vprintf(
sqlite3 *db, /* An open database */
const char *zFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string */
){
char *zSql;
int rc;
zSql = sqlite3_vmprintf(zFormat, ap);
rc = sqlite3_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
sqlite3_free(zSql);
return rc;
}
注意:在sqlite3_get_table_vprintf函数中有个free(zSql)要改成sqlite3_free(zSql);在sqlite2中,zSql由malloc来分配空间,而在sqlite 3中则不是。具体实现大家可以看函数实现。
4. 执行过程
把命令执行过程中所用到的sqlite3相关的库拷贝到/usr/lib下,数据库文件必须支持sqlite3格式的,如果是sqlite 2版本的话,可以使用 sqlite old.db .dump | sqlite3 new.db 命令来把2版本的数据库升级为3版本的数据库
可用如下程序测试sqlite3的sqlite3_get_table_printf接口函数:
int main (void)
{
struct sqlite3 *db_test;
int rc, nrow, ncol;
char *errmsg = NULL, **result = NULL;
rc = sqlite3_open("test.db", &db_test);
if(rc != SQLITE_OK)
{
printf("sqlite3 open error !\n");
}
rc = sqlite3_get_table_printf(db_test, "select * from %s", &result, &nrow, &ncol, &errmsg, "table_test");
if(rc != SQLITE_OK)
{
sqlite3_free_table(result);
printf("sqlite3 get table printf error!\n");
else
{
printf("result is %Q\n",result[0]);
}
sqlite3_close(db_test);
}
我们完全可以实现sqlite3_exec_printf()函数,附件中有我改好的sqlite3.c文件,支持sqlite3_get_table_printf和sqlite3_exec_printf()函数。