疯狂的技术宅

以前出于工作目的,编写和翻译了大量的技术文章,以前端为主,删掉了过时的、毫无营养的内容,留下的都是精华。


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于本站

  • 回到主站

  • 搜索

sql.js:JS专用的内存型数据库

时间: 2019-11-12 分类: 前端技术   字数: 2256 字 阅读: 5分钟
标签: #JavaScript# #SQLite # #sql.js# #GitHub#
  • 本文译自:https://snyk.io/blog/javascript-frameworks-security-report-2019/
  • 译者:疯狂的技术宅

项目链接:https://github.com/kripken/sql.js

CI状态 CDNJS版本

对于没有耐心的人,请在这里处尝试Demo:http://kripken.github.io/sql.js/examples/GUI

sql.js 是 SQLite 到 Webassembly 的端口,是用 Emscripten 编译的 SQLite C 代码。它使用存储在内存中的虚拟数据库文件 ,因此不会保留所做的更改到数据库。但是,它允许你导入任何现有的 sqlite 文件,并将创建的数据库导出为 JavaScript 类型数组 。

没有 C 绑定或 node-gyp 编译,sql.js 是一个简单的JavaScript 文件,可以像传统的 JavaScript 库一样使用。如果你在 JavaScript 中创建本机应用程序(例如 Electron),或者在 node.js 中工作,那么你可能更喜欢使用 SQLite 与 JavaScript 的本机绑定 。

SQLite是 Public Domain,sql.js 是 MIT license。

Sql.js 的开发早于 WebAssembly,因此是作为 asm.js 项目启动的。现在它仍然保持对 asm.js 的向后兼容。

二进制版本

Sql.js 的最后构建日期:

Emscripten 版本 1.38.30(2019-04-16)发布历史

SqlLite 版本:3.28.0(2019-4-16)发布历史

文档

完整文档 根据源代码生成,可用。

用法

var initSqlJs = require('sql.js');
// or if you are in a browser:
// var initSqlJs = window.initSqlJs;

initSqlJs().then(SQL => {

  // Create a database
  var db = new SQL.Database();
  // NOTE: You can also use new SQL.Database(data) where
  // data is an Uint8Array representing an SQLite database file

  // Execute some sql
  sqlstr = "CREATE TABLE hello (a int, b char);";
  sqlstr += "INSERT INTO hello VALUES (0, 'hello');"
  sqlstr += "INSERT INTO hello VALUES (1, 'world');"
  db.run(sqlstr); // Run the query without returning anything

  var res = db.exec("SELECT * FROM hello");
  /*
  [
    {columns:['a','b'], values:[[0,'hello'],[1,'world']]}
  ]
  */

  // Prepare an sql statement
  var stmt = db.prepare("SELECT * FROM hello WHERE a=:aval AND b=:bval");

  // Bind values to the parameters and fetch the results of the query
  var result = stmt.getAsObject({':aval' : 1, ':bval' : 'world'});
  console.log(result); // Will print {a:1, b:'world'}

  // Bind other values
  stmt.bind([0, 'hello']);
  while (stmt.step()) console.log(stmt.get()); // Will print [0, 'hello']

  // You can also use JavaScript functions inside your SQL code
  // Create the js function you need
  function add(a, b) {return a+b;}
  // Specifies the SQL function's name, the number of it's arguments, and the js function to use
  db.create_function("add_js", add);
  // Run a query in which the function is used
  db.run("INSERT INTO hello VALUES (add_js(7, 3), add_js('Hello ', 'world'));"); // Inserts 10 and 'Hello world'

  // free the memory used by the statement
  stmt.free();
  // You can not use your statement anymore once it has been freed.
  // But not freeing your statements causes memory leaks. You don't want that.

  // Export the database to an Uint8Array containing the SQLite database file
  var binaryArray = db.export();
});

演示

有一些示例可在这里得到 。功能最全的是 Sqlite 解释器 。

例子

测试文件提供了关于 api 使用的最新示例。

在浏览器中

HTML 示例文件:

