2021SC@SDUSC SQLite源码分析(十二)————SQLite 数据库文件打开过程

2021SC@SDUSC SQLite源码分析(十二)————SQLite 数据库文件打开过程


前言

基于前面的博客分析和小组内成员的讨论,对数据库文件的打开过程做出分析与总结


过程分析

官方文档中的过程介绍

在这里插入图片描述

逐步分析

1、
main():
位于 shell.c
从命令行参数中得到数据库名,如果数据库文件存在,则打开它。
2、
open_db():
位于 shell.c
功能:确认数据库是否已经打开。如果已打开,则什么都不做。如果没有,则打开它。如果打开失败,输出一个错误信息。
3、
sqlite3_open():
位于 main.c。
功能:打开一个数据库。
该函数中只包含对 opendatabase()的调用,但调用的参数与sqlite3_open_v2()所使用的参数不同。
4、
opendatabase():
位于 main.c。
功能:这个函数为 sqlite3_open()和 sqlite3_open16()工作,打开一个数据库。数据库文件名
"zFilename"采用 UTF-8 编码。
先生成各类标志,然后生成默认的排序法。当需要生成数据库后台驱动时,调用sqlite3BtreeFactory()。
在此函数中真正分配 sqlite 结构的空间:db=sqlite3MallocZero(sizeof(sqlite3) )。
在调用 sqlite3BtreeFactory()之前,需要对 db 的一些域进行设置。

部分源码:

static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb,        /* OUT: Returned database handle */
  unsigned int flags,    /* Operational flags */
  const char *zVfs       /* Name of the VFS to use */
){
  sqlite3 *db;                    /* Store allocated handle here */
  int rc;                         /* Return code */
  int isThreadsafe;               /* True for threadsafe connections */
  char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
  char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */
  int i;                          /* Loop counter */
#ifdef SQLITE_ENABLE_API_ARMOR
  if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
#endif
  *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
  if( rc ) return rc;
#endif

  if( sqlite3GlobalConfig.bCoreMutex==0 ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_NOMUTEX ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_FULLMUTEX ){
    isThreadsafe = 1;
  }else{
    isThreadsafe = sqlite3GlobalConfig.bFullMutex;
  }

  if( flags & SQLITE_OPEN_PRIVATECACHE ){
    flags &= ~SQLITE_OPEN_SHAREDCACHE;
  }else if( sqlite3GlobalConfig.sharedCacheEnabled ){
    flags |= SQLITE_OPEN_SHAREDCACHE;
  }
   /* Allocate the sqlite data structure */
  db = sqlite3MallocZero( sizeof(sqlite3) );
  if( db==0 ) goto opendb_out;
  if( isThreadsafe 
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
   || sqlite3GlobalConfig.bCoreMutex
#endif
  ){
    db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
    if( db->mutex==0 ){
      sqlite3_free(db);
      db = 0;
      goto opendb_out;
    }
    if( isThreadsafe==0 ){
      sqlite3MutexWarnOnContention(db->mutex);
    }
  }
  sqlite3_mutex_enter(db->mutex);
  db->errMask = 0xff;
  db->nDb = 2;
  db->magic = SQLITE_MAGIC_BUSY;
  db->aDb = db->aDbStatic;
  db->lookaside.bDisable = 1;
  db->lookaside.sz = 0;

  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
  db->autoCommit = 1;
  db->nextAutovac = -1;
  db->szMmap = sqlite3GlobalConfig.szMmap;
  db->nextPagesize = 0;
  db->nMaxSorterMmap = 0x7FFFFFFF;
  db->flags |= SQLITE_ShortColNames
                 | SQLITE_EnableTrigger
                 | SQLITE_EnableView
                 | SQLITE_CacheSpill
#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0
                 | SQLITE_TrustedSchema
#endif

5、
sqlite3BtreeFactory()
位于 main.c。
功能:本函数创建到数据库 BTree 驱动的连接。如果 zFilename 是文件名,则打开并使用它。
如果 zFilename 是":memory:",则使用内存数据库(在连接断开时释放)。
如果 zFilename 为空且数据库是虚拟(virtual)的,则只是暂时使用,在连接断开时被删除。
虚拟数据库可以是磁盘文件或就在内存中,由 sqlite3TempInMemory()函数来决定是哪一种
情况。
6、
sqlite3BtreeOpen():
位于 btree.c。
功能:打开一个数据库文件。
由于在 sqlite3BtreeFactory()中已经调用过 sqlite3TempInMemory()函数,所以此处逻辑稍简单
了一些。
zFilename 是数据库文件名。如果 zFilename 为空,创建一个具有随机文件名的数据库,这
个数据库会在调用 sqlite3BtreeClose()时被删除。
如果 zFilename 是":memory:",创建内存数据库,并在关闭时被释放。
如果此 Btree 是共享缓冲区的候选者,则尝试寻找一个已存在的 BtShared 来共享。
如果不是共享缓冲区的候选者或未找到已存在的BtShared,则调用 sqlite3PagerOpen()函数打
开文件。
文件打开之后,调用 sqlite3PagerReadFileheader()来读文件头中的配置信息。
7、
sqlite3PagerOpen():
位于 pager.c。
功能:分配并初始化一个新 Pager 对象,将其指针放到*ppPager。

该 pager 会在调用 sqlite3PagerClose()时被释放。
zFilename 参数是要打开的数据库文件的路径。
如果 zFilename 为空,创建随机文件名的文件。
如果 pager 对象已分配且指定文件打开成功,返回 SQLITE_OK 并将*ppPager 指向新 pager
对象。
如果有错误发生,*ppPager 置空并返回错误代码。
执行过程是:先申请空间,再调用 sqlite3OsOpen()打开文件(如果需要),再根据打开的文
件设置内存。
8、
sqlite3OsOpen():
位于 os.c。
功能:打开一个文件,与具体的操作系统无关。
是一种 VFS 封装。VFS : “virtual file system”,虚拟文件系统。
本函数只有几条语句,只有一条关键语句:
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut);
对于 Win32 操作系统,该语句实际调用的是 winOpen()函数。

int sqlite3OsOpen(
  sqlite3_vfs *pVfs,
  const char *zPath,
  sqlite3_file *pFile,
  int flags,
  int *pFlagsOut
){
  int rc;
  DO_OS_MALLOC_TEST(0);
  /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}

9、
winOpen():
位于 os_win.c。
功能:打开一个 Windows 操作系统文件。
先将文件名转换为操作系统所使用的编码。再设置一系列参数。
最终调用操作系统函数 CreateFileA()打开文件。
10、
CreateFileA():
位于 WINBASE.H。
功能:
打开文件名所指定的文件。如果文件不存在,则创建。

参考资料:《Inside SQLite》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值