2016/03/28


Windows で C++ を使い、データベースの接続先を選ばないアプリケーションを書くのであれば ODBC 接続が一つの選択肢になります。しかし ODBC 接続のアプリケーションを書くのは非常に骨の折れる仕事です。

データの取得 - eternalwindows.jp
http://eternalwindows.jp/windevelop/odbc/odbc05.html

SQLAllocHandle によるハンドルの作成を事ある毎に行わなければなりません。そんな ODBC を使ったアプリケーションの開発を楽にしてくれそうなのが nanodbc です。

nanodbc

A small C++ wrapper for the native C ODBC API.

https://lexicalunit.github.io/nanodbc/

Windows で ODBC のシステムDSNに「mattn」という名前の接続情報を作り、今回は SQLite3 の ODBC ドライバを割り当てました。

odbc

コードも SQLAllocHandle が頻出しないのでとても綺麗に掛けます。

#include <nanodbc.h>
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;

int
main(int argc, char* argv[]) {
  try {
    nanodbc::connection conn("DSN=mattn");
    cout << "Connected with driver " << conn.driver_name() << endl;
    execute(conn, "drop table if exists example;");
    execute(conn, "create table example(id integer primary key, content text);");

    nanodbc::statement stmt(conn);
    prepare(stmt, "insert into example(content) values(?);");
    stmt.bind(0"ふー");
    nanodbc::result result = execute(stmt);
    cout << "\nAffected " << result.affected_rows() << " rows";

    nanodbc::result rows = execute(conn, "select * from example;");
    cout << "\nDisplaying " << rows.affected_rows() << " rows ";
    cout << "(" << rows.rowset_size() << " fetched at a time):" << endl;
    const short cols = rows.columns();
    for(short i = 0; i < cols; i++)
      cout << rows.column_name(i) << "\t";
    cout << endl;

    while(rows.next()) {
      for(short i = 0; i < cols; i++)
        cout << "(" << rows.get<string>(i, "null") << ")\t";
      cout << endl;
    }
  } catch(const exception& e) {
    cerr << e.what() << endl;
    return 1;
  }
}

/* vim:set et sw=2 cino=j2: */

ただしあまり C++ ぽさが無いので物足りない人もいるかもしれません。ライセンスは MIT です。

Posted at by



2016/03/23


こんにちわ。Vim 使ってますか?使ってますね。えっ使ってない?使いましょう。

さてこのたび、技術評論社様から Software Design 別冊シリーズとして Vim と Emacs に関する本が出版されます。僕の記事も含まれています。

仕事ですぐ役立つ Vim&Emacsエキスパート活用術:書籍案内|技術評論社

Unix/Linuxの使い始めのころ,慣れないコマンドライン上で設定ファイルを編集する際に使うテキストエディタがVim(Vi)あるいはEmacsでしょう。

http://gihyo.jp/book/2016/978-4-7741-8007-6

犬さん rhysd さんや、KoRoN さんの記事も収録されています。ぜひ宜しくお願いします。

Posted at by



2016/03/17


MySQLでカジュアルにズンドコキヨシ | GMOメディア エンジニアブログ

ズンドコキヨシ大流行ですね。 ズンドコキヨシまとめ - Qiita を見ていたんですが、MySQLでやってる人はいなさそうなので...

http://tech.gmo-media.jp/post/141178318699/zundoko-kiyoshi-with-mysql

SQLite3 でもやりたい!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
#include <sqlite3ext.h>

#ifdef _WIN32
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif

SQLITE_EXTENSION_INIT1;

static int
zundoko_connect(sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **c) {
  char buf[256];
  snprintf(buf, sizeof(buf)-1"CREATE TABLE %s(val text)", argv[0]);
  int rc = sqlite3_declare_vtab(db, buf);
  *ppVTab = (sqlite3_vtab *) sqlite3_malloc(sizeof(sqlite3_vtab));
  memset(*ppVTab, 0sizeof(sqlite3_vtab));
  return rc;
}

static int
zundoko_create(sqlite3 *db, void *pAux, int argc, const char * const * argv, sqlite3_vtab **ppVTab, char **c) {
  return zundoko_connect(db, pAux, argc, argv, ppVTab, c);
}

