JXAのObjective-Cブリッジは、いくつかの標準添付Cライブラリへのアクセスを提供している。
この記事では、JXAにおいて、SQLite3のCインターフェイスを介して、SQLite3データベースを操作する方法を説明する。
オープンおよびクローズ
sqlite**
型は空のRef
で表現できる。var db = ppDb[0]
はデリファレンス(sqlite *db = *ppDb
)に相当する操作である。
ObjC.import('sqlite3')
var err
var filename = $('~/data.sqlite3').stringByStandardizingPath.js
var ppDb = Ref()
err = $.sqlite3_open(filename, ppDb)
var db = ppDb[0]
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
try {
/* データベース操作 */
} finally {
err = $.sqlite3_close(db)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
テーブル作成
NULL
ポインタは空のRef()
で表現できる。
sql = 'CREATE TABLE IF NOT EXISTS myTable (id INTEGER PRIMARY KEY, name TEXT); DELETE FROM myTable'
err = $.sqlite3_exec(db, sql, Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
レコード挿入
// トランザクション
err = $.sqlite3_exec(db,'BEGIN', Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
sql = 'INSERT INTO myTable (id, name) VALUES (?, ?)'
ppStmt = Ref()
err = $.sqlite3_prepare_v2(db, sql, -1, ppStmt, Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
pStmt = ppStmt[0]
try {
for (var i = 0; i < 100; i++) {
err = $.sqlite3_reset(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_bind_int(pStmt, 1, i)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_bind_text(pStmt, 2, "First " + i + " unique names", -1, -1)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_step(pStmt)
if (err != $.SQLITE_DONE) throw new Error($.sqlite3_errmsg(db))
}
// トランザクション
err = $.sqlite3_exec(db,'END', Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
} finally {
err = $.sqlite3_finalize(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
注意
型がconst char *
の引数に対しては、JavaScriptの文字列を直接渡すことが可能であるが、渡したポインタが指す領域は当該関数呼び出し終了時に解放される模様。
したがって、$.sqlite3_bind_text
などの関数を使用する場合、第5引数にSQLITE_TRANSIENT
(-1
) を使用し、SQLiteの内部バッファに文字列をコピーしておく必要がある。
レコード検索
sql = 'SELECT id, name FROM myTable'
ppStmt = Ref()
err = $.sqlite3_prepare_v2(db, sql, -1, ppStmt, Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
pStmt = ppStmt[0]
try {
while ((err = $.sqlite3_step(pStmt)) == $.SQLITE_ROW) {
console.log($.sqlite3_column_int(pStmt, 0), $.sqlite3_column_text(pStmt, 1))
}
if (err != $.SQLITE_DONE) throw new Error($.sqlite3_errmsg(db))
} finally {
err = $.sqlite3_finalize(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
コード
ObjC.import('sqlite3')
var err
var filename = $('~/data.sqlite3').stringByStandardizingPath.js
var ppDb = Ref()
err = $.sqlite3_open(filename, ppDb)
var db = ppDb[0]
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
try {
var sql, ppStmt, pStmt
sql = 'CREATE TABLE IF NOT EXISTS myTable (id INTEGER PRIMARY KEY, name TEXT); DELETE FROM myTable'
err = $.sqlite3_exec(db, sql, Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_exec(db,'BEGIN', Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
sql = 'INSERT INTO myTable (id, name) VALUES (?, ?)'
ppStmt = Ref()
err = $.sqlite3_prepare_v2(db, sql, -1, ppStmt, Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
pStmt = ppStmt[0]
try {
for (var i = 0; i < 100; i++) {
err = $.sqlite3_reset(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_bind_int(pStmt, 1, i)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_bind_text(pStmt, 2, "First " + i + " unique names", -1, -1)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
err = $.sqlite3_step(pStmt)
if (err != $.SQLITE_DONE) throw new Error($.sqlite3_errmsg(db))
}
err = $.sqlite3_exec(db,'END', Ref(), Ref(), Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
} finally {
err = $.sqlite3_finalize(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
sql = 'SELECT id, name FROM myTable'
ppStmt = Ref()
err = $.sqlite3_prepare_v2(db, sql, -1, ppStmt, Ref())
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
pStmt = ppStmt[0]
try {
while ((err = $.sqlite3_step(pStmt)) == $.SQLITE_ROW) {
console.log($.sqlite3_column_int(pStmt, 0), $.sqlite3_column_text(pStmt, 1))
}
if (err != $.SQLITE_DONE) throw new Error($.sqlite3_errmsg(db))
} finally {
err = $.sqlite3_finalize(pStmt)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
} finally {
err = $.sqlite3_close(db)
if (err != $.SQLITE_OK) throw new Error($.sqlite3_errmsg(db))
}
結果
/* 0 First 0 unique names */
/* 1 First 1 unique names */
...
/* 97 First 97 unique names */
/* 98 First 98 unique names */
/* 99 First 99 unique names */
Result:
0