From 0a783474bcfe1bb01defc5627688c30147f7631d Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Mon, 1 Mar 2021 11:48:03 +0800 Subject: [PATCH 1/7] add nodefs to makefile --- Makefile | 3 ++- src/api.js | 18 ++++++++++++++++++ src/exported_runtime_methods.json | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 287de6fd..54e0b411 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,8 @@ EMFLAGS = \ -s EXTRA_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 diff --git a/src/api.js b/src/api.js index 52bbab58..1b523ab6 100644 --- a/src/api.js +++ b/src/api.js @@ -800,6 +800,24 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { this.functions = {}; } + /** Create database instance + @param {string} fn filename for database file + @return {Database} the created database instance + */ + Database.open = function(fn) { + var obj = Object.create(Database.prototype); + obj.filename = fn; + obj.handleError(sqlite3_open(obj.filename, apiTemp)); + obj.db = getValue(apiTemp, "i32"); + registerExtensionFunctions(obj.db); + // A list of all prepared statements of the database + obj.statements = {}; + // A list of all user function of the database + // (created by create_function call) + obj.functions = {}; + return obj; + } + /** Execute an SQL query, ignoring the rows it returns. @param {string} sql a string containing some SQL text to execute @param {Statement.BindParams} [params] When the SQL statement contains diff --git a/src/exported_runtime_methods.json b/src/exported_runtime_methods.json index 13a8efb8..7a4dde89 100644 --- a/src/exported_runtime_methods.json +++ b/src/exported_runtime_methods.json @@ -3,5 +3,7 @@ "stackAlloc", "stackSave", "stackRestore", +"FS", +"NODEFS", "UTF8ToString" ] From e75de39dcb3d03aebb8bca0c24f4c4a186c94f4e Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Mon, 1 Mar 2021 14:38:14 +0800 Subject: [PATCH 2/7] fix for closure compiler --- src/api.js | 15 ++++++++++++++- src/exported_runtime_methods.json | 1 - 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/api.js b/src/api.js index 1b523ab6..81eaa716 100644 --- a/src/api.js +++ b/src/api.js @@ -804,7 +804,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { @param {string} fn filename for database file @return {Database} the created database instance */ - Database.open = function(fn) { + Database["open"] = function(fn) { var obj = Object.create(Database.prototype); obj.filename = fn; obj.handleError(sqlite3_open(obj.filename, apiTemp)); @@ -1216,6 +1216,19 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { return this; }; + var vfs = Module["FS"]; + + /** Create database instance + @param {string} fn filename for database file + @return {Database} the created database instance + */ + Module["mount"] = function(vdir, osdir) { + if (vfs.mayCreate(vdir)) { + vfs.mkdir(vdir) + } + return vfs.mount(vfs.filesystems["NODEFS"], {root: osdir}, vdir); + } + // export Database to Module Module.Database = Database; }; diff --git a/src/exported_runtime_methods.json b/src/exported_runtime_methods.json index 7a4dde89..eb028ee6 100644 --- a/src/exported_runtime_methods.json +++ b/src/exported_runtime_methods.json @@ -4,6 +4,5 @@ "stackSave", "stackRestore", "FS", -"NODEFS", "UTF8ToString" ] From df29c051a58181a05dc55133204c76d61859209c Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Mon, 1 Mar 2021 18:44:37 +0800 Subject: [PATCH 3/7] nodefs db should not deleted; add test file --- src/api.js | 21 ++++++++++++--------- test/test_nodefs.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 test/test_nodefs.js diff --git a/src/api.js b/src/api.js index 81eaa716..59a52766 100644 --- a/src/api.js +++ b/src/api.js @@ -804,8 +804,9 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { @param {string} fn filename for database file @return {Database} the created database instance */ - Database["open"] = function(fn) { + Database["open"] = function open(fn) { var obj = Object.create(Database.prototype); + obj.filetype = "FS"; obj.filename = fn; obj.handleError(sqlite3_open(obj.filename, apiTemp)); obj.db = getValue(apiTemp, "i32"); @@ -816,7 +817,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { // (created by create_function call) obj.functions = {}; return obj; - } + }; /** Execute an SQL query, ignoring the rows it returns. @param {string} sql a string containing some SQL text to execute @@ -1090,7 +1091,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; }; @@ -1219,15 +1222,15 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { var vfs = Module["FS"]; /** Create database instance - @param {string} fn filename for database file - @return {Database} the created database instance + @param {string} vdir directory name to mount for virtual fs + @param {string} osdir system directory to mount */ - Module["mount"] = function(vdir, osdir) { + Module["mount"] = function mount(vdir, osdir) { if (vfs.mayCreate(vdir)) { - vfs.mkdir(vdir) + vfs.mkdir(vdir); } - return vfs.mount(vfs.filesystems["NODEFS"], {root: osdir}, vdir); - } + vfs.mount(vfs.filesystems["NODEFS"], { root: osdir }, vdir); + }; // export Database to Module Module.Database = Database; diff --git a/test/test_nodefs.js b/test/test_nodefs.js new file mode 100644 index 00000000..0db6d4fb --- /dev/null +++ b/test/test_nodefs.js @@ -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 = SQL.Database.open('/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); + }); +} From 8e3347c69ecdf1c2de60534821f1dc17d4c668e4 Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Mon, 1 Mar 2021 18:51:43 +0800 Subject: [PATCH 4/7] fix lint --- src/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.js b/src/api.js index 59a52766..2ba6361e 100644 --- a/src/api.js +++ b/src/api.js @@ -1091,7 +1091,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { Object.values(this.functions).forEach(removeFunction); this.functions = {}; this.handleError(sqlite3_close_v2(this.db)); - if (this.filetype != "FS") { + if (this.filetype !== "FS") { FS.unlink("/" + this.filename); } this.db = null; From 1886f1c8a695cd5de8b75d00554746357265fc72 Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Tue, 2 Mar 2021 11:19:56 +0800 Subject: [PATCH 5/7] Make test run on debug first; add mountpoint support --- package.json | 2 +- src/api.js | 40 +++++++++++++++++----------------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index fac0370f..9bc9412f 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "scripts": { "build": "make", "rebuild": "make clean && make", - "test": "npm run lint && npm run test-asm && npm run test-asm-debug && npm run test-wasm && npm run test-wasm-debug && npm run test-asm-memory-growth", + "test": "npm run lint && npm run test-asm-debug && npm run test-wasm-debug && npm run test-asm && npm run test-wasm && npm run test-asm-memory-growth", "lint": "eslint .", "prettify": "eslint . --fix", "test-asm": "node test/all.js asm", diff --git a/src/api.js b/src/api.js index 2ba6361e..b43c80c5 100644 --- a/src/api.js +++ b/src/api.js @@ -782,14 +782,20 @@ 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 {number[]} data An array of bytes representing + * @param {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); @@ -800,25 +806,6 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { this.functions = {}; } - /** Create database instance - @param {string} fn filename for database file - @return {Database} the created database instance - */ - Database["open"] = function open(fn) { - var obj = Object.create(Database.prototype); - obj.filetype = "FS"; - obj.filename = fn; - obj.handleError(sqlite3_open(obj.filename, apiTemp)); - obj.db = getValue(apiTemp, "i32"); - registerExtensionFunctions(obj.db); - // A list of all prepared statements of the database - obj.statements = {}; - // A list of all user function of the database - // (created by create_function call) - obj.functions = {}; - return obj; - }; - /** Execute an SQL query, ignoring the rows it returns. @param {string} sql a string containing some SQL text to execute @param {Statement.BindParams} [params] When the SQL statement contains @@ -1232,6 +1219,13 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { vfs.mount(vfs.filesystems["NODEFS"], { root: osdir }, vdir); }; + var mountpoints = Module["fs"]; + if (mountpoints) { + for (var mountpoint of Object.entries(mountpoints)) { + Module["mount"](mountpoint[0], mountpoint[1]) + } + } + // export Database to Module Module.Database = Database; }; From 4ea17ccca9409afe526cda78e7ad589885b775ad Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Tue, 2 Mar 2021 11:25:18 +0800 Subject: [PATCH 6/7] fix test --- test/test_nodefs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_nodefs.js b/test/test_nodefs.js index 0db6d4fb..4ecd189c 100644 --- a/test/test_nodefs.js +++ b/test/test_nodefs.js @@ -8,7 +8,7 @@ exports.test = function(SQL, assert) { SQL.mount('/nfs', __dirname); //Works - var db = SQL.Database.open('/nfs/test.sqlite'); + 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"); From 9d579ff58ef40dc6a11cb0ee291bd4d2a576bd90 Mon Sep 17 00:00:00 2001 From: Boyi <chenby@localhost> Date: Tue, 2 Mar 2021 13:55:35 +0800 Subject: [PATCH 7/7] fix for lint --- src/api.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/api.js b/src/api.js index b43c80c5..66cf464d 100644 --- a/src/api.js +++ b/src/api.js @@ -782,11 +782,12 @@ 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 {number[]|string} data An array of bytes representing, or a string for mapped file name + * @param {number[]|string} data An array of bytes representing, + * or a string for mapped file name * an SQLite database file */ function Database(data) { - if (data != null && typeof data === 'string') { + if (data != null && typeof data === "string") { this.filename = data; this.filetype = "FS"; } else { @@ -1219,11 +1220,12 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { vfs.mount(vfs.filesystems["NODEFS"], { root: osdir }, vdir); }; - var mountpoints = Module["fs"]; + var mountpoints = Module["mountpoints"]; if (mountpoints) { - for (var mountpoint of Object.entries(mountpoints)) { - Module["mount"](mountpoint[0], mountpoint[1]) - } + Array.prototype.forEach.call(Object.keys(mountpoints), + function mount(mp) { + Module["mount"](mp, mountpoints[mp]); + }); } // export Database to Module