LoginSignup
2
2

More than 3 years have passed since last update.

IndexedDBをSQLで操作可能なSqlWebというライブラリを使ってみた

Last updated at Posted at 2019-06-02

概要

IndexedDBをSQLで操作してみたいと思って探してみたところ良さそうなライブラリがあったのでメモ

環境

macOS 10.13.6
npm 6.9.0

インストール

公式のGitHubではReact、TypeScript、Webpack、CDNの4つのサンプルを置いてくれているので、今回はWebpackでテスト。npmは導入されている状態です。

Webpackのインストール

適当なディレクトリを作成してWebpackをインストールします。

$ mkdir test_sqlweb
$ cd test_sqlweb
$ npm init -y
$ npm i webpack webpack-cli --save-dev

インストールが完了したらwebpack.config.jsを作成しておきます。
src/sqlweb.jsにコードを書き、バンドルされたファイルはdist/bundle.jsに出力させる予定なので下記のように記載します。

webpack.config.js
const path = require('path');

module.exports = {
    mode: "development",
    entry: path.resolve(__dirname, "src/sqlweb.js"),
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "sqlweb.bundle.js"
    }
};

SqlWebのインストール

SqlWebはIndexedDBをSQL「風に」扱うJsStoreというライブラリの拡張ですので、JsStoreとコード中に用いるfile-loaderも同時にインストールします。
※この記事を書いている時にJsStoreのアップデートがあったみたいで、最新の3.0.0だと用意したプログラムが動作しなかったので、以前のバージョンをインストールします。
※2019/07/14追記 最新版でも動作を確認できましたので、最新バージョンで問題なさそうです。

$ npm i jsstore sqlweb file-loader --save-dev

動作確認

コード作成

前述の通りsrc/sqlweb.jsにコードを書いていきます。

sqlweb.js
import * as JsStore from "jsstore";
import * as SqlWeb from 'sqlweb';

// バックグラウンドで動かすためのWeb workerの設定
const workerPath = require("file-loader?name=scripts/jsstore.worker.js!../node_modules/jsstore/dist/jsstore.worker");
const con = new JsStore.Instance(new Worker('dist/'+workerPath));

// SQL Webを使用する宣言
JsStore.useSqlWeb(SqlWeb);

// indexedDBの設定
const dbName = "sample_db";
const tbName = "sample_tb";

// indexedDBの初期化
initJsStore();

function initJsStore(){
    con.runSql(`ISDBEXIST ${dbName}`).then((isExist) => {
        if (isExist) {
            const qry = 'OPENDB ' + dbName;
            con.runSql(qry);
        } else {
            const qry = getDbQuery();
            con.runSql(qry);
            // 初期データの追加
            addData();
        }
    }).catch(err => {
        console.error(err);
    })
}

// 初期データの追加
function addData(){
    const data = [
        {name:'TARO', club:'baseball'},
        {name:'JIRO', club:'soccer'},
        {name:'SABU', club:'tennis'},
    ]
    data.forEach(val =>{
        const qry = `insert into ${tbName} values ({name: '${val.name}', club: '${val.club}'})`;
        con.runSql(qry);
    })
}

// DBとテーブルの初期化用SQL作成
function getDbQuery() {
    const db = `DEFINE DB ${dbName};`;
    const tblSampleQry = `
DEFINE TABLE ${tbName}(
id PRIMARYKEY AUTOINCREMENT,
name STRING NOTNULL ,
club STRING NOTNULL
);`;
    const dbCreatequery = db + tblSampleQry;
    return dbCreatequery;
}

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>SqlWeb Test Page</title>
</head>
<body>
    <h1>Hello SqlWeb!</h1>
    <script src="dist/bundle.js"></script>
</body>
</html>

現状のディレクトリ構成は下記のようになっています。

test_sqlweb
├── dist
│   ├── scripts
│   │   └── jsstore.worker.js
│   └── sqlweb.bundle.js
├── index.html
├── node_modules
|   └── ...
├── package-lock.json
├── package.json
├── src
│   └── sqlweb.js
└── webpack.config.js

ここまで書いたらpackage.jsonを以下のように修正して、コマンドを実行します。

package.json
{
  "name": "test_sqlweb",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "webpack",
    "start": "webpack --watch"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "file-loader": "^3.0.1",
    "jsstore": "^2.12.0",
    "sqlweb": "^1.2.1",
    "webpack": "^4.32.2",
    "webpack-cli": "^3.3.2"
  },
  "dependencies": {}
}
$ npm start

ブラウザでの確認

ブラウザでindex.htmlを開き、デベロッパーツールで確認するとIndexedDBにデータが書き込まれているのが確認できます。

Chrome

スクリーンショット 2019-06-02 11.20.10.png

Firefox

スクリーンショット 2019-06-02 11.20.27.png

はまったところ

  • NetworkError: Failed to load worker script
    Chromeだとエラー文すら出力されなくてFirefoxだとこのエラーになる。workerファイルのパスがずれていたのでそれを修正して解決。

  • Uncaught (in promise) DOMException: Failed to execute 'open' on 'IDBFactory': access to the Indexed Database API is denied in this context.
    Chromeでindex.htmlを開いた場合に出たエラー。Firefoxではエラーにならない。Chromeに起動オプションを付けて起動することで解決。
    Access to the Indexed Database API is denied in this context
    MacでGoogleChromeで起動オプションを設定する方法

  • JsStoreのバージョンが上がり、以前のプログラムが動作しなくなった。(2019/06/02時点)
    恐らくこれもWebworkerのパスの指定方法が問題じゃないかとあたりを付けているが、現状は調べきれなかった。JsStoreのバージョンを下げることで解決。

感想

SQLでローカルに保存できるデータを扱いたいなあと思って探していたらSqlwebに行き着きました。NoSQLであるIndexedDBをSQLで操作できるという点は非常に良いです。ただし、SQL文に若干癖があり(CREATE DBがDEFINE DBだったり、insertの際の値の指定法等)、うまく利用するには工夫が必要といった印象です。

また、Sqlwebの動作を確認するために、フォームに打ったSQLをそのまま実行するページを作りましたので貼っておきます。
https://github.com/ryu022304/sqlweb-test

参考サイト

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2