static int zundoko_disconnect(sqlite3_vtab *pVTab) {
  sqlite3_free(pVTab);
  return SQLITE_OK;
}

static int
zundoko_destroy(sqlite3_vtab *pVTab) {
  sqlite3_free(pVTab);
  return SQLITE_OK;
}

typedef struct {
  sqlite3_vtab_cursor base;
  int rowid;
  int kiyoshi;
  char zundoko[6];
} cursor;

static int
zundoko_open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
  cursor *c = (cursor *)sqlite3_malloc(sizeof(cursor));
  *ppCursor = &c->base;
  return SQLITE_OK;
}

static int
zundoko_close(cursor *c) {
  sqlite3_free(c);
  return SQLITE_OK;
}

static int
zundoko_next(cursor *c) {
  int i, l = sizeof(c->zundoko)/sizeof(c->zundoko[0]);
  for (i = 0; i < l-1; i++)
    c->zundoko[i] = c->zundoko[i+1];
  c->zundoko[5] = c->kiyoshi ? 'K' : (rand() % 2 == 0 ? 'Z' : 'D');
  c->rowid++;
  return SQLITE_OK;
}

static int
zundoko_filter(cursor *c, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
  srand((unsigned)time(NULL));
  c->rowid = 0;
  c->kiyoshi = 0;
  memset(c->zundoko, 0sizeof(c->zundoko));
  zundoko_next(c);
  return SQLITE_OK;
}

static int
zundoko_eof(cursor *c) {
  c->kiyoshi = memcmp(c->zundoko+1"ZZZZD"5) == 0;
  return c->zundoko[4] == 'K';
}

static int
zundoko_column(cursor *c, sqlite3_context *ctxt, int i) {
  char *p = "?";
  switch (c->zundoko[5]) {
    case 'Z': p = "ズン"break;
    case 'D': p = "ドコ"break;
    case 'K': p = "キ・ヨ・シ!"break;
  }
  sqlite3_result_text(ctxt, strdup(p), strlen(p), NULL);
  return SQLITE_OK;
}

static int
zundoko_rowid(cursor *c, sqlite3_int64 *pRowid) {
  *pRowid = c->rowid;
  return SQLITE_OK;
}

static int
zundoko_bestindex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo) {
  return SQLITE_OK;
}

static const sqlite3_module module = {
  0,
  zundoko_create,
  zundoko_connect,
  zundoko_bestindex,
  zundoko_disconnect,
  zundoko_destroy,
  zundoko_open,
  (int (*)(sqlite3_vtab_cursor *)) zundoko_close,
  (int (*)(sqlite3_vtab_cursor *, intchar const *, int, sqlite3_value **)) zundoko_filter,
  (int (*)(sqlite3_vtab_cursor *)) zundoko_next,
  (int (*)(sqlite3_vtab_cursor *)) zundoko_eof,
  (int (*)(sqlite3_vtab_cursor *, sqlite3_context *, int)) zundoko_column,
  (int (*)(sqlite3_vtab_cursor *, sqlite3_int64 *)) zundoko_rowid,
  NULL// zundoko_update
  NULL// zundoko_begin
  NULL// zundoko_sync
  NULL// zundoko_commit
  NULL// zundoko_rollback
  NULL// zundoko_findfunction
  NULL// zundoko_rename
};

static void
destructor(void *arg) {
  return;
}


EXPORT int
sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) {
  SQLITE_EXTENSION_INIT2(api);
  sqlite3_create_module_v2(db, "zundoko", &module, NULL, destructor);
  return 0;
}

こんなソースファイルを用意し Windows であれば以下の様にコンパイルします。

gcc -I. -g -o zundoko.dll -shared zundoko.c

sqlite3 を起動して dll を読み込みます。

SQLite version 3.7.14 2012-09-03 15:42:36
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

sqlite> select load_extension("zundoko.dll");
load_extension("zundoko.dll")

読み込めたら仮想テーブルを作ります。

sqlite> create virtual table zundoko using zundoko(val);

あとは SELECT

sqlite> SELECT * FROM ZUNDOKO;
ドコ
ドコ
ズン
ズン
ズン
ズン
ドコ
キ・ヨ・シ!

ソースコードはここに置いておきます。

Posted at by