sqlite-1.0.0源码执⾏的基本流程概述
sqlite-1.0.0原理概述
sqlite是⼀款嵌⼊式的轻量级的数据库,⾸个版本诞⽣于2000年,该数据库遵守ACID的关系数据库管理系统,SQLite不是⼀个cs架构的数据库引擎,⽽是被集成在⽤户程序中,SQLite实现了⼤部分的SQL标准。本⽂主要概述sqlite-1.0.0版本的启动的简单流程。
sqlite-1.0.0的源码
sqlite源码⽬录
主要包括了源码⽬录src,vdbe.c中主要包括了sqlite虚拟机的执⾏过程,where.c解析where语法的过程,shell.c主要是终端交互的过程中来获取输⼊并解析执⾏sql语句,insert.c主要就是插⼊数据的解析;在tool中的lemon的分析⼯具等。
sqlite的基本解析过程
⼀条sql的执⾏的主要过程如下:
在sqlite-1.0.0的实现过程中,使⽤了gdbm来做底层的数据存储与管理,sqlite的整个的实现流程,先是输⼊的语法词法解析,然后通过⽣成的语法⽣成相应的sql的虚拟机的执⾏指令,最后再执⾏该虚拟机指令,最终虚拟机指令通过gdbm来操作数据。
sqlite-1.0.0的源码的执⾏过程
通过在终端中输⼊sqlite执⾏,执⾏的⼊⼝函数为shell.c中的main函数;
int main(int argc, char **argv){
sqlite *db;
char *zErrMsg = 0;
char *argv0 = argv[0];
struct callback_data data;
memset(&data, 0, sizeof(data));
strcpy(data.separator,"|");
data.showHeader = 0;
while( argc>=2 && argv[1][0]=='-' ){ // 处理传⼊参数的处理是否是html 是否为header
if( strcmp(argv[1],"-html")==0 ){
argc--;
argv++;
}else if( strcmp(argv[1],"-list")==0 ){
argc--;
argc--;
argv++;
}else if( strcmp(argv[1],"-line")==0 ){
argc--;
argv++;
}else if( argc>=3 && strcmp(argv[0],"-separator")==0 ){
sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[2]);
argc -= 2;
argv += 2;
}else if( strcmp(argv[1],"-header")==0 ){
data.showHeader = 1;
argc--;
argv++;
}else if( strcmp(argv[1],"-noheader")==0 ){
data.showHeader = 0;
argc--;
argv++;
}else{
fprintf(stderr,"%s: unknown option: %s\n", argv0, argv[1]);
return 1;
}
}
if( argc!=2 && argc!=3 ){
fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
exit(1);
}
data.db = db = sqlite_open(argv[1], 0666, &zErrMsg); // 打开⽂件
if( db==0 ){
data.db = db = sqlite_open(argv[1], 0444, &zErrMsg); // 如果打不开就换个模式打开 if( db==0 ){
if( zErrMsg ){ // 出错信息
fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1],zErrMsg);
}else{
fprintf(stderr,"Unable to open database %s\n", argv[1]);
}
exit(1);
}else{
printf("Database \"%s\" opened READ ONLY!\n", argv[1]);
}
}
data.out = stdout; // 输出信息
if( argc==3 ){ // 三个输⼊参数第三个参数为sql语句
if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
fprintf(stderr,"SQL error: %s\n", zErrMsg);
exit(1);
}
}else{ // 打开sql的交互界⾯
char *zLine;
char *zSql = 0;
int nSql = 0;
int istty = isatty(0);
if( istty ){
printf(
"Enter \".help\" for instructions\n"
);
}
while( (zLine = one_input_line(zSql, istty))!=0 ){ // 读取终端命令⾏的输⼊数据
if( zLine && zLine[0]=='.' ){
do_meta_command(zLine, db, &data); // 展⽰元数据信息
free(zLine);
continue;
}
if( zSql==0 ){
nSql = strlen(zLine);
zSql = malloc( nSql+1 );
zSql = malloc( nSql+1 );
strcpy(zSql, zLine);
}else{
int len = strlen(zLine); // 获取输⼊的长度
zSql = realloc( zSql, nSql + len + 2 ); // 重新增加内存
if( zSql==0 ){
fprintf(stderr,"%s: out of memory!\n", argv0); // 如果申请内存失败则报错
exit(1);
}
strcpy(&zSql[nSql++], "\n"); // 给字符串数组加\n
strcpy(&zSql[nSql], zLine); // 拷贝获取的字符串数据
nSql += len;
}
free(zLine);
if( sqlite_complete(zSql) ){ // 检查是否是完成的字符串数据
datat = 0;
if( sqlite_exec(db, zSql, callback, &data, &zErrMsg)!=0 // 执⾏该sql语句并设置回调显⽰函数callback
&& zErrMsg!=0 ){
printf("SQL error: %s\n", zErrMsg); // 如果出错则报错
free(zErrMsg);
zErrMsg = 0;
}
free(zSql); // 释放内存
zSql = 0;
nSql = 0;
}
} // 等待下⼀条数据输⼊
}
sqlite_close(db); // 关闭该数据库
return 0;
}
该main函数主要就是处理输⼊的命令⾏参数,并循环处理传⼊的终端的命令⾏的sql语句。接着我们就继续分析sqlit_exec函数的执⾏过程;
/*
** Execute SQL code. Return one of the SQLITE_ success/failure
** codes. Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**
** If the SQL is a query, then for each row in the query result
** the xCallback() function is called. pArg becomes the first
** argument to xCallback(). If xCallback=NULL then no callback
** is invoked, even for queries.
*/
int sqlite_exec(
sqlite *db, /* The database on which the SQL executes */
char *zSql, /* The SQL to be executed */
sqlite_callback xCallback, /* Invoke this callback routine */
void *pArg, /* First argument to xCallback() */
char **pzErrMsg /* Write error messages here */
){
Parse sParse; // 解析的保存的数据结构
int rc;
if( pzErrMsg ) *pzErrMsg = 0;
if( (db->flags & SQLITE_Initialized)==0 ){
int rc = sqliteInit(db, pzErrMsg); // 检查是否数据库初始化完成如果未初始化完成则报错返回
if( rc!=SQLITE_OK ) return rc;
}
memset(&sParse, 0, sizeof(sParse)); // 变量的内容指向的地址设置为空
sParse.db = db; // 设置数据库
sParse.xCallback = xCallback; // 设置回调函数
sParse.pArg = pArg; // 设置传⼊参数
rc = sqliteRunParser(&sParse, zSql, pzErrMsg); // 开始解析并执⾏
sqliteStrRealloc(pzErrMsg);
return rc;
}
主要就是进⾏了检查并设置了相关的参数进⾏配置,接着就执⾏了sqliteRunParser函数来执⾏;
int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){
int nErr = 0;
int i;
void *pEngine;
int once = 1;
static FILE *trace = 0;
extern void *sqliteParserAlloc(void*(*)(int)); // 该函数就是通过lemon来⽣成的函数
extern void sqliteParserFree(void*, void(*)(void*));
extern int sqliteParser(void*, int, ...); // 调⽤lemon定义的语法解析的函数,传⼊token来解析 extern void sqliteParserTrace(FILE*, char *);
i = 0;
continue语句执行过程sqliteParseInfoReset(pParse);
pEngine = sqliteParserAlloc((void*(*)(int))malloc);
if( pEngine==0 ){
sqliteSetString(pzErrMsg, "out of memory", 0);
return 1;
}
sqliteParserTrace(trace, "parser: "); // 设置追踪
while( nErr==0 && i>=0 && zSql[i]!=0 ){ // 循环遍历数据
int tokenType;
pParse->sLastToken.z = &zSql[i];
pParse->sLastToken.n = sqliteGetToken(&zSql[i], &tokenType); // 解析传⼊的数据获取token
i += pParse->sLastToken.n;
if( once ){
pParse->sFirstToken = pParse->sLastToken;
once = 0;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论