SQLite3をCでいじる
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > SQLite3をCでいじる
CからSQLiteをいじる
思うところがあって、SQLiteをCからいじるということをやってみた。
環境
- WSL上のUbuntu 14.06(サポート切れ)
- WSL上のUbuntu 16.04
これほど古いと、SQLiteのバージョンは3.8.2になるが、使える関数がなかったりする。
インストール
build-essentialとかはインストールしてある。
$ sudo apt install libsqlite3-dev
コード
SQLiteのバージョンを表示するコード
#include <stdio.h>
#include <sqlite3.h>
int main(void) {
printf("SQLite3 lib number version: %d\n", sqlite3_libversion_number());
printf("SQLite3 version: %s\n", sqlite3_version);
return 0;
}
これをコンパイルする
$ gcc -Wall -o ver_sqlite3 ver_sqlite3.c -lsqlite3
実行
$ ./ver_sqlite3
SQLite3 lib number version: 3011000
SQLite3 version: 3.11.0
memoryに接続する
#include <sqlite3.h>
#include <stdio.h>
int main(void) {
sqlite3 *db;
sqlite3_stmt *res;
int rc = sqlite3_open(":memory:", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
// sqlite3_prepare_v3 が使えるのは 3.20.0 から
// https://sqlite.org/changes.html#version_3_20_0
rc = sqlite3_prepare_v2(db, "SELECT SQLITE_VERSION();", -1, &res, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
rc = sqlite3_step(res);
if (rc == SQLITE_ROW) {
printf("%s\n", sqlite3_column_text(res, 0));
}
sqlite3_finalize(res);
sqlite3_close(db);
return 0;
}
Carsというテーブルで色々する
Carsというテーブルに対して、まずSELECTで一行取得、Suzukiというnameの行があったらDELETEしてCarsのidのMAXを取得してからCarsにSuzukiというnameの行をINSERTする
簡単に言うと、実行するたびにSuzukiという行が追加されているが、ダブらない。
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
int main(void) {
sqlite3 *db;
sqlite3_stmt *res;
// open
int rc = sqlite3_open("test.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *sql = "SELECT id, name FROM Cars WHERE id = ?";
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
if (rc == SQLITE_OK) {
sqlite3_bind_int(res, 1, 3);
} else {
fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(db));
}
int step = sqlite3_step(res);
if (step == SQLITE_ROW) {
printf("%s: ", sqlite3_column_text(res, 0));
printf("%s\n", sqlite3_column_text(res, 1));
}
sqlite3_finalize(res);
char *car_name = "Suzuki";
// delete suzuki
char *del = "DELETE FROM Cars WHERE name = ?;";
rc = sqlite3_prepare_v2(db, del, -1, &res, 0);
if (rc == SQLITE_OK) {
sqlite3_bind_text(res, 1, car_name, strlen(car_name), SQLITE_TRANSIENT);
} else {
fprintf(stderr, "Faild to execute statement: %s\n", sqlite3_errmsg(db));
}
rc = sqlite3_step(res);
if (rc != SQLITE_DONE) {
fprintf(stderr, "execution failed: %s", sqlite3_errmsg(db));
} else {
printf("Delete completed\n");
}
// get max id
char *last_row_sql = "SELECT MAX(id) FROM Cars;";
rc = sqlite3_prepare_v2(db, last_row_sql, -1, &res, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to execute statement: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(res);
sqlite3_close(db);
return 1;
}
int last_row_id = 0;
step = sqlite3_step(res);
if (step == SQLITE_ROW) {
last_row_id = sqlite3_column_int(res, 0);
printf("last_row_id: %d\n", last_row_id);
}
sqlite3_finalize(res);
// insert suzuki
char *ins = "INSERT INTO Cars(id, name, price) VALUES(?, ?, ?);";
rc = sqlite3_prepare_v2(db, ins, -1, &res, 0);
if (rc == SQLITE_OK) {
sqlite3_bind_int(res, 1, last_row_id + 1);
sqlite3_bind_text(res, 2, car_name, strlen(car_name), SQLITE_TRANSIENT);
sqlite3_bind_int(res, 3, 29000);
} else {
fprintf(stderr, "Faild to execute statement: %s\n", sqlite3_errmsg(db));
}
rc = sqlite3_step(res);
if (rc != SQLITE_DONE) {
printf("execution failed: %s", sqlite3_errmsg(db));
} else {
printf("execution completed: %d\n", (int)sqlite3_last_insert_rowid(db));
}
sqlite3_finalize(res);
sqlite3_close(db);
return 0;
}