Sequelize.js + SQLite路径中包含空格的问题

最近项目中尝试使用 sequelize.js + SQLite 的组合记录信息,遇到一个问题:如果 sqlite 路径中存在空格,sequelize.js 无法找到数据库文件。本文记录一下排查过程以及处理方案。

相关依赖如下:

"sequelize": "^4.19.0",
"sqlite3": "^3.1.13",

一开始,数据库连接操作是这样写的(已去掉无关项):

this.sequelize = new Sequelize(`sqlite:${path}`, {
    dialect: 'sqlite'
});

path 的值类似 /Users/wu/tmp/mydata.db,一切正常。

后来,无意中使用了一个路径中带有空格的文件地址,例如 /Users/wu/tmp/a b/mydata.db(注意其中的 a b 中间有个空格),便出现了如下错误:

Unhandled rejection SequelizeConnectionError: SQLITE_CANTOPEN: unable to open database file
    at Database.connections.(anonymous function).lib.Database.err (/Users/wu/.../node_modules/sequelize/lib/dialects/sqlite/connection-manager.js:67:63)

提示找不到 database 文件。

Google 搜索一番没找到结果,于是打开 connection-manager.js,添加日志打印,发现访问的文件地址为:

'/Users/wu/tmp/a%20b/mydata.db' 

可以看到,路径 a b 中的空格被编码为 %20 了,按这个路径去查找,当然会找不到文件。进一步分析,可以发现在 sequelize.js 初始化时,就使用了 url.parse 方法将传入的参数进行了编码:

const urlParts = url.parse(arguments[0]);

知道问题成因了,如何处理呢?

首先想到的是在使用这个文件地址之前,再将它解码回去。但这需要修改 sequelize.js 的源码,将来升级、部署都会比较麻烦。

继续阅读 sequelize.js,注意到其第 119 行开始有以下内容:

if (options.dialect === 'sqlite' && urlParts.pathname && urlParts.pathname.indexOf('/:memory') !== 0) {
    const path = Path.join(options.host, urlParts.pathname);
    options.storage = options.storage || path;
}

也就是说,使用 SQLite 时,如果传入了 storage 参数,那么最终使用的路径以这个为准。

于是,这个问题的解答就简单了,将路径通过 storage 参数传入即可。比如:

this.sequelize = new Sequelize(`sqlite:${path}`, {
    dialect: 'sqlite',
    storage: path // <-- 在这儿指定文件路径
});

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s