专栏首页京程一灯sql.js:JS专用的内存型数据库[github项目精选0x01]

sql.js:JS专用的内存型数据库[github项目精选0x01]

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

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

sql.js 是 SQLite【http://sqlite.org/about.html】 到 Webassembly 的端口,是用 Emscripten【http://kripken.github.io/emscripten-site/docs/introducing_emscripten/about_emscripten.html】 编译的 SQLite C 代码。它使用存储在内存中的虚拟数据库文件【https://kripken.github.io/emscripten-site/docs/porting/files/file_systems_overview.html】,因此不会保留所做的更改到数据库。但是,它允许你导入任何现有的 sqlite 文件,并将创建的数据库导出为 JavaScript 类型数组【https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays】。

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

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

Sql.js 的开发早于 WebAssembly,因此是作为 asm.js【https://en.wikipedia.org/wiki/Asm.js】 项目启动的。现在它仍然保持对 asm.js 的向后兼容。

二进制版本

Sql.js 的最后构建日期:

Emscripten 版本 1.38.30(2019-04-16)发布历史【https://emscripten.org/docs/introducing_emscripten/release_notes.html】

SqlLite 版本:3.28.0(2019-4-16)发布历史【https://www.sqlite.org/changes.html】

文档

完整文档【http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Database.html】 根据源代码生成,可用。

用法

 1var initSqlJs = require('sql.js');
 2// or if you are in a browser:
 3// var initSqlJs = window.initSqlJs;
 4
 5initSqlJs().then(SQL => {
 6
 7  // Create a database
 8  var db = new SQL.Database();
 9  // NOTE: You can also use new SQL.Database(data) where
10  // data is an Uint8Array representing an SQLite database file
11
12  // Execute some sql
13  sqlstr = "CREATE TABLE hello (a int, b char);";
14  sqlstr += "INSERT INTO hello VALUES (0, 'hello');"
15  sqlstr += "INSERT INTO hello VALUES (1, 'world');"
16  db.run(sqlstr); // Run the query without returning anything
17
18  var res = db.exec("SELECT * FROM hello");
19  /*
20  [
21    {columns:['a','b'], values:[[0,'hello'],[1,'world']]}
22  ]
23  */
24
25  // Prepare an sql statement
26  var stmt = db.prepare("SELECT * FROM hello WHERE a=:aval AND b=:bval");
27
28  // Bind values to the parameters and fetch the results of the query
29  var result = stmt.getAsObject({':aval' : 1, ':bval' : 'world'});
30  console.log(result); // Will print {a:1, b:'world'}
31
32  // Bind other values
33  stmt.bind([0, 'hello']);
34  while (stmt.step()) console.log(stmt.get()); // Will print [0, 'hello']
35
36  // You can also use JavaScript functions inside your SQL code
37  // Create the js function you need
38  function add(a, b) {return a+b;}
39  // Specifies the SQL function's name, the number of it's arguments, and the js function to use
40  db.create_function("add_js", add);
41  // Run a query in which the function is used
42  db.run("INSERT INTO hello VALUES (add_js(7, 3), add_js('Hello ', 'world'));"); // Inserts 10 and 'Hello world'
43
44  // free the memory used by the statement
45  stmt.free();
46  // You can not use your statement anymore once it has been freed.
47  // But not freeing your statements causes memory leaks. You don't want that.
48
49  // Export the database to an Uint8Array containing the SQLite database file
50  var binaryArray = db.export();
51});

演示

有一些示例可在这里得到【https://kripken.github.io/sql.js/index.html】。功能最全的是 Sqlite 解释器【https://kripken.github.io/sql.js/examples/GUI/index.html】。

例子

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

在浏览器中

HTML 示例文件:

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

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

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

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

1dbFileElm.onchange = () => {
2  var f = dbFileElm.files[0];
3  var r = new FileReader();
4  r.onload = function() {
5    var Uints = new Uint8Array(r.result);
6    db = new SQL.Database(Uints);
7  }
8  r.readAsArrayBuffer(f);
9}

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

从服务器加载数据库

 1var xhr = new XMLHttpRequest();
 2// For example: https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite
 3xhr.open('GET', '/path/to/database.sqlite', true);
 4xhr.responseType = 'arraybuffer';
 5
 6xhr.onload = e => {
 7  var uInt8Array = new Uint8Array(this.response);
 8  var db = new SQL.Database(uInt8Array);
 9  var contents = db.exec("SELECT * FROM my_table");
10  // contents is now [{columns:['col1','col2',...], values:[[first row], [second row], ...]}]
11};
12xhr.send();

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

在 node.js 中使用

