赞
踩
基于前面的博客分析和小组内成员的讨论,对数据库文件的打开过程做出分析与总结
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》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。