本文介绍UnQLite的基本使用,包括增删改查,事务ACID
文章目录
- UnQLite介绍
- UnQLite常用接口
- 函数
- 返回码
- Demo
- Key/Value存储
- 数据库游标
UnQLite介绍
- UnQLite简介
UnQLite是,由 Symisc Systems公司出品的一个嵌入式C语言软件库,它实现了一个自包含、无服务器、零配置、事务化的NoSQL数据库引擎。UnQLite是一个文档存储数据库,类似于MongoDB、Redis、CouchDB等。同时,也是一个标准的Key/Value存储,与BerkeleyDB和LevelDB等类似。
UnQLite是一个嵌入式NoSQL(键/值存储和文档存储)数据库引擎。不同于其他绝大多数NoSQL数据库,UnQLite没有一个独立的服务器进程。UnQLite直接读/写普通的磁盘文件。包含多个数据集的一个完整的数据库,存储在单一的磁盘文件中。数据库文件格式是跨平台的,可以在32位和64位系统或大端和小端架构之间,自由拷贝一个数据库。UnQLite的主要特点,如下:
`无服务器`数据库引擎。
`事务化` (ACID) 数据库。
`零配置`。
`单一数据库文件`,不使用临时文件。
`跨平台`的`文件格式`。
UnQLite是一个自包含的C语言程序库,`无任何外部依赖`。
标准的`Key/Value`存储。
基于`Jx9`的`文档存储`(JSON)数据库。
支持`游标`,满足线性记录遍历。
`插件式`运行时可交换存储引擎。
支持`磁盘持久化`和`内存模式`的数据库。
内建强大的磁盘存储引擎,支持`O(1)`查询。
`线程安全`,完全可重入。
简单、清晰,很容易使用的`API`。
支持`TB(Terabyte)尺寸`的数据库。
采用`BSD开源许可协议`。
合并:UnQLite和Jx9相关所有C源代码文件,都合并到`单一的文件中`。
很好的`在线支持`。
UnQLite常用接口
函数
/* Database Engine Handle */
UNQLITE_APIEXPORT int unqlite_open(unqlite **ppDB,const char *zFilename,unsigned int iMode);
UNQLITE_APIEXPORT int unqlite_config(unqlite *pDb,int nOp,...);
UNQLITE_APIEXPORT int unqlite_close(unqlite *pDb);
/* Key/Value (KV) Store Interfaces */
UNQLITE_APIEXPORT int unqlite_kv_store(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen);
UNQLITE_APIEXPORT int unqlite_kv_append(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen);
UNQLITE_APIEXPORT int unqlite_kv_store_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
UNQLITE_APIEXPORT int unqlite_kv_append_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...);
UNQLITE_APIEXPORT int unqlite_kv_fetch(unqlite *pDb,const void *pKey,int nKeyLen,void *pBuf,unqlite_int64 /* in|out */*pBufLen);
UNQLITE_APIEXPORT int unqlite_kv_fetch_callback(unqlite *pDb,const void *pKey,
int nKeyLen,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
UNQLITE_APIEXPORT int unqlite_kv_delete(unqlite *pDb,const void *pKey,int nKeyLen);
UNQLITE_APIEXPORT int unqlite_kv_config(unqlite *pDb,int iOp,...);
/* Document (JSON) Store Interfaces powered by the Jx9 Scripting Language */
UNQLITE_APIEXPORT int unqlite_compile(unqlite *pDb,const char *zJx9,int nByte,unqlite_vm **ppOut);
UNQLITE_APIEXPORT int unqlite_compile_file(unqlite *pDb,const char *zPath,unqlite_vm **ppOut);
UNQLITE_APIEXPORT int unqlite_vm_config(unqlite_vm *pVm,int iOp,...);
UNQLITE_APIEXPORT int unqlite_vm_exec(unqlite_vm *pVm);
UNQLITE_APIEXPORT int unqlite_vm_reset(unqlite_vm *pVm);
UNQLITE_APIEXPORT int unqlite_vm_release(unqlite_vm *pVm);
UNQLITE_APIEXPORT int unqlite_vm_dump(unqlite_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_extract_variable(unqlite_vm *pVm,const char *zVarname);
/* Cursor Iterator Interfaces */
UNQLITE_APIEXPORT int unqlite_kv_cursor_release(unqlite *pDb,unqlite_kv_cursor *pCur);
UNQLITE_APIEXPORT int unqlite_kv_cursor_seek(unqlite_kv_cursor *pCursor,const void *pKey,int nKeyLen,int iPos);
UNQLITE_APIEXPORT int unqlite_kv_cursor_first_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_last_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_valid_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_next_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_prev_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_key(unqlite_kv_cursor *pCursor,void *pBuf,int *pnByte);
UNQLITE_APIEXPORT int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
UNQLITE_APIEXPORT int unqlite_kv_cursor_data(unqlite_kv_cursor *pCursor,void *pBuf,unqlite_int64 *pnData);
UNQLITE_APIEXPORT int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);
UNQLITE_APIEXPORT int unqlite_kv_cursor_delete_entry(unqlite_kv_cursor *pCursor);
UNQLITE_APIEXPORT int unqlite_kv_cursor_reset(unqlite_kv_cursor *pCursor);
/* Manual Transaction Manager */
UNQLITE_APIEXPORT int unqlite_begin(unqlite *pDb);
UNQLITE_APIEXPORT int unqlite_commit(unqlite *pDb);
UNQLITE_APIEXPORT int unqlite_rollback(unqlite *pDb);
/* Utility interfaces */
UNQLITE_APIEXPORT int unqlite_util_load_mmaped_file(const char *zFile,void **ppMap,unqlite_int64 *pFileSize);
UNQLITE_APIEXPORT int unqlite_util_release_mmaped_file(void *pMap,unqlite_int64 iFileSize);
UNQLITE_APIEXPORT int unqlite_util_random_string(unqlite *pDb,char *zBuf,unsigned int buf_size);
UNQLITE_APIEXPORT unsigned int unqlite_util_random_num(unqlite *pDb);
/* In-process extending interfaces */
UNQLITE_APIEXPORT int unqlite_create_function(unqlite_vm *pVm,const char *zName,int (*xFunc)(unqlite_context *,int,unqlite_value **),void *pUserData);
UNQLITE_APIEXPORT int unqlite_delete_function(unqlite_vm *pVm, const char *zName);
UNQLITE_APIEXPORT int unqlite_create_constant(unqlite_vm *pVm,const char *zName,void (*xExpand)(unqlite_value *, void *),void *pUserData);
UNQLITE_APIEXPORT int unqlite_delete_constant(unqlite_vm *pVm, const char *zName);
/* On Demand Object allocation interfaces */
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_scalar(unqlite_vm *pVm);
UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_array(unqlite_vm *pVm);
UNQLITE_APIEXPORT int unqlite_vm_release_value(unqlite_vm *pVm,unqlite_value *pValue);
UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_scalar(unqlite_context *pCtx);
UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_array(unqlite_context *pCtx);
UNQLITE_APIEXPORT void unqlite_context_release_value(unqlite_context *pCtx,unqlite_value *pValue);
/* Dynamically Typed Value Object Management Interfaces */
UNQLITE_APIEXPORT int unqlite_value_int(unqlite_value *pVal, int iValue);
UNQLITE_APIEXPORT int unqlite_value_int64(unqlite_value *pVal, unqlite_int64 iValue);
UNQLITE_APIEXPORT int unqlite_value_bool(unqlite_value *pVal, int iBool);
UNQLITE_APIEXPORT int unqlite_value_null(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_double(unqlite_value *pVal, double Value);
UNQLITE_APIEXPORT int unqlite_value_string(unqlite_value *pVal, const char *zString, int nLen);
UNQLITE_APIEXPORT int unqlite_value_string_format(unqlite_value *pVal, const char *zFormat,...);
UNQLITE_APIEXPORT int unqlite_value_reset_string_cursor(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_resource(unqlite_value *pVal, void *pUserData);
UNQLITE_APIEXPORT int unqlite_value_release(unqlite_value *pVal);
/* Foreign Function Parameter Values */
UNQLITE_APIEXPORT int unqlite_value_to_int(unqlite_value *pValue);
UNQLITE_APIEXPORT int unqlite_value_to_bool(unqlite_value *pValue);
UNQLITE_APIEXPORT unqlite_int64 unqlite_value_to_int64(unqlite_value *pValue);
UNQLITE_APIEXPORT double unqlite_value_to_double(unqlite_value *pValue);
UNQLITE_APIEXPORT const char * unqlite_value_to_string(unqlite_value *pValue, int *pLen);
UNQLITE_APIEXPORT void * unqlite_value_to_resource(unqlite_value *pValue);
UNQLITE_APIEXPORT int unqlite_value_compare(unqlite_value *pLeft, unqlite_value *pRight, int bStrict);
/* Setting The Result Of A Foreign Function */
UNQLITE_APIEXPORT int unqlite_result_int(unqlite_context *pCtx, int iValue);
UNQLITE_APIEXPORT int unqlite_result_int64(unqlite_context *pCtx, unqlite_int64 iValue);
UNQLITE_APIEXPORT int unqlite_result_bool(unqlite_context *pCtx, int iBool);
UNQLITE_APIEXPORT int unqlite_result_double(unqlite_context *pCtx, double Value);
UNQLITE_APIEXPORT int unqlite_result_null(unqlite_context *pCtx);
UNQLITE_APIEXPORT int unqlite_result_string(unqlite_context *pCtx, const char *zString, int nLen);
UNQLITE_APIEXPORT int unqlite_result_string_format(unqlite_context *pCtx, const char *zFormat, ...);
UNQLITE_APIEXPORT int unqlite_result_value(unqlite_context *pCtx, unqlite_value *pValue);
UNQLITE_APIEXPORT int unqlite_result_resource(unqlite_context *pCtx, void *pUserData);
/* Dynamically Typed Value Object Query Interfaces */
UNQLITE_APIEXPORT int unqlite_value_is_int(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_float(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_bool(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_string(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_null(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_numeric(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_callable(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_scalar(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_json_array(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_json_object(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_resource(unqlite_value *pVal);
UNQLITE_APIEXPORT int unqlite_value_is_empty(unqlite_value *pVal);
/* JSON Array/Object Management Interfaces */
UNQLITE_APIEXPORT unqlite_value * unqlite_array_fetch(unqlite_value *pArray, const char *zKey, int nByte);
UNQLITE_APIEXPORT int unqlite_array_walk(unqlite_value *pArray, int (*xWalk)(unqlite_value *, unqlite_value *, void *), void *pUserData);
UNQLITE_APIEXPORT int unqlite_array_add_elem(unqlite_value *pArray, unqlite_value *pKey, unqlite_value *pValue);
UNQLITE_APIEXPORT int unqlite_array_add_strkey_elem(unqlite_value *pArray, const char *zKey, unqlite_value *pValue);
UNQLITE_APIEXPORT int unqlite_array_count(unqlite_value *pArray);
/* Call Context Handling Interfaces */
UNQLITE_APIEXPORT int unqlite_context_output(unqlite_context *pCtx, const char *zString, int nLen);
UNQLITE_APIEXPORT int unqlite_context_output_format(unqlite_context *pCtx,const char *zFormat, ...);
UNQLITE_APIEXPORT int unqlite_context_throw_error(unqlite_context *pCtx, int iErr, const char *zErr);
UNQLITE_APIEXPORT int unqlite_context_throw_error_format(unqlite_context *pCtx, int iErr, const char *zFormat, ...);
UNQLITE_APIEXPORT unsigned int unqlite_context_random_num(unqlite_context *pCtx);
UNQLITE_APIEXPORT int unqlite_context_random_string(unqlite_context *pCtx, char *zBuf, int nBuflen);
UNQLITE_APIEXPORT void * unqlite_context_user_data(unqlite_context *pCtx);
UNQLITE_APIEXPORT int unqlite_context_push_aux_data(unqlite_context *pCtx, void *pUserData);
UNQLITE_APIEXPORT void * unqlite_context_peek_aux_data(unqlite_context *pCtx);
UNQLITE_APIEXPORT unsigned int unqlite_context_result_buf_length(unqlite_context *pCtx);
UNQLITE_APIEXPORT const char * unqlite_function_name(unqlite_context *pCtx);
/* Call Context Memory Management Interfaces */
UNQLITE_APIEXPORT void * unqlite_context_alloc_chunk(unqlite_context *pCtx,unsigned int nByte,int ZeroChunk,int AutoRelease);
UNQLITE_APIEXPORT void * unqlite_context_realloc_chunk(unqlite_context *pCtx,void *pChunk,unsigned int nByte);
UNQLITE_APIEXPORT void unqlite_context_free_chunk(unqlite_context *pCtx,void *pChunk);
/* Global Library Management Interfaces */
UNQLITE_APIEXPORT int unqlite_lib_config(int nConfigOp,...);
UNQLITE_APIEXPORT int unqlite_lib_init(void);
UNQLITE_APIEXPORT int unqlite_lib_shutdown(void);
UNQLITE_APIEXPORT int unqlite_lib_is_threadsafe(void);
UNQLITE_APIEXPORT const char * unqlite_lib_version(void);
UNQLITE_APIEXPORT const char * unqlite_lib_signature(void);
UNQLITE_APIEXPORT const char * unqlite_lib_ident(void);
UNQLITE_APIEXPORT const char * unqlite_lib_copyright(void);
返回码
/* 标准UnQLite返回值 */
#define UNQLITE_OK /* Successful result */
/* 以下的都是错误码 */
#define UNQLITE_NOMEM /* Out of memory */
#define UNQLITE_ABORT /* Another thread have released this instance */
#define UNQLITE_IOERR /* IO error */
#define UNQLITE_CORRUPT /* Corrupt pointer */
#define UNQLITE_LOCKED /* Forbidden Operation */
#define UNQLITE_BUSY /* The database file is locked */
#define UNQLITE_DONE /* Operation done */
#define UNQLITE_PERM /* Permission error */
#define UNQLITE_NOTIMPLEMENTED /* Method not implemented by the underlying Key/Value storage engine */
#define UNQLITE_NOTFOUND /* No such record */
#define UNQLITE_NOOP /* No such method */
#define UNQLITE_INVALID /* Invalid parameter */
#define UNQLITE_EOF /* End Of Input */
#define UNQLITE_UNKNOWN /* Unknown configuration option */
#define UNQLITE_LIMIT /* Database limit reached */
#define UNQLITE_EXISTS /* Records exists */
#define UNQLITE_EMPTY /* Empty record */
#define UNQLITE_COMPILE_ERR /* Compilation error */
#define UNQLITE_VM_ERR /* Virtual machine error */
#define UNQLITE_FULL /* Full database (unlikely) */
#define UNQLITE_CANTOPEN /* Unable to open the database file */
#define UNQLITE_READ_ONLY /* Read only Key/Value storage engine */
#define UNQLITE_LOCKERR /* Locking protocol error */
Demo
参考文档:
- https://unqlite.github.io/2013/05/26/intro/,五分钟玩转UnQLite
- https://unqlite.github.io/archive/,存档
- https://unqlite.org/c_api_func.html,该目录查看每个接口函数的具体使用
Key/Value存储
涉及到事务ACID的操作,得用一个pDb handler,然后事务回滚。
对于KV操作,可以结合cJSON库,将需要存储的表记录(struct结构体定义的表结构)转换为json串,作为value。
#include <unqlite.h>
int i,rc;
unqlite *pDb;
// Open our database;
rc = unqlite_open(&pDb,"test.db",UNQLITE_OPEN_CREATE);
if( rc != UNQLITE_OK ){ return; }
// Store some records
rc = unqlite_kv_store(pDb,"test",-1,"Hello World",11); //test => 'Hello World'
if( rc != UNQLITE_OK ){
//Insertion fail, Hande error (See below)
return;
}
// A small formatted string
rc = unqlite_kv_store_fmt(pDb,"date",-1,"Current date: %d:%d:%d",2013,06,07);
if( rc != UNQLITE_OK ){
//Insertion fail, Hande error (See below)
return;
}
//Switch to the append interface
rc = unqlite_kv_append(pDb,"msg",-1,"Hello, ",7); //msg => 'Hello, '
if( rc == UNQLITE_OK ){
//The second chunk
rc = unqlite_kv_append(pDb,"msg",-1,"Current time is: ",17); //msg => 'Hello, Current time is: '
if( rc == UNQLITE_OK ){
//The last formatted chunk
rc = unqlite_kv_append_fmt(pDb,"msg",-1,"%d:%d:%d",10,16,53); //msg => 'Hello, Current time is: 10:16:53'
}
}
//Delete a record
unqlite_kv_delete(pDb,"test",-1);
//Store 20 random records.
for(i = 0 ; i < 20 ; ++i ){
char zKey[12]; //Random generated key
char zData[34]; //Dummy data
// generate the random key
unqlite_util_random_string(pDb,zKey,sizeof(zKey));
// Perform the insertion
rc = unqlite_kv_store(pDb,zKey,sizeof(zKey),zData,sizeof(zData));
if( rc != UNQLITE_OK ){
break;
}
}
if( rc != UNQLITE_OK ){
//Insertion fail, Handle error
const char *zBuf;
int iLen;
/* Something goes wrong, extract the database error log */
unqlite_config(pDb,UNQLITE_CONFIG_ERR_LOG,&zBuf,&iLen);
if( iLen > 0 ){
puts(zBuf);
}
if( rc != UNQLITE_BUSY && rc != UNQLITE_NOTIMPLEMENTED ){
/* Rollback */
unqlite_rollback(pDb);
}
}
//Auto-commit the transaction and close our handle.
unqlite_close(pDb);
数据库游标
游标提供了一种机制,通过它,你可以遍历整个数据库的记录。使用游标,你可以定位,提取,移动和删除数据库记录。
#include <unqlite.h>
int rc;
unqlite *pDb;
unqlite_kv_cursor *pCursor;
unqlite_int64 iData;
// Open our database;
rc = unqlite_open(&pDb,"test.db",UNQLITE_OPEN_CREATE);
if( rc != UNQLITE_OK ){ return; }
//Store some records unqlite_kv_store(), unqlite_kv_append()...
/* Allocate a new cursor instance */
rc = unqlite_kv_cursor_init(pDb,&pCursor);
if( rc != UNQLITE_OK ){ return; }
/* Point to the last record */
rc = unqlite_kv_cursor_last_entry(pCursor);
if( rc != UNQLITE_OK ){ return; }
/* Iterate over the records */
while( unqlite_kv_cursor_valid_entry(pCursor) ){
/* Consume the key */
printf("\nKey ==>\n\t");
unqlite_kv_cursor_key_callback(pCursor,DataConsumerCallback,0);
/* Extract data length */
unqlite_kv_cursor_data(pCursor,NULL,&iData);
printf("\nData length ==> %lld\n\t",iData);
/* Consume the data */
unqlite_kv_cursor_data_callback(pCursor,DataConsumerCallback,0);
/* Point to the previous record */
unqlite_kv_cursor_prev_entry(pCursor);
}
/* Finally, Release our cursor */
unqlite_kv_cursor_release(pDb,pCursor);
//Auto-commit the transaction and close our handle
unqlite_close(pDb);