sql.js 托管在 npm 上【https://www.npmjs.org/package/sql.js】。你只需运行 npm install sql.js 就能安装。

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

从磁盘读取数据库:

1var fs = require('fs');
2var initSqlJs = require('sql-wasm.js');
3var filebuffer = fs.readFileSync('test.sqlite');
4
5initSqlJs().then(function(SQL){
6  // Load the db
7  var db = new SQL.Database(filebuffer);
8});

将数据库写入磁盘

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

1var fs = require("fs");
2// [...] (create the database)
3var data = db.export();
4var buffer = new Buffer(data);
5fs.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.js】 和 dist/worker.sql-wasm.wasm【dist/worker.sql-wasm.wasm】.。

例:

 1<script>
 2  var worker = new Worker("/dist/worker.sql-wasm.js");
 3  worker.onmessage = () => {
 4    console.log("Database opened");
 5    worker.onmessage = event => {
 6      console.log(event.data); // The result of the query
 7    };
 8
 9    worker.postMessage({
10      id: 2,
11      action: 'exec',
12      sql: 'SELECT * FROM test'
13    });
14  };
15
16  worker.onerror = e => console.log("Worker error: ", e);
17  worker.postMessage({
18    id:1,
19    action:'open',
20    buffer:buf, /*Optional. An ArrayBuffer representing an SQLite Database file*/
21  });
22</script>

有关完整的例子,请参见 examples/GUI/gui.js【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 则可以同步加载。

所以在过去,你应该:

1<script src='js/sql.js'></script>
2<script>
3  var db = new SQL.Database();
4  //...
5</script>

或者

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

在版本1.x 中:

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

或者:

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

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

下载与使用:

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

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

对于每个 relase【https://github.com/kripken/sql.js/releases/】,你都会在 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【examples/GUI/gui.js】。

编译

  • 安装 EMSDK,这里有详细描述【https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html】
  • 运行 npm run rebuild

本文分享自微信公众号 - 前端先锋(jingchengyideng),作者:疯狂的技术宅

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 用 TypeScript 开发 Node.js 程序[每日前端夜话0x5E]

    翻译:疯狂的技术宅 原文:https://medium.com/@freek_mencke/how-to-write-node-js-applications-...

    疯狂的技术宅
  • Webpack5.0 新特性尝鲜实战 ?? [每日前端夜话0x37]

    在老袁写这篇文章的时候,v5版本仍然处于早期阶段,可能仍然有问题。而且作为一个major版本,其中有一些breaking changes,可能会导致一些配置和插...

    疯狂的技术宅
  • 为什么要使用Node.js?

    JavaScript的流行给它本身带来许多变化,Web开发的面貌也发生了巨大的改变。现在JavaScript不仅可以运行在浏览器上,甚至可以运行在服务器上,像F...

    疯狂的技术宅
  • js的动态加载、缓存、更新以及复用(一)使用范围:遇到的问题:目标:页面结构:正文

    使用范围:   OA、MIS、ERP等信息管理类的项目,暂时不考虑网站。 遇到的问题:   完成一个项目,往往需要引用很多js文件,比如jQuery.js、ea...

    用户1174620
  • js的动态加载、缓存、更新以及复用(二)恼人的命名冲突

      上一篇发出来后得到了很多回复,在此首先感谢大家的热情捧场!有的推荐第三方框架,比如 In.js、requrieJS、sea.js、lab.js等。这个开阔了...

    用户1174620
  • Webpack系列——手把手教你使用Webpack搭建简易的React开发环境

    在这篇文章中我们开始利用我们之前所学搭建一个简易的React开发环境,用以巩固我们之前学习的Webpack知识。首先我们需要明确这次开发环境需要达到的效果:1、...

    用户1515472
  • 一步一步创建vue2.0项目(一)

    新建一个文件夹 vue2.0-learn 。_前提是默认已经安装了nodejs和npm_

    frontoldman
  • 2020 年 Java 程序员应该学习什么?

    大家好,我相信大家在新的一年都有一个良好的开端,并准备好制定一个提升自我技术的目标。作为 Java 开发人员,我还制定了一些目标,希望在今年成为一名更好的 Ja...

    武培轩
  • 03 Spring的父子容器

    1、概念理解和知识铺垫 在Spring整体框架的核心概念中,容器是核心思想,就是用来管理Bean的整个生命周期的,而在一个项目中,容器不一定只有一个,Sprin...

    nnngu
  • Layui 模板laytpl

    //第一步:编写模版。你可以使用一个script标签存放模板,如: <script id="demo" type="text/html"> <h3>{{ d...

    用户5760343

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动