<meta charset="utf8" />
<html>
  <script src='/dist/sql-wasm.js'></script>
  <script>
    config = {
      locateFile: filename => `/dist/${filename}` 
    }
    // The `initSqlJs` function is globally provided by all of the main dist files if loaded in the browser.
    // We must specify this locateFile function if we are loading a wasm file from anywhere other than the current html page's folder.
    initSqlJs(config).then(function(SQL){
      //Create the database
      var db = new SQL.Database();
      // Run a query without reading the results
      db.run("CREATE TABLE test (col1, col2);");
      // Insert two rows: (1,111) and (2,222)
      db.run("INSERT INTO test VALUES (?,?), (?,?)", [1,111,2,222]);
  
      // Prepare a statement
      var stmt = db.prepare("SELECT * FROM test WHERE col1 BETWEEN $start AND $end");
      stmt.getAsObject({$start:1, $end:1}); // {col1:1, col2:111}
  
      // Bind new values
      stmt.bind({$start:1, $end:2});
      while(stmt.step()) { //
        var row = stmt.getAsObject();
        console.log('Here is a row: ' + JSON.stringify(row));
      }
    });
  </script>
  <body>
    Output is in Javascript console
  </body>
</html>

从用户选择的文件创建数据库

构造函数 SQL.Database 把表示数据库文件的整数数组作为可选参数。

以下代码用 HTML input 作为加载数据库的来源:

dbFileElm.onchange = () => {
  var f = dbFileElm.files[0];
  var r = new FileReader();
  r.onload = function() {
    var Uints = new Uint8Array(r.result);
    db = new SQL.Database(Uints);
  }
  r.readAsArrayBuffer(f);
}

参见:http://kripken.github.io/sql.js/examples/GUI/gui.js

从服务器加载数据库

var xhr = new XMLHttpRequest();
// For example: https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite
xhr.open('GET', '/path/to/database.sqlite', true);
xhr.responseType = 'arraybuffer';

xhr.onload = e => {
  var uInt8Array = new Uint8Array(this.response);
  var db = new SQL.Database(uInt8Array);
  var contents = db.exec("SELECT * FROM my_table");
  // contents is now [{columns:['col1','col2',...], values:[[first row], [second row], ...]}]
};
xhr.send();

参见:https://github.com/kripken/sql.js/wiki/Load-a-database-from-the-server

在 node.js 中使用

sql.js 托管在 npm 上 。你只需运行 npm install sql.js 就能安装。

另外,你也可以从下面的下载链接中简单地下载 sql-wasm.js 和 sql-wasm.wasm。

从磁盘读取数据库:

var fs = require('fs');
var initSqlJs = require('sql-wasm.js');
var filebuffer = fs.readFileSync('test.sqlite');
 
initSqlJs().then(function(SQL){
  // Load the db
  var db = new SQL.Database(filebuffer);
});

将数据库写入磁盘

你需要将 db.export 的结果转换为 buffer

var fs = require("fs");
// [...] (create the database)
var data = db.export();
var buffer = new Buffer(data);
fs.writeFileSync("filename.sqlite", buffer);

参见:https://github.com/kripken/sql.js/blob/master/test/test_node_file.js

用作 web worker

如果你不想在程序的主线程中运行 CPU 密集型 SQL 查询,可以使用更有限的 WebWorker API。

你将需要下载 dist/worker.sql-wasm.js 和 dist/worker.sql-wasm.wasm .。

例:

<script>
  var worker = new Worker("/dist/worker.sql-wasm.js");
  worker.onmessage = () => {
    console.log("Database opened");
    worker.onmessage = event => {
      console.log(event.data); // The result of the query
    };
	
    worker.postMessage({
      id: 2,
      action: 'exec',
      sql: 'SELECT * FROM test'
    });
  };

  worker.onerror = e => console.log("Worker error: ", e);
  worker.postMessage({
    id:1,
    action:'open',
    buffer:buf, /*Optional. An ArrayBuffer representing an SQLite Database file*/
  });
</script>

有关完整的例子,请参见 examples/GUI/gui.js 。

Flavors/versions Targets/Downloads

该库包含 Sqlite 的 WebAssembly 和 asm.js 两个版本。(WebAssembly 是较新的,也是首选的编译为 JavaScript 的方法,它已经取代了 asm.js。它会生成更小、更快的代码。)包含 Asm.js 版本是为了兼容性的考虑。

从 0.x 升级到 1.x

