Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]Add support for NODEFS #439

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ EMFLAGS = \
-s EXPORTED_RUNTIME_METHODS=@src/exported_runtime_methods.json \
-s SINGLE_FILE=0 \
-s NODEJS_CATCH_EXIT=0 \
-s NODEJS_CATCH_REJECTION=0
-s NODEJS_CATCH_REJECTION=0 \
-l nodefs.js

EMFLAGS_ASM = \
-s WASM=0
Expand Down
47 changes: 38 additions & 9 deletions src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,9 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
"number",
"number",
"number",
"number",
"number",
"number",
"number"



]
);
var sqlite3_value_type = cwrap("sqlite3_value_type", "number", ["number"]);
Expand Down Expand Up @@ -819,14 +818,21 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
* @memberof module:SqlJs
* Open a new database either by creating a new one or opening an existing
* one stored in the byte array passed in first argument
* @param {Array<number>} data An array of bytes representing
* @param {Array<number>|string} data An array of bytes representing,
* or a string for mapped file name
* an SQLite database file
*/
function Database(data) {
this.filename = "dbfile_" + (0xffffffff * Math.random() >>> 0);
if (data != null) {
FS.createDataFile("/", this.filename, data, true, true);
if (data != null && typeof data === "string") {
this.filename = data;
this.filetype = "FS";
} else {
this.filename = "dbfile_" + (0xffffffff * Math.random() >>> 0);
if (data != null) {
FS.createDataFile("/", this.filename, data, true, true);
}
}

this.handleError(sqlite3_open(this.filename, apiTemp));
this.db = getValue(apiTemp, "i32");
registerExtensionFunctions(this.db);
Expand Down Expand Up @@ -1113,7 +1119,9 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
Object.values(this.functions).forEach(removeFunction);
this.functions = {};
this.handleError(sqlite3_close_v2(this.db));
FS.unlink("/" + this.filename);
if (this.filetype !== "FS") {
FS.unlink("/" + this.filename);
}
this.db = null;
};

Expand Down Expand Up @@ -1250,6 +1258,27 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() {
return this;
};

var vfs = Module["FS"];

/** Create database instance
@param {string} vdir directory name to mount for virtual fs
@param {string} osdir system directory to mount
*/
Module["mount"] = function mount(vdir, osdir) {
if (vfs.mayCreate(vdir)) {
vfs.mkdir(vdir);
}
vfs.mount(vfs.filesystems["NODEFS"], { root: osdir }, vdir);
};

var mountpoints = Module["mountpoints"];
if (mountpoints) {
Array.prototype.forEach.call(Object.keys(mountpoints),
function mount(mp) {
Module["mount"](mp, mountpoints[mp]);
});
}

/** Register a custom aggregate with SQLite
@example <caption>Register a custom sum function</caption>
db.create_aggregate("js_sum", {
Expand Down
3 changes: 2 additions & 1 deletion src/exported_runtime_methods.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"stackAlloc",
"stackSave",
"stackRestore",
"UTF8ToString",
"FS",
"UTF8ToString"

"allocate",
"ALLOC_NORMAL",
Expand Down
35 changes: 35 additions & 0 deletions test/test_nodefs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
exports.test = function(SQL, assert) {
//Node filesystem module - You know that.
var fs = require('fs');

//Ditto, path module
var path = require('path');

SQL.mount('/nfs', __dirname);

//Works
var db = new SQL.Database('/nfs/test.sqlite');

//[{"columns":["id","content"],"values":[["0","hello"],["1","world"]]}]
var res = db.exec("SELECT * FROM test WHERE id = 0");
assert.deepEqual(res,
[{"columns":["id","content"],"values":[[0,"hello"]]}],
"One should be able to read the mounted file from disk");
db.close();
}

if (module == require.main) {
const target_file = process.argv[2];
const sql_loader = require('./load_sql_lib');
sql_loader(target_file).then((sql)=>{
require('test').run({
'test node file': function(assert){
exports.test(sql, assert);
}
});
})
.catch((e)=>{
console.error(e);
assert.fail(e);
});
}