2013/07/04

unqlite これまで組み込みDBだと SQLite が一般的でしたが、ローカルであっても NoSQL したい、組み込みで使いたい、というニーズはあるかと思います。 そんな場合、UnQLite を使うと便利そうです。
UnQLite - An Embeddable NoSQL Database Engine

UnQLite is a self-contained C library without dependency. It requires very minimal support from exte...

http://unqlite.org/
unqlite/unqlite - GitHub

README.md UnQLite UnQLite is a in-process software library which implements a self-contained, server...

https://github.com/unqlite/unqlite
特徴としては以下の通り。
  • サーバの要らない NoSQL データベースエンジン
  • トランザクショナル(ACID)データベース
  • ゼロコンフィグレーション
  • 単一のデータベースファイルでテンポラリファイルを使用しない
  • クロスプラットフォームなファイルフォーマット
  • UnQLite は依存の無いCライブラリを内蔵している
  • 標準でキーバリューストアを提供している
  • Jx9によるドキュメントストア(JSON)データベース
  • カーソルをサポートしており、リニアレコードをトラバース出来る
  • プラッガブルランタイムによりストレージエンジンを交換出来る
  • ディスクだけでなくインメモリデータベースもサポート
  • O(1) での検索をサポートした強力なストレージエンジンを構築
  • スレッドセーフで再入可能
  • 単純で綺麗で簡単にAPIが使える
  • テラバイトサイズのデータベースをサポート
  • BSDライセンス
  • 融合: UnQLiteとJx9が単一のソースコードで結合されたC言語ソースファイル
  • 可用性の高いオンラインサポート
詳しい詳細は以下を参照
UnQLite - Distinctive Features

The following page enumerates distinctive features of the UnQLite Database Engine and the Jx9 Embedd...

http://unqlite.org/features.html
試しに幾らかプログラムを書いてみた。
まずは単純にストアする物。 #include "unqlite.h"

int
main(int argc, char* argv[]) {
  int rc;
  unqlite *db;
  char buf[256];
  unqlite_int64 buflen = sizeof(buf);

  rc = unqlite_open(&db, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) return;

  rc = unqlite_kv_store_fmt(db, "mattn", -1"俺の%s""塩");
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_kv_fetch(db , "mattn", -1, buf, &buflen);
  if (rc != UNQLITE_OK) goto leave;

  buf[buflen] = 0;
  puts(buf);

leave:
  if (rc != UNQLITE_OK) {
    const char *pbuf;
    int len;
    unqlite_config(db, UNQLITE_CONFIG_ERR_LOG, &pbuf, &len);
    if (len > 0) {
      puts(pbuf);
    }
    if (rc != UNQLITE_BUSY && rc != UNQLITE_NOTIMPLEMENTED) {
      unqlite_rollback(db);
    }
  }
  unqlite_close(db);
}
使い方はそんなに難しくないですが、エラーを取るのに何手か掛かるのは少し面倒臭いです。 次に結合
#include "unqlite.h"

int
main(int argc, char* argv[]) {
  int rc;
  unqlite *db;
  char buf[256];
  unqlite_int64 buflen = sizeof(buf);

  rc = unqlite_open(&db, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) return;

  rc = unqlite_kv_store(db, "mattn", -1"じゅげむ"12);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_kv_append(db, "mattn", -1"じゅげむ2"12);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_kv_append(db, "mattn", -1"ごこうの"12);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_kv_append(db, "mattn", -1"すりきれ"12);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_kv_fetch(db , "mattn", -1, buf, &buflen);
  if (rc != UNQLITE_OK) goto leave;

  buf[buflen] = 0;
  puts(buf);

leave:
  if (rc != UNQLITE_OK) {
    const char *pbuf;
    int len;
    unqlite_config(db, UNQLITE_CONFIG_ERR_LOG, &pbuf, &len);
    if (len > 0) {
      puts(pbuf);
    }
    if (rc != UNQLITE_BUSY && rc != UNQLITE_NOTIMPLEMENTED) {
      unqlite_rollback(db);
    }
  }
  unqlite_close(db);
}
伸長も楽ちん。
実は UnQLite には Jx9 という組み込み言語が内蔵されており、データベースをスクリプトで操作出来る様になっています。
#include "unqlite.h"
#include <stdio.h>

static int
printer(const void *out,unsigned int len,void *data) {
  return fwrite(out, len, 1stdout) > 0 ? UNQLITE_OK : UNQLITE_ABORT;
}

int
main(int argc, char* argv[]) {
  int rc;
  unqlite *db;
  unqlite_vm* vm;

  rc = unqlite_open(&db, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) return;

  rc = unqlite_compile_file(db, "mattn.jx9", &vm);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_vm_config(vm, UNQLITE_VM_CONFIG_OUTPUT, printer, 0);
  if (rc != UNQLITE_OK) goto leave;

  rc = unqlite_vm_exec(vm);
  if (rc != UNQLITE_OK) goto leave;

leave:
  if (rc != UNQLITE_OK) {
    const char *pbuf;
    int len;
    unqlite_config(db, UNQLITE_CONFIG_ERR_LOG, &pbuf, &len);
    if (len > 0) {
      puts(pbuf);
    }
    if (rc != UNQLITE_BUSY && rc != UNQLITE_NOTIMPLEMENTED) {
      unqlite_rollback(db);
    }
  }
  if (vm) unqlite_vm_release(vm);
  unqlite_close(db);
}
この様に Jx9 ファイルをコンパイル実行するコードを書いて if (!db_exists('users')) {
  $rc = db_create('users');
  if (!$rc) {
    print db_errlog();
    return;
  }
}
$users = [
{
   name: 'james',
   age : 27,
   mail: 'dude@example.com'
},
{
   name: 'robert',
   age : 35,
   mail: 'rob@example.com'
},
{
   name: 'monji',
   age : 47,
   mail: 'monji@example.com'
},
{
   name: 'barzini',
   age : 52,
   mail: 'barz@mobster.com'
}
];
$rc = db_store('users', $users);
if (!$rc) {
  print db_errlog();
  return;
}
$rc = db_store('users', {name: 'mattn', age: 18, mail: 'mattn.jp@gmail.com'});
if (!$rc) {
  print db_errlog();
  return;
}
print "Total number of stored records: ", db_total_records('users'), JX9_EOL;
スクリプトを書きます。実行すると users データベースに JSON の様な構造でデータが格納されます。

なかなか面白いですね。
もう少し拡張すれば、ひとりぼっちTreasure Dataも作れそうな気がしました。
残念ながら、他の NoSQL と速度比較した資料を見つけ出せなかったので、時間が出来たらベンチマークも走らせてみたいと思いました。
これからこの UnQLite の各言語バインディングも出てくるんじゃないかと思います。
組み込みソフトウェア開発スタートアップ: ITエンジニアのための組み込み技術入門 (DESIGN WAVE MOOK) 組み込みソフトウェア開発スタートアップ: ITエンジニアのための組み込み技術入門 (DESIGN WAVE MOOK)
デザインウェーブマガジン編集部
CQ出版 単行本 / ¥2,420 (2005年07月01日)
 
発送可能時間:

Posted at 15:36 | WriteBacks () | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.






















A quick preview will be rendered here when you click "Preview" button.