SQLite C 接口
操作系统接口对象
typedef struct sqlite3_vfs sqlite3_vfs; typedef void (*sqlite3_syscall_ptr)(void); struct sqlite3_vfs { int iVersion; /* Structure version number (currently 3) */ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); void (*xDlClose)(sqlite3_vfs*, void*); int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); int (*xSleep)(sqlite3_vfs*, int microseconds); int (*xCurrentTime)(sqlite3_vfs*, double*); int (*xGetLastError)(sqlite3_vfs*, int, char *); /* ** The methods above are in version 1 of the sqlite_vfs object ** definition. Those that follow are added in version 2 or later */ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); /* ** The methods above are in versions 1 and 2 of the sqlite_vfs object. ** Those below are for version 3 and greater. */ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in future versions. The iVersion ** value will increment whenever this happens. */ };
sqlite3_vfs 对象的实例定义了 SQLite 核心和底层操作系统之间的接口。对象名称中的“vfs”代表“虚拟文件系统”。有关详细信息,请参阅VFS 文档。
VFS 接口有时会通过在末尾添加新方法来扩展。每次发生这样的扩展时,iVersion 字段都会递增。iVersion 值在 2007-09-04 的 SQLite版本 3.5.0中开始为 1 ,然后在 2010-07-21 的 SQLite版本 3.7.0中增加到 2,然后在 2011 年的 SQLite版本 3.7.6中增加到 3 -04-12。附加字段可能会附加到 sqlite3_vfs 对象,并且 iVersion 值可能会在 SQLite 的未来版本中再次增加。请注意,由于疏忽,sqlite3_vfs 对象的结构在 2008 年 7 月 16 日从 SQLite 3.5.9版过渡到3.6.0版时发生了变化,但 iVersion 字段没有增加。
szOsFile 字段是 此 VFS 使用的子类sqlite3_file结构的大小。mxPathname 是此 VFS 中路径名的最大长度。
已注册的 sqlite3_vfs 对象保存在由 pNext 指针形成的链表中。sqlite3_vfs_register() 和sqlite3_vfs_unregister()接口以线程安全的方式管理这个列表。sqlite3_vfs_find()接口搜索列表。应用程序代码和 VFS 实现都不应该使用 pNext 指针。
pNext 字段是 SQLite 将永远修改的 sqlite3_vfs 结构中的唯一字段。SQLite 将仅在持有特定静态互斥锁时访问或修改此字段。对象注册后,应用程序永远不应修改 sqlite3_vfs 对象中的任何内容。
zName 字段包含 VFS 模块的名称。该名称在所有 VFS 模块中必须是唯一的。
SQLite 保证 xOpen 的 zFilename 参数是 NULL 指针或从 xFullPathname() 获得的字符串,并添加了可选的后缀。如果将后缀添加到 zFilename 参数,它将由一个“-”字符后跟不超过 11 个字母数字和/或“-”字符组成。SQLite 进一步保证在调用 xClose() 之前字符串有效且不变。由于前面的句子,如果出于某种原因需要记住文件名, sqlite3_file可以安全地存储指向文件名的指针。如果 xOpen 的 zFilename 参数是 NULL 指针,则 xOpen 必须为该文件创建自己的临时名称。.
xOpen() 的标志参数包括在sqlite3_open_v2()的标志参数中设置的所有位。或者,如果使用sqlite3_open() 或sqlite3_open16(),则标志至少包括 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE。如果 xOpen() 以只读方式打开文件,则它会将 *pOutFlags 设置为包含SQLITE_OPEN_READONLY。*pOutFlags 中的其他位可能会被设置。
SQLite 还会将以下标志之一添加到 xOpen() 调用中,具体取决于正在打开的对象:
- SQLITE_OPEN_MAIN_DB
- SQLITE_OPEN_MAIN_JOURNAL
- SQLITE_OPEN_TEMP_DB
- SQLITE_OPEN_TEMP_JOURNAL
- SQLITE_OPEN_TRANSIENT_DB
- SQLITE_OPEN_SUBJOURNAL
- SQLITE_OPEN_SUPER_JOURNAL
- SQLITE_OPEN_WAL
文件 I/O 实现可以使用对象类型标志来改变它处理文件的方式。例如,不关心崩溃恢复或回滚的应用程序可能会使打开日志文件成为空操作。写入该日志也将是空操作,任何读取该日志的尝试都将返回 SQLITE_IOERR。或者实现可能会识别出数据库文件将以随机顺序进行页面对齐的扇区读取和写入,并相应地设置其 I/O 子系统。
SQLite 还可能将以下标志之一添加到 xOpen 方法中:
SQLITE_OPEN_DELETEONCLOSE标志意味着文件在关闭时应该被删除。SQLITE_OPEN_DELETEONCLOSE将为 TEMP 数据库及其日志、临时数据库和子日志设置。
SQLITE_OPEN_EXCLUSIVE标志总是与 SQLITE_OPEN_CREATE 标志结合使用,它们都直接类似于 POSIX open() API 的 O_EXCL 和 O_CREAT 标志。SQLITE_OPEN_EXCLUSIVE 标志与 SQLITE_OPEN_CREATE 配对时,用于指示应始终创建文件,如果文件已经存在则为错误。它不用于指示文件应该以独占访问方式打开。
SQLite 至少分配了 szOsFile 字节的内存来保存作为第三个参数传递给 xOpen的sqlite3_file结构。xOpen 方法不必分配结构;它应该只是填写它。请注意,xOpen 方法必须将 sqlite3_file.pMethods 设置为有效的sqlite3_io_methods对象或 NULL。即使打开失败,xOpen 也必须这样做。SQLite 期望 sqlite3_file.pMethods 元素在 xOpen 返回后有效,而不管 xOpen 调用成功或失败。
xAccess() 的 flags 参数可以是SQLITE_ACCESS_EXISTS 来测试文件是否存在,或者是SQLITE_ACCESS_READWRITE来测试文件是否可读和可写,或者是SQLITE_ACCESS_READ 来测试文件是否至少可读。SQLITE_ACCESS_READ 标志从未实际使用过,也没有在 SQLite 的内置 VFS 中实现。该文件由第二个参数命名,可以是一个目录。xAccess 方法在成功时返回SQLITE_OK,如果出现 I/O 错误或第二个参数中给出的文件名非法,则返回一些非零错误代码。如果返回 SQLITE_OK,则将非零或零写入 *pResOut 以指示文件是否可访问。
SQLite 将始终为输出缓冲区 xFullPathname 分配至少 mxPathname+1 个字节。输出缓冲区的确切大小也作为参数传递给这两种方法。如果输出缓冲区不够大,则应返回SQLITE_CANTOPEN 。由于 SQLite 将此作为致命错误处理,因此 vfs 实现应努力通过将 mxPathname 设置为足够大的值来防止这种情况发生。
xRandomness()、xSleep()、xCurrentTime() 和 xCurrentTimeInt64() 接口严格来说并不是文件系统的一部分,但为了完整性,它们包含在 VFS 结构中。xRandomness() 函数尝试将 nBytes 字节的高质量随机性返回到 zOut。返回值是实际得到的随机字节数。xSleep() 方法使调用线程至少休眠指定的微秒数。xCurrentTime() 方法返回当前日期和时间的 Julian Day Number 作为浮点值。xCurrentTimeInt64() 方法以整数形式返回儒略日数乘以 86400000(一天 24 小时的毫秒数)。
SQLite 核心不使用 xSetSystemCall()、xGetSystemCall() 和 xNestSystemCall() 接口。这些可选接口由一些 VFS 提供,以方便测试 VFS 代码。通过用其控制下的功能覆盖系统调用,测试程序可以模拟故障和错误条件,否则很难或不可能诱发。可以覆盖的系统调用集因一个 VFS 而异,也因同一 VFS 的一个版本而异。使用这些接口的应用程序必须为任何或所有这些接口为 NULL 或它们的行为从一个版本更改为下一个版本做好准备。如果 VFS 的 iVersion 小于 3,应用程序不得尝试访问这些方法中的任何一个。