Sqlite学习笔记(11)-API(2)
2015-08-25 17:16
183 查看
2.2.3 执行Prepared Query
前面提到,预处理查询(Prepared Query)是SQLite执行所有SQL命令的方式,包括以下三个过程:
(1)Preparation
分析器(parser),分词器(tokenizer)和代码生成器(code generator)把SQL Statement编译成VDBE字节码,编译器会创建一个statement句柄(sqlite3_stmt),它包括字节码以及其它执行命令和遍历结果集的所有资源。
相应的C API为sqlite3_prepare_v2(),位于prepare.c文件中,如下:
(2) Execution
VDBE执行字节码,执行过程是一个步进(stepwise)的过程,每一步(step)由sqlite3_step()启动,并由VDBE执行一段字节码。在遍历结果集的过程中,它返回SQLITE_ROW,当到达结果末尾时,返回SQLITE_DONE。
相应的C API为sqlite3_step(),位于Vdbeapi.c文件中,如下:
(3)Finalization
VDBE关闭statement,释放资源。
相应的C API为sqlite3_finalize(),位于Vdbeapi.c文件中,如下:
这三步-preparation, execution, finalization-分别代表不同的statement句柄状态- prepared, active, or finalized。图2.3显示了这些步骤和状态。
下边我们可以用一段伪代码展示一下执行过程,代码如下:
图2.3 语句执行过程
2.2.4 执行Wrapped Query
前边已经提到过,wrapped query只是对prepared query的三个过程封装而已。Wrapped query包括二个函数,sqlite3_exec()以及sqlite3_get_table()。这两个函数都可用于查询,不过sqlite3_exec()主要用于不返回数据的查询,而sqlite3_get_table()则相反。其中sqlite3_exec()位于Legacy.c,而sqlite3_get_table()位于table.c。
前面提到,预处理查询(Prepared Query)是SQLite执行所有SQL命令的方式,包括以下三个过程:
(1)Preparation
分析器(parser),分词器(tokenizer)和代码生成器(code generator)把SQL Statement编译成VDBE字节码,编译器会创建一个statement句柄(sqlite3_stmt),它包括字节码以及其它执行命令和遍历结果集的所有资源。
相应的C API为sqlite3_prepare_v2(),位于prepare.c文件中,如下:
int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; }
(2) Execution
VDBE执行字节码,执行过程是一个步进(stepwise)的过程,每一步(step)由sqlite3_step()启动,并由VDBE执行一段字节码。在遍历结果集的过程中,它返回SQLITE_ROW,当到达结果末尾时,返回SQLITE_DONE。
相应的C API为sqlite3_step(),位于Vdbeapi.c文件中,如下:
int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ int cnt = 0; /* Counter to prevent infinite loop of reprepares */ sqlite3 *db; /* The database connection */ if( vdbeSafetyNotNull(v) ){ return SQLITE_MISUSE_BKPT; } db = v->db; sqlite3_mutex_enter(db->mutex); v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ int savedPc = v->pc; rc2 = rc = sqlite3Reprepare(v); if( rc!=SQLITE_OK) break; sqlite3_reset(pStmt); if( savedPc>=0 ) v->doingRerun = 1; assert( v->expired==0 ); } if( rc2!=SQLITE_OK ){ const char *zErr = (const char *)sqlite3_value_text(db->pErr); sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); v->rc = rc2; } else { v->zErrMsg = 0; v->rc = rc = SQLITE_NOMEM; } } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; }
(3)Finalization
VDBE关闭statement,释放资源。
相应的C API为sqlite3_finalize(),位于Vdbeapi.c文件中,如下:
int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); } return rc; }
这三步-preparation, execution, finalization-分别代表不同的statement句柄状态- prepared, active, or finalized。图2.3显示了这些步骤和状态。
下边我们可以用一段伪代码展示一下执行过程,代码如下:
# 1. Open the database, create a connection object (db) db = open('foods.db') # 2.A. Prepare a statement stmt = db.prepare('select * from episodes') # 2.B. Execute. Call step() is until cursor reaches end of result set. while stmt.step() == SQLITE_ROW print stmt.column('name') end # 2.C. Finalize. Release read lock. stmt.finalize() # 3. Insert a record stmt = db.prepare('INSERT INTO foods VALUES (…)') stmt.step() stmt.finalize() # 4. Close database connection. db.close()
图2.3 语句执行过程
2.2.4 执行Wrapped Query
前边已经提到过,wrapped query只是对prepared query的三个过程封装而已。Wrapped query包括二个函数,sqlite3_exec()以及sqlite3_get_table()。这两个函数都可用于查询,不过sqlite3_exec()主要用于不返回数据的查询,而sqlite3_get_table()则相反。其中sqlite3_exec()位于Legacy.c,而sqlite3_get_table()位于table.c。
相关文章推荐
- Sqlite学习笔记(10)-API(1)
- 安装二进制软件包的mysql出现 error while loading shared libraries: libaio.so.1:
- Redis 持久化数据方式 RDB AOF
- SQLite3查询表结构
- 数据库事物隔离级别通俗理解
- SQLite3查询表结构
- [mysql] 分区介绍
- 高级sql 分组汇总
- Memcached之stats命令(3)
- Oracle利用数据伪列实现分页功能
- MyBatis学习 之 三、动态SQL语句
- 安装oracle11g rac,报错must be configured to display at least 256
- MyBatis学习 之 二、SQL语句映射文件(2)增删改查、参数、缓存
- LINUX 使用DBCA创建ORACLE数据库
- MyBatis学习 之 二、SQL语句映射文件(1)resultMap
- Linux_oracle命令大全(转)
- UBUNTU如何改变mysql默认文件夹数据文件夹
- Oracle分组查询
- JDBC连接数据库
- java开发中JDBC连接MySQL数据库代码