これまで組み込み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, 1, stdout) > 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 の各言語バインディングも出てくるんじゃないかと思います。
 
