| 2014年4月10日
在目前做的元数据节点中,为了保存一些节点的私有数据,选择了本地存储,在选择本地存储的选择上又选择了使用sqlite,sqlite对数据存储和数据解析在使用比较简单。而且编译入当前代码也是比较容易的。
Sqlite常使用的函数有下面几个。
sqlite3_open()
sqlite3_errcode(_sqlite)
sqlite3_errmsg()
sqlite3_get_table()
sqlite3_exec()
sqlite3_prepare()
sqlite3_step()
sqlite3_column()
sqlite3_finalize()
sqlite3_close()
sqlite3_open的接口定义如下:
int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
直接传入db文件的路径,和sqlite空对象指针,如果打开成功,sqlite则指向打开的sqlite对象,打开失败则指向NULL,打开成功返回值为SQLITE_OK,如果不为SQLITE_OK则可以调用函数sqlite3_errcode(_sqlite) 和sqlite3_errmsg()来获取打开失败原因。如下:
if (sqlite3_open(_db_name.c_str(), &_sqlite) != SQLITE_OK)
{
int errcode = sqlite3_errcode(_sqlite);
LOG(ERROR) << "opened " << _db_name << " ERROR("
<< errcode << "): " << sqlite3_errmsg(_sqlite);
return false;
}
关闭sqlite函数是sqlite3_close(),定义如下:
int sqlite3_close(sqlite3*);
sqlite3_get_table使用来查询结果,接口定义如下:
int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
zSql可以是多条sql语句,返回的结果放在pazResult中,以数组方式存放,官方文档的例子说明:
Name | Age
-----------------------
Alice | 43
Bob | 28
Cindy | 21
azResult[0] = "Name";
azResult[1] = "Age";
azResult[2] = "Alice";
azResult[3] = "43";
azResult[4] = "Bob";
azResult[5] = "28";
azResult[6] = "Cindy";
azResult[7] = "21";
这些内存都是在sqlite3_get_table内部查询时申请的,因此为了避免内存泄漏,使用完了之后需要释放掉,释放这样的内存函数:sqlite3_free_table,定义如下:
void sqlite3_free_table(char **result);
如果查询失败则在最后一个参数pzErrmsg中赋值错误原因,查询成功该值是NULL,当然这个字符串的内存也是在sqlite3_get_table内部申请的,释放这部分内存要是用sqlite3_free()函数,直接调用即可:
sqlite3_free(pzErrmsg);
std::string check_sql = boost::str(boost::format("select * from %s limit 1;") % tbname);
int ret = sqlite3_get_table(_sqlite, check_sql.c_str(), &result,
&num_rows, &num_cols, &errmsg);
if (ret != SQLITE_OK)
{
LOG(ERROR) << check_sql << " sqlite db:" << _sqlite << " ERROR: " << errmsg;
sqlite3_free(errmsg);
}
sqlite3_free_table(result);
return (SQLITE_OK == ret);
int ret = sqlite3_get_table(sqlite, sql.c_str(), &table, &num_rows, &num_cols, &errmsg);
if (ret != SQLITE_OK)
{
LOG(ERROR) << "sqlite sql[" << sql << "] ERROR: " << errmsg;
sqlite3_free(errmsg);
return false;
}
else
{
bool is_error = false;
for (int i=0; i<num_rows; ++i)
{
int field_no = 0;
int index = (i + 1) * num_cols;
char* total_file_num = table[index + field_no++];
char* total_file_size = table[index + field_no++];
try
{
_total_file_num = boost::lexical_cast<uint32_t>(total_file_num);
_total_file_size = boost::lexical_cast<uint64_t>(total_file_size);
}
catch (boost::bad_lexical_cast& ex)
。。。。。
sqlite3_exec()是也是用来执行sql语句: 一般用作更新操作,比如删除,更新,插入等sql的执行,调用起来也比较简单,这个函数是sqlite3_prepare_v2(), sqlite3_step(), and sqlite3_finalize()这几个函数的封装,一次性调用执行了上面几个函数。当然也可以用来做查询任务,使用其参数callback函数进行查询结果的处理。接口定义如下:
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
我在使用中一般使用该函数进行增删改sql。
bool CSqliteHelp::update(const std::string& sql)
{
char* errmsg = NULL;
int ret = sqlite3_exec(_sqlite, sql.c_str(), 0, 0, &errmsg);
if (ret != SQLITE_OK)
{
LOG(ERROR) << sql << " ERROR: " << errmsg;
sqlite3_free(errmsg);
return false;
}
return true;
}
```
sqlite3_prepare()也是一个执行查询sql的函数,查询结果在后面的代码可以使用sqlite3_step() 逐条取出使用,每次取结果集中的一行。
```c
nret = sqlite3_prepare(_sqlite, sql.c_str(), sql.size(), &stmt_tmp, &errmsg);
if(SQLITE_OK == nret)
{
*stmt = stmt_tmp;
}
else
{
LOG(ERROR) << sql << " ERROR: " << errmsg;
sqlite3_finalize(stmt_tmp);
}
........
while (sqlite3_step(stmt) == SQLITE_ROW)
{
bool ret = true;
uint64_t md5 = 0;
uint64_t size = 0;
std::string path = (const char*)sqlite3_column_text(stmt, 0);
.......
}
sqlite3_finalize(stmt);
取其中字段的函数如下,这些都是取对应的类型的函数,直接使用即可。
sqlite3_column_double
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_bytes16
sqlite3_column_text
sqlite3_column_text16
sqlite3_prepare使用的查询结果内存也是在内部申请的,在使用完之后就需要释放,释放使用sqlite3_finalize()函数: 跟多相关函数可以在这里查看: http://www.sqlite.org/c3ref/funclist.html
关注「黑光技术」,关注大数据+微服务