2013/07/04

Recent entries from same category

  1. RapidJSON や simdjson よりも速いC言語から使えるJSONライブラリ「yyjson」
  2. コメントも扱える高機能な C++ 向け JSON パーサ「jsoncpp」
  3. C++ で flask ライクなウェブサーバ「clask」書いた。
  4. C++ 用 SQLite3 ORM 「sqlite_orm」が便利。
  5. zsh で PATH に相対パスを含んだ場合にコマンドが補完できないのは意図的かどうか。

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 の各言語バインディングも出てくるんじゃないかと思います。
Posted at by | Edit