sql.js 的 1.0 版必须异步加载,而 asm.js 则可以同步加载。

所以在过去,你应该:

<script src='js/sql.js'></script>
<script>
  var db = new SQL.Database();
  //...
</script>

或者

var SQL = require('sql.js');
var db = new SQL.Database();
//...

在版本1.x 中:

<script src='dist/sql-wasm.js'></script>
<script>
  initSqlJs({ locateFile: filename => `/dist/${filename}` }).then(function(SQL){
    var db = new SQL.Database();
    //...
  });
</script>

或者:

var initSqlJs = require('sql-wasm.js');
initSqlJs().then(function(SQL){
  var db = new SQL.Database();
  //...
});

现在,NOTHING 是 SQLite 中的保留字,而以前不是。这可能会导致类似 Error: near "nothing": syntax error 的错误。

下载与使用:

尽管 asm.js 文件是作为单个 Javascript 文件分发的,但 WebAssembly 库却能够最有效地对 .js 加载器和 .wasm 文件进行分发,例如 dist/sql-wasm.js 和 dist/sql-wasm.wasm。 .js 文件负责包装与加载 .wasm 文件。

包含在 distributed artifacts 中的sql.js版本

对于每个 relase ,你都会在 release assets 中找到一个名为 sqljs.zip 的文件。它包含:

  • sql-wasm.js:WebAssembly 版本的Sql.js。适合生产环境。如果选择它,则还需要包含 sql-wasm.wasm。
  • sql-wasm-debug.js:Sql.js 的 WebAssembly 调试版本。更大,打开了断言,这对本地开发很有用。如果使用它,则需要包含 sql-wasm-debug.wasm。
  • sql-asm.js:Sql.js 的 asm.js 旧版本。较慢且更大。出于兼容性的原因提供。
  • sql-asm-memory-growth.js:默认情况下,Asm.js 不允许内存增长,因为它速度较慢且会进行优化。如果你正在使用 sql-asm.js 并看到这个错误:Cannot enlarge memory arrays ,请使用此文件。
  • sql-asm-debug.js:Sql.js 的 Debug asm.js 版本。用它进行本地开发。
  • worker.* :以上库的 Web Worker 版本。 API 更加有限。有关它的示例,请参见 examples/GUI/gui.js 。

编译

  • 安装 EMSDK,这里有详细描述
  • 运行 npm run rebuild
标签: #JavaScript# #SQLite # #sql.js# #GitHub#

标题:sql.js:JS专用的内存型数据库

链接:https://fe-tech.viewnode.com/post/201911/12a/

作者:疯狂的技术宅

声明: 本博客文章除特别声明外,均采用 CC BY-NC-ND 4.0 国际许可协议( 知识共享署名-非商业性使用-禁止演绎 4.0),转载请注明出处!

JavaScript 测试教程 part 1:用 Jest 进行单元测试
解决 JavaScript 中处理 null 和 undefined 的麻烦事
  • 文章目录
  • 站点概览
疯狂的技术宅

疯狂的技术宅

退休程序员,硬件发烧友,人工智能爱好者。写写代码喝喝茶,晒晒太阳带带娃。

457 日志
8 分类
583 标签
GitHub
友情链接
  • viewnode
  • mofish
标签云
  • Javascript 172
  • Node.Js 62
  • Vue 36
  • Typescript 28
  • 实战项目 28
  • 面试 21
  • React 20
  • Css 17
  • 面试题 16
  • 教程 13
  • Promise 12
  • Chrome 9
  • Debug 9
  • 调试 9
  • 资源 9
  • Deno 8
  • Dom 8
  • 杂谈 8
  • 正则表达式 8
  • 测试 8
  • 二进制版本
  • 文档
  • 用法
  • 演示
  • 例子
    • 在浏览器中
    • 在 node.js 中使用
    • 用作 web worker
  • Flavors/versions Targets/Downloads
  • 从 0.x 升级到 1.x
    • 下载与使用:
  • 包含在 distributed artifacts 中的sql.js版本
  • 编译
© 2018 - 2022 疯狂的技术宅 All Rights Reserved
Powered by - Hugo v0.99.0 / Theme by - NexT
Storage by 俺的服务器 / 冀ICP备2022010157号
0%