SQLite剖析(3):C/C++接口介绍
发布时间:2020-12-13 00:05:46 所属栏目:百科 来源:网络整理
导读:本文整理自http://sqlite.com/cintro.html。 SQLite 3是SQLite一个全新的版本,它虽然是在SQLite 2的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和API。SQLite 3是为了满足以下的需求而开发的: * 支持UTF-16编码 * 用户自定义的文本比较方
本文整理自http://sqlite.com/cintro.html。
SQLite 3是SQLite一个全新的版本,它虽然是在SQLite 2的代码基础之上开发的,但是使用了和之前的版本不兼容的数据库格式和API。SQLite 3是为了满足以下的需求而开发的: * 支持UTF-16编码 * 用户自定义的文本比较方法 * 可以对BLOBs字段建立索引 由于对于C语言应该用什么数据类型来存放UTF-16编码的字符串并没有一致的规范,因此SQLite使用了普通的void*类型来指向UTF-16编码的字符串。 客户端使用过程中可以把void*映射成适合他们的系统的任何数据类型。 SQLite 3.X版的和2.X版的API非常相似,但是有一些重要的改变需要注意。3.X版的API增加到超过185个,所有API接口函数和数据结构的前缀都由"sqlite_"改为了"sqlite3_",这是为了避免同时使用SQLite 2.X和SQLite 3.X这两个版本的时候发生链接冲突。这里概要地介绍一下SQLite的核心API,详细的API指南参考http://sqlite.com/capi3ref.html。 一个SQL数据库引擎的首要任务是执行SQL语句以获得我们想要的数据。为了完成这个任务,开发需要知道两个对象:数据库连接对象sqlite3和SQL预处理语句对象sqlite3_stmt,定义如下: typedef struct sqlite3 sqlite3; typedef struct sqlite3_stmt sqlite3_stmt; 严格地说,SQL预处理语句对象不是必需的,因为有使用方便的包装函数sqlite3_exec或sqlite3_get_table,它们封装并且隐藏了SQL语句对象。不过理解SQL语句对象能更好地使用SQLite。 数据库连接对象和SQL语句对象由下面几个核心的C/C++接口来控制: sqlite3_open() sqlite3_prepare() sqlite3_step() sqlite3_column() sqlite3_finalize() sqlite3_close() 这六个C/C++接口及上面的两个对象构成SQLite的核心功能。注意这些接口有些有多个版本,例如sqlite3_open()有三个独立的版本,它们以稍微不同的方式完成同样的事情:sqlite3_open(),sqlite3_open16()和sqlite3_open_v2()。sqlite3_column()代表一个家族系列sqlite_column_int(),sqlite_column_blob()等等,用于提取结果集中各种类型的列数据。 1、打开和关闭数据库连接 int sqlite3_open( const char *filename,/* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); int sqlite3_open16( const void *filename,/* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); int sqlite3_open_v2( const char *filename,/* Database filename (UTF-8) */ sqlite3 **ppDb,/* OUT: SQLite db handle */ int flags,/* Flags */ const char *zVfs /* Name of VFS module to use */ ); int sqlite3_close(sqlite3*); int sqlite3_close_v2(sqlite3*); int sqlite3_errcode(sqlite3 *db); int sqlite3_extended_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); const void *sqlite3_errmsg16(sqlite3*);建立到一个SQLite数据库文件的连接,返回连接对象,如果数据库文件不存在,则创建这个文件,函数返回一个整数错误代码。许多SQLite接口需要一个指向连接对象的指针作为第一个参数,这个函数用来创建一个数据库连接对象。sqlite3_open()和sqlite3_open16()的不同之处在于sqlite3_open16()使用UTF-16编码(使用本地主机字节顺序)传递数据库文件名。如果要创建新数据库,sqlite3_open16()将内部文本转换为UTF-16编码,反之sqlite3_open()将文本转换为UTF-8编码。打开或者创建数据库的命令会被缓存,直到这个数据库真正被调用的时候才会被执行。而且允许使用PRAGMA声明来设置如本地文本编码或默认内存页面大小等选项和参数。 sqlite3_close()关闭数据库连接,在关闭之前所有准备好的SQL语句对象都要被销毁。 sqlite3_errcode()通常用来获取最近调用的API接口返回的错误代码。sqlite3_errmsg()则用来得到这些错误代码所对应的文字说明。这些错误信息将以UTF-8的编码返回,并且在下一次调用任何SQLiteAPI函数的时候被清除。sqlite3_errmsg16()和sqlite3_errmsg()大体上相同,除了返回的错误信息将以UTF-16本机字节顺序编码。 SQLite的返回码定义如下: #define SQLITE_OK 0 /* Successful result */ /* beginning-of-error-codes */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* Database is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */2、编译SQL语句 int sqlite3_prepare( sqlite3 *db,/* Database handle */ const char *zSql,/* SQL statement,UTF-8 encoded */ int nByte,/* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt,/* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_prepare_v2( sqlite3 *db,/* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_prepare16( sqlite3 *db,/* Database handle */ const void *zSql,UTF-16 encoded */ int nByte,/* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_prepare16_v2( sqlite3 *db,/* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ );把SQL文本编译成一个SQL语句对象并返回这个对象的指针。它只是把含有SQL语句的字符串编译成字节码,并不执行SQL语句。sqlite3_prepare()处理的SQL语句应该是UTF-8编码的,而sqlite3_prepare16()则要求是UTF-16编码的。输入的参数中只有第一个SQL语句会被编译。第四个参数则用来指向输入参数中下一个需要编译的SQL语句存放的SQLite statement对象的指针。任何时候如果调用sqlite3_finalize() 将销毁一个准备好的SQL声明。在数据库关闭之前,所有准备好的声明都必须被释放销毁。sqlite3_reset()函数用来重置一个SQL声明的状态,使得它可以被再次执行。注意现在sqlite3_prepare()已经不被推荐使用 了,在新的应用中推荐使用sqlite3_prepare_v2()。 3、执行SQL语句 int sqlite3_step(sqlite3_stmt*);在SQL声明准备好之后,就可以调用sqlite3_step()来执行这个SQL声明。如果SQL返回了一个单行结果集,sqlite3_step()函数将返回SQLITE_ROW,若要得到结果集的第二行、第三行,...,则要继续调用sqlite3_step()。如果SQL语句执行成功或者正常将返回SQLITE_DONE,否则将返回错误代码。如果不能打开数据库文件则会返回SQLITE_BUSY。 执行SQL语句还可以直接用便捷的包装函数,这样就无需预先编译SQL语句。如下: typedef int (*sqlite3_callback)(void*,int,char**,char**); int sqlite3_exec( sqlite3*,/* An open database */ const char *sql,/* SQL to be evaluated */ int (*callback)(void*,char**),/* Callback function */ void *,/* 1st argument to callback */ char **errmsg /* Error msg written here */ );sqlite3_exec函数依然像它在SQLite 2中一样承担着很多的工作。该函数的第二个参数中可以指定零个或多个SQL语句,查询的结果返回给回调函数,回调函数会作用在结果集的每条记录上。sqlite3_exec函数实际上封装了sqlite3_prepare_v2(),sqlite3_step()和sqlite3_finalize(),因此可以通过一个调用直接执行多条SQL语句,让应用程序省略大量代码,因此在实际应用中一般使用这个函数。 4、获取结果集数据 const void *sqlite3_column_blob(sqlite3_stmt*,int iCol); int sqlite3_column_bytes(sqlite3_stmt*,int iCol); int sqlite3_column_bytes16(sqlite3_stmt*,int iCol); const char *sqlite3_column_decltype(sqlite3_stmt *,int iCol); const void *sqlite3_column_decltype16(sqlite3_stmt *,int iCol); double sqlite3_column_double(sqlite3_stmt*,int iCol); int sqlite3_column_int(sqlite3_stmt*,int iCol); sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*,int iCol); const unsigned char *sqlite3_column_text(sqlite3_stmt*,int iCol); const void *sqlite3_column_text16(sqlite3_stmt*,int iCol); int sqlite3_column_type(sqlite3_stmt*,int iCol); sqlite3_value *sqlite3_column_value(sqlite3_stmt*,int iCol); const char *sqlite3_column_name(sqlite3_stmt*,int N); const void *sqlite3_column_name16(sqlite3_stmt*,int N); int sqlite3_column_count(sqlite3_stmt *pStmt); int sqlite3_data_count(sqlite3_stmt *pStmt);如果函数sqlite3_step()的返回值是SQLITE_ROW,那么上面的这些方法可以用来获得记录集行中的数据。 sqlite3_column_count()函数返回结果集中包含的列数. sqlite3_column_count()可以在执行了sqlite3_prepare()之后的任何时刻调用。sqlite3_data_count()除了必需要在sqlite3_step()之后调用之外,其他跟sqlite3_column_count()大同小异。如果调用sqlite3_step()返回值是SQLITE_DONE或者一个错误代码,则此时调用sqlite3_data_count()将返回0,然而sqlite3_column_count()仍然会返回结果集中包含的列数。 返回的记录集通过使用其它的几个sqlite3_column_***()函数来提取,所有的这些函数都把列的编号作为第二个参数。列编号从左到右以零起始。请注意它和之前那些从1起始的参数的不同。 sqlite3_column_type()函数返回第N列的值的数据类型,具体的返回值如下: define SQLITE_INTEGER 1 #define SQLITE_FLOAT 2 #define SQLITE_TEXT 3 #define SQLITE_BLOB 4 #define SQLITE_NULL 5sqlite3_column_decltype()则用来返回该列在CREATE TABLE语句中声明的类型。它可以用在当返回类型是空字符串的时候。sqlite3_column_name()返回第N列的字段名。sqlite3_column_bytes()用来返回UTF-8编码的BLOBs列的字节数或者TEXT字符串的字节数。sqlite3_column_bytes16()对于BLOBs列返回同样的结果,但是对于TEXT字符串则按 TF-16的编码来计算字节数。sqlite3_column_blob()返回BLOB数据。sqlite3_column_text()返回UTF-8编码的TEXT数据。sqlite3_column_text16()返回UTF-16编码的TEXT数据。sqlite3_column_int()以本地主机的整数格式返回一个整数值。sqlite3_column_int64()返回一个64位的整数。最后,sqlite3_column_double()返回浮点数。 不一定非要按照sqlite3_column_type()接口返回的数据类型来获取数据,数据类型不同时软件将自动转换。 5、SQL声明对象的销毁或重用 int sqlite3_finalize(sqlite3_stmt*); int sqlite3_reset(sqlite3_stmt*);函数sqlite3_finalize()销毁由sqlite3_prepare()创建的SQL声明对象。在数据库关闭之前每个准备好的声明都必须被销毁,以避免内存泄露。sqlite3_reset()则用来重置一个SQL声明的状态,使得它可以被再次执行。例如用sqlite3_step()执行完编译好的SQL声明后,还想再执行它,则可用sqlite3_reset()重置它即可,而无需用sqlite3_prepare()再来编译一个新SQL声明,因为很多SQL声明的编译时间甚至超过执行时间。 6、给SQL语句绑定参数 SQL语句声明中可以包含一些如下形式的参数: ? ?NNN :AAA $AAA @AAA 其中"NNN"是一个整数,"AAA" 是一个字符串,这些标记代表一些不确定的字符值(或者说是通配符)。在首次调用sqlite3_step()之前或者刚调用sqlite3_reset()之后,应用程序可以用sqlite3_bind接口来填充这些参数。每一个通配符都被分配了一个编号(由它在SQL声明中的位置决定,从1开始),此外也可以用 "NNN" 来表示 "?NNN" 这种情况。允许相同的通配符在同一个SQL声明中出现多次, 在这种情况下所有相同的通配符都会被替换成相同的值。没有被绑定的通配符将自动取NULL值。 int sqlite3_bind_blob(sqlite3_stmt*,const void*,int n,void(*)(void*)); int sqlite3_bind_double(sqlite3_stmt*,double); int sqlite3_bind_int(sqlite3_stmt*,int); int sqlite3_bind_int64(sqlite3_stmt*,sqlite3_int64); int sqlite3_bind_null(sqlite3_stmt*,int); int sqlite3_bind_text(sqlite3_stmt*,const char*,void(*)(void*)); int sqlite3_bind_text16(sqlite3_stmt*,void(*)(void*)); int sqlite3_bind_value(sqlite3_stmt*,const sqlite3_value*); int sqlite3_bind_zeroblob(sqlite3_stmt*,int n);以上是 sqlite3_bind所包含的全部接口,它们是用来给SQL声明中的通配符赋值的。没有绑定的通配符则被认为是空值。绑定上的值不会被sqlite3_reset()函数重置。但是在调用了sqlite3_reset()之后所有的通配符都可以被重新赋值。注意绑定操作是可选的。 7、扩展SQLite (1)创建自定义的比较序列: int sqlite3_create_collation( sqlite3*,const char *zName,int eTextRep,void *pArg,int(*xCompare)(void*,const void*) ); int sqlite3_create_collation_v2( sqlite3*,const void*),void(*xDestroy)(void*) ); int sqlite3_create_collation16( sqlite3*,const void *zName,const void*) ); int sqlite3_collation_needed( sqlite3*,void*,void(*)(void*,sqlite3*,const char*) ); int sqlite3_collation_needed16( sqlite3*,const void*) );这些函数在数据库连接上,为要比较的文本添加、删除或者修改自定义比较规则。第三个参数eTextRep表示SQLite支持的字符编码类型,必须以下常量之一: #define SQLITE_UTF8 1 #define SQLITE_UTF16LE 2 #define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* sqlite3_create_function only */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */sqlite3_create_collation()函数用来声明一个比较序列和实现它的比较函数,比较函数只能用来做文本的比较。同一个自定义的比较规则的同一个比较函数可以有UTF-8,UTF-16LE和UTF-16BE等多个编码的版本。sqlite3_create_collation16()和sqlite3_create_collation()的区别也仅仅在于比较名称的编码是UTF-16还是UTF-8。 可以使用sqlite3_collation_needed()函数来注册一个回调函数,当数据库引擎遇到未知的比较规则时会自动调用该函数。在回调函数中可以查找一个相似的比较函数,并激活相应的sqlite_3_create_collation()函数。回调函数的第四个参数是比较规则的名称。同样sqlite3_collation_needed采用UTF-8编码,sqlite3_collation_need16()采用UTF-16编码。 (2)创建自定义的SQL函数: int sqlite3_create_function( sqlite3 *db,const char *zFunctionName,int nArg,void *pApp,void (*xFunc)(sqlite3_context*,sqlite3_value**),void (*xStep)(sqlite3_context*,void (*xFinal)(sqlite3_context*) ); int sqlite3_create_function16( sqlite3 *db,const void *zFunctionName,void (*xFinal)(sqlite3_context*) ); int sqlite3_create_function_v2( sqlite3 *db,void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*) );nArg参数用来表明自定义函数的参数个数。如果参数值为0,则表示接受任意个数的参数。用eTextRep参数来表明传入参数的编码形式。SQLite 3允许同一个自定义函数有多种不同的编码参数的版本。数据库引擎会自动选择转换参数编码个数最少的版本使用。 普通的函数只需要设置xFunc参数,而把xStep和xFinal设为NULL。聚合函数则需要设置xStep和xFinal参数,然后把xFunc设为NULL。该方法和使用sqlite3_create_aggregate() API一样。 sqlite3_create_function16()和sqlite_create_function()的不同就在于自定义的函数名一个要求是UTF-16编码,而另一个则要求是UTF-8。 请注意自定函数的参数目前使用sqlite3_value结构体指针替代了SQLite version 2.X中的字符串指针。下面的函数用来从sqlite3_value结构体中提取数据,以获得SQL函数的参数值: const void *sqlite3_value_blob(sqlite3_value*); int sqlite3_value_bytes(sqlite3_value*); int sqlite3_value_bytes16(sqlite3_value*); double sqlite3_value_double(sqlite3_value*); int sqlite3_value_int(sqlite3_value*); sqlite3_int64 sqlite3_value_int64(sqlite3_value*); const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*);上面的函数调用以下的API来获得上下文内容和返回结果: void *sqlite3_aggregate_context(sqlite3_context*,int nBytes); void sqlite3_result_blob(sqlite3_context*,void(*)(void*)); void sqlite3_result_double(sqlite3_context*,double); void sqlite3_result_error(sqlite3_context*,int); void sqlite3_result_error16(sqlite3_context*,int); void sqlite3_result_error_toobig(sqlite3_context*); void sqlite3_result_error_nomem(sqlite3_context*); void sqlite3_result_error_code(sqlite3_context*,int); void sqlite3_result_int(sqlite3_context*,int); void sqlite3_result_int64(sqlite3_context*,sqlite3_int64); void sqlite3_result_null(sqlite3_context*); void sqlite3_result_text(sqlite3_context*,void(*)(void*)); void sqlite3_result_text16(sqlite3_context*,void(*)(void*)); void sqlite3_result_text16le(sqlite3_context*,void(*)(void*)); void sqlite3_result_text16be(sqlite3_context*,void(*)(void*)); void sqlite3_result_value(sqlite3_context*,sqlite3_value*); void sqlite3_result_zeroblob(sqlite3_context*,int n); void *sqlite3_user_data(sqlite3_context*); void *sqlite3_get_auxdata(sqlite3_context*,int N); void sqlite3_set_auxdata(sqlite3_context*,int N,void (*)(void*));(3)注册自定义的虚拟表模块 int sqlite3_create_module( sqlite3 *db,/* SQLite connection to register module with */ const char *zName,/* Name of the module */ const sqlite3_module *p,/* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); int sqlite3_create_module_v2( sqlite3 *db,/* Methods for the module */ void *pClientData,/* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ );其中第二个参数指定虚拟表模块名称,第三个参数指向虚拟表模块,第四个参数为传给虚拟表模块xCreate/xConnect方法的客户数据。sqlite3_create_module_v2()还有第五个参数,指定对pClientData数据进行析构的函数。若指定析构函数为NULL,则该函数与sqlite3_create_module()等价。 SQLite的所有内建SQL函数都使用上面这些接口来创建,可参考SQLite源代码,特别是date.c和func.c中的SQL函数代码。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |