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));
data.mode = MODE_List;
strcpy(data.separator,"|");
data.showHeader = 0;
while( argc>=2 && argv[1][0]=='-' ){ // 处理传入参数的处理 是否是html 是否为header
if( strcmp(argv[1],"-html")==0 ){
data.mode = MODE_Html;
argc--;
argv++;
}else if( strcmp(argv[1],"-list")==0 ){
data.mode = MODE_List;
argc--;
argv++;
}else if( strcmp(argv[1],"-line")==0 ){
data.mode = MODE_Line;
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 );
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) ){ // 检查是否是完成的字符串数据
data.cnt = 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;
}