uri全称(Uniform ResourceIdentifiers)即统一资源标识标识符,这是按一定规则组织的用来定位到具体资源的名称,有点类似于网址,关于uri的资料可以参考以下2篇文档:
官方的uri说明
http://www.sqlite.org/uri.html
Uri详解之——Uri结构与代码提取
http://blog.youkuaiyun.com/harvic880925/article/details/44679239
uri的格式由scheme(协议)、域名( authority)、路径(path)、请求字符串(querystring)和 fragment组成,具体格式如下:
[scheme:][//authority][path][?query][#fragment]
在sqlite3中,scheme使用file,authority和path二个参数必须要有一个,authority目前只有localhost,一般可以忽略,当然也可以修改源代码来定义自己的域名。query为打开数据库连接时一些附加的请求操作,如vfs=demo,mode=ro等,多个请求可以用&连接,fragment目前用不到,如果名字中出现%HH,H指16进制数字,那么替换为对应的字符,如%20替换为空格,如下是uri文件格式的一些例子:
URI filenames | Results |
file:data.db | Open the file "data.db" in the current directory. |
file:/home/fred/data.db | Open the database file "/home/fred/data.db". |
file://darkstar/home/fred/data.db | An error. "darkstar" is not a recognized authority. |
file:///C:/Documents%20and%20Settings/fred/Desktop/data.db | Windows only: Open the file "data.db" on fred's desktop on drive C:. Note that the %20 escaping in this example is not strictly necessary - space characters can be used literally in URI filenames. |
file:data.db?mode=ro&cache=private | Open file "data.db" in the current directory for read-only access. Regardless of whether or not shared-cache mode is enabled by default, use a private cache. |
file:/home/fred/data.db?vfs=unix-dotfile | Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" that uses dot-files in place of posix advisory locking. |
file:data.db?mode=readonly | An error. "readonly" is not a valid option for the "mode" parameter. |
如果要使用uri来解析数据库文件名,需要调用 sqlite3_config(SQLITE_CONFIG_URI,1) 来使能uri解析,否则只按照普通的文件路径名来解析。
sqlite3是通过sqlite3ParseUri()函数来来解析uri名称的,以下这个条件来判断是否需要以uri格式来解析文件名
if( ((flags & SQLITE_OPEN_URI)
|| sqlite3GlobalConfig.bOpenUri)
&& nUri>=5 && memcmp(zUri, "file:", 5)==0
){
……
}
解析时遍历文件名字符
while( (c = zUri[iIn])!=0 && c!='#' ){
iIn++;
……
}
通过eState变量来表示解析状态机,eState的值可以是0、1、2,分别代表如下状态:
0:解析文件名
1:解析name=value请求参数中的name
2: 解析name=value请求参数中的value
在解析过程中,碰到?、=、&、#会替换成\0,解析完毕后,在结尾添加2个\0。这里为什么是2个呢,因为在之后解析query参数时,\0起到间隔的作用,再遇到一个\0表示解析结束。另外还有一些输入异常情况的处理,比如?vfs&mode=readonly,这里解析到&还没出现=,所以&会替换为2个\0,一个表示vfs为空,一个表示间隔,在这种情况下,出现2个\0并未解析结束,所以如果在eState=1时就结束了,需要在结尾添加3个\0,一个表示value为空,一个表示间隔,一个表示结尾,
if( eState==1 ) zFile[iOut++] = '\0';
zFile[iOut++] = '\0';
zFile[iOut++] = '\0';
如果是这样的输入?=win32&mode=readonly,因为不知道是什么请求操作,会直接跳过=win32,代码如下:
……
else if( eState==1 && (c=='&' || c=='=') ){
if( zFile[iOut-1]==0 ){
/* An empty option name. Ignore this option altogether. */
while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
continue;
}
……
解析query参数时,如果是vfs=,那么使用相应的vfs打开数据库,如果是cache=、mode=、那么将相应的参数输出给pFlags