2012年11月26日月曜日

SQLiteを使ってみる 第3回

結果を返すタイプのクエリを投げてみよう。今回は、以下のような簡単なテーブルを作って、それを丸ごと返してもらう。

日付品目価格
11/25りんご123
11/26ごりら456

まずはサンプルコード。

// vim: set fileencoding=utf-8:
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
#define DEFAULT_FILENAME "test3.sqlite3"
sqlite3 *open_db(const char *filename) {
    sqlite3 *db;
    int rc;
    rc = sqlite3_open(filename, &db);
    printf("sqlite3_open() : %d\n", rc);
    if (rc != SQLITE_OK) {
        sqlite3_close(db);
        db = NULL;
    }
    return db;
}
int close_db(sqlite3 *db) {
    int rc;
    rc =  sqlite3_close(db);
    printf("sqlite3_close() : %d\n", rc);
    return rc;
}
sqlite3_stmt *exec_query(sqlite3 *db, const char *query) {
    sqlite3_stmt *stmt;
    int rc;
    rc = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
    printf("sqlite3_prepare_v2() : %d\n", rc);
    if (rc != SQLITE_OK) return NULL;
    rc = sqlite3_step(stmt);
    printf("sqlite3_step() : %d\n", rc);
    return stmt;
}
int fin_query(sqlite3_stmt *stmt) {
    int rc;
    rc = sqlite3_finalize(stmt);
    printf("sqlite3_finalize() : %d\n", rc);
    return rc;
}
int main(int argc, char **argv) {
    sqlite3 *db = NULL;
    int rc;
    char *filename = DEFAULT_FILENAME;
    // open
    if (argc >= 2) filename = argv[1];
    db = open_db(filename);
    if (db == NULL) return 1;
    sqlite3_stmt *stmt;
    rc = 2;
    // create table
    stmt = exec_query(db, "create table 家計簿(日付 text,品目 text,価格 int);");
    if (stmt == NULL) goto ensure;
    fin_query(stmt);
    // insert
    stmt = exec_query(db, "insert into 家計簿(日付,品目,価格) values('11/25','りんご',123);");
    if (stmt == NULL) goto ensure;
    fin_query(stmt);
    stmt = exec_query(db, "insert into 家計簿(日付,品目,価格) values('11/26','ごりら',456);");
    if (stmt == NULL) goto ensure;
    fin_query(stmt);
    // select
    const char *query = "select * from 家計簿";
    rc = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
    if (rc != SQLITE_OK) goto ensure;
    for (;;) {
        rc = sqlite3_step(stmt);
        printf("sqlite3_step() : %d\n", rc);
        if (rc != SQLITE_ROW) break;
        const unsigned char *text;
        int val;
        // 日付
        text = sqlite3_column_text(stmt, 0);
        if (text != NULL) printf("'%s', ", text);
        // 品目
        text = sqlite3_column_text(stmt, 1);
        if (text != NULL) printf("'%s', ", text);
        // 価格
        val = sqlite3_column_int(stmt, 2);
        printf("%d\n", val);
    }
    fin_query(stmt);
    rc = 0;
ensure:
    // close
    close_db(db);
    return rc;
}

結果は常に1行ずつ参照される。また、参照される行はsqlite3_step()が呼ばれる度に次へと進む。sqlite3_step()の戻り値は、参照する行が残っている場合はSQLITE_ROW、全ての行を返し終えた場合はSQLITE_DONEとなる。

sqlite3_column_text()が文字列へのポインタを返していることに注意。当然、メモリのどこかに文字列を確保しているわけだが、これはsqlite3_step()で次の行へ移ったときやsqlite3_finalize()で後始末するときに、自動的に解放される。このメモリの扱いは、ポインタを返す他のsqlite3_column_*()でも同様。

0 件のコメント:

コメントを投稿