WSH(JScript)用簡易データベース:DBLite.js
WSH(JScript)用簡易データベースです。
機能概要は、以下の通りです。
- SQLite(DB)の操作
本ライブラリの使用には、別途SQLite ODBC Driverのインストールが必要です。
サンプル
dblite.wsf<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
<job>
<?job error="false" debug="true" ?>
<script language="JavaScript" src="../lib/json3.min.js"/>
<script language="JavaScript" src="../common/DBLite.js"/>
<script language="JavaScript"><![CDATA[
(function() {
"use strict";
function random(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
};
function main() {
var db = new DBLite('./test.sqlite3');
if (db.open()) {
var table1 = db.createTable('table1');
var table2 = db.createTable('table2');
// 未指定時の取得
var date = table1.get('date', 'no data');
WScript.Echo('pre: '+date);
var date = new Date();
WScript.Echo('now: '+date.toLocaleString());
table1.set('date', date.toLocaleString());
// オブジェクトの格納
var obj1 = {aaa:'AAA',bbb:'bbb'};
WScript.Echo('obj1: '+JSON.stringify(obj1));
table1.set('obj', obj1);
var obj2 = table1.get('obj');
WScript.Echo('obj2: '+JSON.stringify(obj2));
// 一覧の取得
var val = random(0, 100);
var key = 'key'+val;
table2.set(key, val);
var keys = table2.keys(true);
while (keys.hasNext()) {
var key = keys.next();
WScript.Echo(key+': '+table2.get(key));
}
table2.close();
table1.close();
}
db.close();
}
main();
})();
]]></script>
</job>
</package>
出力結果例>cscript dblite.wsf
pre: no data
now: 2018年6月13日 10:44:06
obj1: {"aaa":"AAA","bbb":"bbb"}
obj2: {"aaa":"AAA","bbb":"bbb"}
key60: 60
>cscript dblite.wsf
pre: 2018年6月13日 10:44:06
now: 2018年6月13日 10:44:11
obj1: {"aaa":"AAA","bbb":"bbb"}
obj2: {"aaa":"AAA","bbb":"bbb"}
key60: 60
key66: 66
>cscript dblite.wsf
pre: 2018年6月13日 10:44:11
now: 2018年6月13日 10:44:15
obj1: {"aaa":"AAA","bbb":"bbb"}
obj2: {"aaa":"AAA","bbb":"bbb"}
key60: 60
key66: 66
key68: 68
参考リンク
DBLite.js
GitHubで公開しました。最新版は、k08045kk/WSHLibraryから取得してください。
DBLite.js/*!
* DBLite.js v3
*
* Copyright (c) 2018 toshi
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
*/
/**
* 簡易データベース
* SQLiteを使用した簡易データベース、
* キーバリュー方式で使用できることを目標とする。
* DBやSQL文を意識しなくても使用できることを目標とする。
* [SQLite ODBC Driver]のインストールが別途必要です。
* @requires module:ActiveXObject('Scripting.FileSystemObject')
* @requires module:ActiveXObject('ADODB.Command')
* @requires module:ActiveXObject("ADODB.Connection")
* @requires module:JSON
* @requires Console.js
* @requires ErrorUtility.js
* @auther toshi(https://www.bugbugnow.net/)
* @license MIT License
* @version 3
* @see 1.20180611 - add - 初版
* @see 2.20180723 - fix - パス長が規定値を超えた場合、エラーする
* @see 3.20190927 - update - keysIterator, valuesIteratorを追加
*/
(function(root, factory) {
if (!root.DBLite) {
root.DBLite = factory(root.JSON,
root.Console);
}
})(this, function DBLite_factory(JSON, Console) {
"use strict";
var fs = new ActiveXObject('Scripting.FileSystemObject');
var _this = void 0;
/**
* PrivateUnderscore.js
* @version 5
*/
{
function _isObject(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
function _isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
function _FileUtility_createFolder(folderpath) {
var ret = false,
fullpath = fs.GetAbsolutePathName(folderpath);
if (!(fs.FolderExists(fullpath) || fs.FileExists(fullpath))) {
var parentpath = fs.GetParentFolderName(fullpath);
if (parentpath != '') {
_FileUtility_createFolder(fs.GetParentFolderName(fullpath));
}
try {
fs.CreateFolder(fullpath);
ret = true;
} catch (e) {
// ファイルが見つかりません(パス長問題) || パスが見つかりません(パス不正 || 存在しない)
}
}
return ret;
};
function _FileUtility_createFileFolder(filepath) {
var ret = false;
var fullpath = fs.GetAbsolutePathName(filepath);
var parentpath= fs.GetParentFolderName(fullpath);
if (parentpath != '') {
ret = _FileUtility_createFolder(parentpath);
}
return ret;
};
}
_this = function DBLite_constructor() {
this.initialize.apply(this, arguments);
};
function createTablesCommand(_this) { // テーブル一覧取得
return ["SELECT name FROM sqlite_master WHERE type = 'table';"];
};
function createSchemaCommand(_this, table) { // スキーマ取得
return ["SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?;", table];
};
function createCreateTableCommand(_this, table) {
return ["CREATE TABLE IF NOT EXISTS ["+table+"] (" // (存在しない場合に、)テーブル作成
+ _this.field.key+" TEXT NOT NULL UNIQUE, " // 文字列(NULLなし, 重複なし)
+ _this.field.val+" TEXT);"]; // 文字列
};
function createDropTableCommand(_this, table) { // (存在する場合に、)テーブル削除
return ["DROP TABLE IF EXISTS ["+table+"];"];
};
function createReplaceCommand(_this, table, key, val) { // レコードの置き換え
return ["REPLACE INTO ["+table+"]"
+ " ("+_this.field.key+", "+_this.field.val+") VALUES (?, ?);", key, val];
};
function createInsertCommand(_this, table, key, val) { // レコード挿入(ある場合、無処理)
return ["INSERT OR IGNORE INTO ["+table+"]"
+ " ("+_this.field.key+", "+_this.field.val+") VALUES (?, ?);", key, val];
};
function createSelectValueCommand(_this, table, key) { // 値の取得
return ["SELECT "+_this.field.val+" FROM ["+table+"]"
+ " WHERE "+_this.field.key+" = ?;", key];
};
function createSelectExistsCommand(_this, table, field, fieldValue) { // 条件合致の最初1件取得
return ["SELECT "+_this.field.key+" FROM ["+table+"]"
+ " WHERE "+field+" = ? LIMIT 1;", fieldValue];
};
function createSelectCountCommand(_this, table) { // レコード数の取得
return ["SELECT COUNT("+_this.field.key+") FROM ["+table+"];"];
};
function createSelectKeysCommand(_this, table, limit, offset) { // 鍵一覧の取得
return ["SELECT ALL "+_this.field.key+" FROM ["+table+"]"
+ ((limit !== void 0) ? " LIMIT " +limit : "")
+ ((offset !== void 0) ? " OFFSET "+offset: "")
+ ";"];
};
function createSelectUniqValuesCommand(_this, table, limit, offset) { // ユニークな値一覧取得
return ["SELECT DISTINCT "+_this.field.val+" FROM ["+table+"]"
+ ((limit !== void 0) ? " LIMIT " +limit : "")
+ ((offset !== void 0) ? " OFFSET "+offset: "")
+ ";"];
};
function createDeleteCommand(_this, table, key) { // レコードの削除
return ["DELETE FROM ["+table+"] WHERE "+_this.field.key+" = ?;", key];
};
/**
* コマンド作成
* @private
* @param {Array} command - コマンド([コマンド文字列, 引数...])
* @return {ADODB.Command} 結果
*/
function createCmd(_this, command) {
var cmd = null; // ADODB.Command
try {
cmd = new ActiveXObject('ADODB.Command'); // 「Command」オブジェクト生成
cmd.ActiveConnection = _this.con; // 「Connection」オブジェクト設定
cmd.CommandType = 1; // コマンドタイプをテキスト(1)に設定
cmd.Prepared = true; // 「Prepared」を真に設定
// 発行するコマンド文字列(SQL文)を設定
cmd.CommandText = command[0]; // コマンドを設定
for (var i=1; i<command.length; i++) {
cmd.Parameters(i-1).Value = command[i]; // 引数を設定
}
} catch (e) {
if (_this.console) _this.console.errorStackTrace(e);
cmd = null;
}
return cmd;
}
/**
* データベースレコードセットの反復子
*/
var Iterator = (function DBLite$Iterator_factory() {
"use strict";
var _this = function DBLite$Iterator_constructor() {
this.initialize.apply(this, arguments);
};
/**
* コンストラクタ
* @param {ADODB.Recordset} rs - レコードセット
*/
_this.prototype.initialize = function DBLite$Iterator_initialize(master, rs) {
this.master = master;
this.rs = rs; // ADODB.Recordset
this.count = 0;
this.fields = []; // フィールド名一覧
try {
for (var f=0; f<this.rs.Fields.Count; f++) { // フィールド数分ループ
this.fields.push(this.rs.Fields(f).Name);
}
} catch (e) {}
};
/**
* クローズ
* クローズ後、hasNext()は、falseを返します。
*/
_this.prototype.close = function DBLite$Iterator_close() {
if (this.rs !== null) {
try {
if (this.rs.State > 0) { // 開いている場合
this.rs.Close();
}
} catch (e) {
if (this.master && this.master.console) this.master.console.errorStackTrace(e);
} finally {
this.rs = null; // レコードセットを開放
this.master = null;
}
}
};
/**
* 次があるか
* 次のレコードがある場合、trueを返します。
* 次のレコードがない場合、Recordsetをクローズします。
* @return {boolean} 結果
*/
_this.prototype.hasNext = function DBLite$Iterator_hasNext() {
var ret = false;
if (this.rs !== null) {
ret = !this.rs.EOF;
if (ret === false) { // 次がない時
this.close(); // 閉じる
}
}
return ret;
};
/**
* 次のレコードへ
* フィールドが1つの場合、値を返します。
* フィールドが2つ以上の場合、コンテナに値を格納します。
* 次のレコードがない場合、Recordsetをクローズします。
* @param {Object} container - コンテナ
* @return {boolean|string} 結果
* コンテナありの場合、false:失敗/true:成功
* コンテナなしの場合、null:失敗/string:成功
*/
_this.prototype.next = function DBLite$Iterator_next(containar) {
var ret = (_isObject(containar))? false: null; // コンテナあり:false/コンテナなし:null
try {
if (this.hasNext()) {
if (containar !== void 0) { // コンテナありの時
for (var f=0; f<this.rs.Fields.Count; f++) {// フィールド数分ループ
containar[this.rs.Fields(f).Name].push(this.rs.Fields(f).Value);
}
ret = true;
} else if (this.rs.Fields.Count === 1) { // フィールドが1つの時
ret = this.rs.Fields(0).Value;
}
this.count++; // カウンタを進める
this.rs.MoveNext(); // 次へ進める
}
} catch (e) {
if (this.master && this.master.console) this.master.console.errorStackTrace(e);
this.close();
}
return ret;
};
/**
* コンテナ作成
* フィールド名を鍵とする、空の配列を格納したオブジェクトを返します。
* next関数の引数として使用します。
* @return {Object} container - コンテナ
*/
_this.prototype.container = function DBLite$Iterator_container(obj) {
if (obj == null) obj = {} // 既定値(={})
for (var f=0; f<this.fields.length; f++) {// フィールド数分ループ
if (obj[this.fields[f]] === void 0) { // フィールドがない時
obj[this.fields[f]] = [];
}
}
return obj;
};
/**
* 要素の取得数
* next関数によって、いままでに取得した個数を返します。
* @return {number} カウンタ
*/
_this.prototype.counter = function DBLite$Iterator_counter() {
return this.count;
};
return _this;
})();
/**
* コンストラクタ
* @constructor
* @param {string} path - データベースのパス(相対パスで指定可能)
*/
_this.prototype.initialize = function DBLite_initialize(path) {
this.field = {"key":"key","val":"val"}; // フィールドの名称
this.con = null; // ADODB.Connection
this.fullpath = fs.GetAbsolutePathName(path); // ファイルの絶対パス
this.stack = {}; // コマンドのスタック
this.console = void 0; // エラー出力用コンソール
if (Console) {
this.console = Console.getConsole();
}
};
/**
* オープン
* @return {boolean} 結果(true:接続成功or接続済み)
*/
_this.prototype.open = function DBLite_open() {
var ret = false;
try {
if (this.con === null) {
_FileUtility_createFileFolder(this.fullpath); // フォルダを作成
// SQLiteにドライバ経由で接続
// <http://www.ch-werner.de/sqliteodbc/>のドライバが必要
this.con = new ActiveXObject("ADODB.Connection");
this.con.ConnectionString = // 接続文字列設定
"DRIVER=SQLite3 ODBC Driver;" // ODBCドライバ
+ "DATABASE="+this.fullpath+";"; // データベース
this.con.Open(); // 接続開始
ret = true;
} else {
ret = (this.con.State > 0); // 接続中の時
}
} catch (e) {
if (this.console) this.console.errorStackTrace(e);
ret = false;
}
return ret;
};
/**
* クローズ
* pushの残りを書き込む。
* @return {boolean} 結果(true切断成功or未接続)
*/
_this.prototype.close = function DBLite_close() {
var ret = false;
try {
if (this.con !== null) {
if (this.con.State > 0) { // 接続中の時
this.flushAll(); // push済みのデータを書き込み
this.con.Close(); // 切断
}
this.con = null; // 開放
}
ret = true;
} catch (e) {
if (this.console) this.console.errorStackTrace(e);
}
return ret;
};
/**
* コマンド実行
* Iteratorは、0件ヒットの可能性がある。
* @param {boolean} isResult - 結果の出力有無
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
* @return {(boolean|Object)} 結果(null|true|Iterator)
*/
_this.prototype.execute = function DBLite_execute(command) {
var ret = null;
if (this.con === null || this.con.State === 0) { // 未接続
return ret;
}
var cmd = null; // ADODB.Command
var rs = null; // ADODB.Recordset
try {
cmd = createCmd(this, command); // ADODB.Command作成
rs = cmd.Execute(); // 実行
if (rs.State > 0) { // レコードがある時(戻り値ありの時)
ret = new Iterator(this, rs);
} else {
ret = true; // 戻り値なしの実行結果
}
} catch (e) {
if (this.console) this.console.errorStackTrace(e);
ret = null;
} finally {
rs = null;
cmd = null;
}
return ret;
};
/**
* トランザクションあり複数コマンド実行
* 引数に設定した、コマンドをすべて実行する。
* 処理は、トランザクションで行うため、失敗するとロールバックする。
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
* @return {boolean} 結果
*/
_this.prototype.exec = function DBLite_exec(command_args) {
var ret = false,
i = 0,
command = null;
try {
if (this.open()) { // 接続
this.con.BeginTrans(); // トランザクション開始
for (i=0; i<arguments.length; i++) {
command = arguments[i];
if (this.execute(command) !== true) { // 失敗の時
throw null;
}
}
this.con.CommitTrans(); // トランザクション、コミット
ret = true;
}
} catch (e1) {
e1.message += "\n" + i+"/"+arguments.length+":"+JSON.stringify(command);
if (this.console) this.console.errorStackTrace(e1);
try {
this.con.RollbackTrans(); // トランザクション、ロールバック
} catch (e2) {
e2.message += "\n" + "RollbackTrans";
if (this.console) this.console.errorStackTrace(e2);
}
}
return ret;
};
/**
* 反復子作成
* コマンドの結果を反復子として返します。
* 反復子は、hasNext()がfalseを返す。
* または、明示的にclose()を実施する必要があります。終了処理が必要です。
* iteratorは、取得時のDBの状態を返します。
* そのため、取得後に挿入/削除があっても挿入/削除前の値を返します。
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
* @return {Iterator} Iterator
*/
_this.prototype.iterator = function DBLite_iterator(command) {
var ret = null;
if (this.open()) { // 接続
var ite = this.execute(command); // コマンド実行
if (ite && ite !== true && ite.constructor === Iterator) {
ret = ite; // レコードがある時
}
}
return (ret !== null)? ret: new Iterator(this, null); // 取得失敗時は、空の反復子を返す
};
/**
* データ参照(単数)
* 取得レコードが1つである場合、値を返します。
* コンテナ(空のオブジェクト)を指定した場合、コンテナに結果を格納します。
* ただし、成功/失敗に関わらず、コンテナに値を格納するため、戻り値で成功/失敗を判定します。
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
* @param {Object} container - コンテナ
* @return {(boolean|number|string)} 結果
* コンテナありの場合、成功:true/失敗:false
* コンテナなしの場合、成功:値/失敗:null
*/
_this.prototype.select = function DBLite_select(command, container) {
var ret = (container !== void 0)? false: null; // コンテナあり:false, なし:null
var ite = this.iterator(command); // 反復子取得
if (container !== void 0) { // コンテナがある時
ite.container(container); // コンテナを初期化
}
var obj = ite.next(container); // 1番目を取得
if ((container !== void 0 && obj === true) // コンテナあり成功の時
|| (container === void 0 && obj !== null)) { // コンテンなし成功の時
if (!ite.hasNext()) { // 2番目がない時
ret = obj;
}
}
ite.close(); // 明示的に閉じる
ite = null;
return ret;
};
/**
* データ参照(複数)
* 取得レコードを配列として返します。
* コンテナ(空のオブジェクト)を指定した場合、コンテナに結果を格納します。
* ただし、成功/失敗に関わらず、コンテナに値を格納するため、戻り値で成功/失敗を判定します。
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
* @param {Object} container - コンテナ
* @return {(boolean|Array)} 結果
* コンテナありの場合、成功:true/失敗:false
* コンテナなしの場合、成功:値/失敗:null
*/
_this.prototype.selects = function DBLite_selects(command, container) {
var ret = (container !== void 0)? false: [];// コンテナあり:false, なし:null
var ite = this.iterator(command); // 反復子取得
if (container !== void 0) { // コンテナがある時
ite.container(container); // コンテナを初期化
}
var obj = ite.next(container); // 1番目を取得
if (container !== void 0 && obj === true) { // コンテナあり成功の時
while (ite.next(container)); // コンテナに格納
ret = true;
}
if (container === void 0 && obj !== null) { // コンテナなし成功の時
ret = [obj];
while ((obj=ite.next()) !== null) { // 末尾までループ
ret.push(obj); // 配列に格納
}
}
ite.close(); // 明示的に閉じる
ite = null;
return ret;
};
/**
* 作成済みのテーブル名を取得
* @return {Array} テーブル名一覧
*/
_this.prototype.getTableNames = function DBLite_getTableNames() {
return this.selects(createTablesCommand(this));
};
/**
* テーブル有無
* @param {string} name - テーブル名
* @return {boolean} 結果
*/
_this.prototype.existsTable = function DBLite_existsTable(name) {
return (this.select(createSchemaCommand(this, name)) !== null);
};
/**
* テーブル追加
* @param {string} name - テーブル名
* @return {TableLite} TableLite
*/
_this.prototype.getTable =
_this.prototype.createTable = function DBLite_createTable(name) {
return (this.exec(createCreateTableCommand(this, name)) === true)?
new TableLite(this, name):
null;
};
/**
* テーブル削除
* @param {string} name - テーブル名
* @return {boolean} 結果
*/
_this.prototype.deleteTable =
_this.prototype.dropTable = function DBLite_dropTable(name) {
return this.exec(createDropTableCommand(this, name));
};
/**
* 鍵がテーブルに含まれるか
* @param {string} table - テーブル名
* @param {string} key - 鍵
* @return {boolean} 結果
*/
_this.prototype.containsKey = function DBLite_containsKey(table, key) {
var command = createSelectExistsCommand(this, table, this.field.key, key);
return (this.select(command) !== null);
};
/**
* 値がテーブルに含まれるか
* @param {string} table - テーブル名
* @param {Object} val - 値
* @return {boolean} 結果
*/
_this.prototype.containsValue = function DBLite_containsValue(table, val) {
var command = createSelectExistsCommand(this, table, this.field.val, JSON.stringify(val));
return (this.select(command) !== null);
};
/**
* 鍵がテーブルに含まれるか
* containsKey関数のラップ関数
* @param {string} table - テーブル名
* @param {string} key - 鍵
* @return {boolean} 結果
*/
_this.prototype.contains = function DBLite_contains(table, key) {
return this.containsKey(table, key);
};
/**
* 値の設定
* 鍵と値を配列とした場合、配列内の要素を鍵と値として複数設定する。
* 処理はトランザクションとして実行するため、1つでも失敗すると未処理となります。
* 本関数を短時間に大量に呼び出した場合、
* 呼び出し毎にファイルアクセスが発生するため、遅延が発生します。
* 短時間に大量に呼び出す場合、push, flush関数の使用をおすすめします。
* @param {string} table - テーブル名
* @param {(string|Array)} key - 鍵
* @param {(Object|Array)} val - 値
* @param {boolean} [overwrite=true] - 上書き有無
* @return {boolean} 結果
*/
_this.prototype.set = function DBLite_set(table, key, val, overwrite) {
if (!_isArray(key)) { // 配列でない時
key = [key]; // 配列化
val = [val];
}
var createCommand = (overwrite !== false)? createReplaceCommand: createInsertCommand;
var commands = [];
for (var i=0; i<key.length; i++) {
commands.push(createCommand(this, table, key[i], JSON.stringify(val[i])));
}
return this.exec.apply(this, commands);
};
/**
* 値の取得
* @param {string} table - テーブル名
* @param {string} key - 鍵
* @param {Object} def - 取得失敗時の値
* @return {Object} 値 or 取得失敗時の値
*/
_this.prototype.get = function DBLite_get(table, key, def) {
var text = this.select(createSelectValueCommand(this, table, key));
return (text !== null) ? JSON.parse(text): def;
};
/**
* レコード件数
* @param {string} table - テーブル名
* @return {number} レコードの件数
*/
_this.prototype.size = function DBLite_size(table) {
return this.select(createSelectCountCommand(this, table));
};
/**
* 鍵の配列
* 取得する鍵の配列が大きい場合、メモリ領域を圧迫することに注意してください。
* 取得する鍵の配列が大きい場合、Iteratorの使用をおすすめします。
* 注意:Iterator使用の場合、専用関数を使用してください。limit=trueは、廃止の可能性があります。
* @param {string} table - テーブル名
* @param {string} key - 鍵
* @param {(boolean|number)} limit - 取得最大レコード数(trueならば、戻り値(Iterator))
* @param {number} offset - レコード取得開始位置
* @return {Array} 鍵の配列 or null
*/
_this.prototype.keys = function DBLite_keys(table, limit, offset) {
return (limit === true) ?
this.iterator(createSelectKeysCommand(this, table)): // true: Iterator
this.selects(createSelectKeysCommand(this, table, limit, offset)); // true以外: 配列
};
_this.prototype.keysIterator = function DBLite_keysIterator(table, limit, offset) {
return this.iterator(createSelectKeysCommand(this, table, limit, offset));
};
/**
* ユニークな値の配列
* 同一の値をまとめて、ユニークな配列を返します。
* 注意:Iterator使用の場合、専用関数を使用してください。limit=trueは、廃止の可能性があります。
* @param {string} table - テーブル名
* @param {string} key - 鍵
* @param {(boolean|number)} limit - 取得最大レコード数(trueならば、戻り値(Iterator))
* @param {number} offset - レコード取得開始位置
* @return {Array} 値の配列 or null
*/
_this.prototype.values = function DBLite_values(table, limit, offset) {
var ret = null;
if (limit === true) {
ret = this.iterator(createSelectUniqValuesCommand(this, table));
} else {
var vals = this.selects(createSelectUniqValuesCommand(this, table, limit, offset));
ret = [];
for (var i=0; i<vals.length; i++) {
ret.push(JSON.parse(vals[i])); // オブジェクトに復元
}
}
return ret;
};
_this.prototype.valuesIterator = function DBLite_valuesIterator(table, limit, offset) {
return this.iterator(createSelectUniqValuesCommand(this, table, limit, offset));
};
/**
* レコード削除
* @param {string} table テーブル名
* @param {string} key - 鍵
* @return {boolean} 結果
*/
_this.prototype.del = function DBLite_del(table, key) {
return this.exec(createDeleteCommand(this, table, key));
};
/**
* スタック追加
* 追加したコマンドは、flush()で実行します。
* close()時に、すべてのコマンドをflush()します。(成功を保証するものではありません)
* 補足:set関数では、set毎にファイルアクセスが発生するため、処理が遅い。
* @param {string} table - テーブル名
* @param {Array} command - コマンド([コマンド文字列, 引数, ...])
*/
_this.prototype.pushCommand = function DBLite_pushCommand(table, command) {
if (this.stack[table] === void 0) this.stack[table] = []; // 未使用時に配列を準備
this.stack[table].push(command); // コマンドを登録
};
_this.prototype.pushSet = function DBLite_pushSet(table, key, val, overwrite) {
var createCommand = (overwrite !== false)? createReplaceCommand: createInsertCommand;
this.pushCommand(table, createCommand(this, table, key, JSON.stringify(val)));
};
_this.prototype.pushDel = function DBLite_pushDel(table, key) {
this.pushCommand(table, createDeleteCommand(this, table, key));
};
_this.prototype.push = function DBLite_push(table, key, val, overwrite) {
this.pushSet(table, key, val, overwrite);
};
/**
* スタック実行
* スタック内のコマンドを実行する。
* 限界値(cv)を設定した場合、限界値に達していなければ処理を行わない。
* @param {string} table - テーブル名
* @param {number} cv - 限界値
* @return {boolean} 結果(true/false:実行結果、null:未処理)
*/
_this.prototype.flush = function DBLite_flush(table, cv) {
var ret = true; // 未処理(=null)
if (this.stack[table] !== void 0) { // スタックがある時
if (cv === void 0 || cv <= this.stack[table].length) { // 臨界値以上の時
ret = this.exec.apply(this, this.stack[table]);
this.stack[table] = [];
// 補足:成功/失敗に関わらず、スタックをクリアする。
// 残しておいてもどっちみち次も失敗するため。
}
}
return ret;
};
_this.prototype.flushAll = function DBLite_flushAll() {
var ret = true; // 初期値
for (var table in this.stack) { // stackの鍵(テーブル名)でループ
ret = (this.flush(table) && ret); // flush実行(一度でも失敗(=false))
}
return ret;
};
var TableLite = (function DBLite$TableLite_factory() {
"use strict";
var _this = function DBLite$TableLite_constructor() {
this.initialize.apply(this, arguments);
};
/**
* テーブルアクセス用のIF
* @param {DBLite} master - 親クラス
* @param {string} name - テーブル名
*/
_this.prototype.initialize = function DBLite$TableLite_initialize(master, name) {
this.master = master;
this.name = name;
}
/**
* テーブル名取得
* @return {string} テーブル名
*/
_this.prototype.getName = function DBLite$TableLite_getName() {
return this.name;
};
/**
* テーブルを閉じる
*/
_this.prototype.close = function DBLite$TableLite_close() {
this.master = null;
this.name = null;
};
/**
* テーブル削除
* @return {boolean} 結果
*/
_this.prototype.drop = function DBLite$TableLite_drop() {
if (this.master.dropTable(this.name)) {
this.close();
}
return ret;
};
// DBLiteのラップ関数郡
_this.prototype.containsKey = function DBLite$TableLite_containsKey(key) {
return this.master.containsKey(this.name, key);
};
_this.prototype.containsValue = function DBLite$TableLite_containsValue(val) {
return this.master.containsValue(this.name, val);
};
_this.prototype.contains = function DBLite$TableLite_contains(key) {
return this.master.contains(this.name, key);
};
_this.prototype.set = function DBLite$TableLite_set(key, val, overwrite) {
return this.master.set(this.name, key, val, overwrite);
};
_this.prototype.get = function DBLite$TableLite_get(key, def) {
return this.master.get(this.name, key, def);
};
_this.prototype.del = function DBLite$TableLite_del(key) {
return this.master.del(this.name, key);
};
_this.prototype.size = function DBLite$TableLite_size() {
return this.master.size(this.name);
};
_this.prototype.keys = function DBLite$TableLite_keys(limit, offset) {
return this.master.keys(this.name, limit, offset);
};
_this.prototype.keysIterator = function DBLite$TableLite_keysIterator(limit, offset) {
return this.master.keysIterator(this.name, limit, offset);
};
_this.prototype.values = function DBLite$TableLite_values(limit, offset) {
return this.master.values(this.name, limit, offset);
};
_this.prototype.valuesIterator = function DBLite$TableLite_valuesIterator(limit, offset) {
return this.master.valuesIterator(this.name, limit, offset);
};
_this.prototype.pushCommand = function DBLite$TableLite_pushCommand(command) {
this.master.pushCommand(this.name, command);
};
_this.prototype.pushSet = function DBLite$TableLite_pushSet(key, val, overwrite) {
this.master.pushSet(this.name, key, val, overwrite);
};
_this.prototype.pushDel = function DBLite$TableLite_pushDel(key) {
this.master.pushDel(this.name, key);
};
_this.prototype.push = function DBLite$TableLite_push(key, val, overwrite) {
this.master.push(this.name, key, val, overwrite);
};
_this.prototype.flush = function DBLite$TableLite_flush(cv) {
return this.master.flush(this.name, cv);
};
return _this;
})();
return _this;
});
変更履歴
更新日 | 内容 |
---|---|
2018/06/13 | v1 - add - 初版 |
2018/07/25 | v2 - fix - パス長が規定値を超えた場合、エラーする |
2019/09/27 | v3 - update - keysIterator, valuesIteratorを追加 |