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));
  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;
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值