forked from dlang/cdcdb
Переход на другую библиотеку
This commit is contained in:
parent
1f50b21457
commit
0fc56e7c04
5 changed files with 180 additions and 148 deletions
2
dub.json
2
dub.json
|
@ -7,7 +7,7 @@
|
|||
"license": "BSL-1.0",
|
||||
"name": "cdcdb",
|
||||
"dependencies": {
|
||||
"arsd-official:sqlite": "~>12.0.0",
|
||||
"d2sqlite3": "~>1.0.0",
|
||||
"zstd": "~>0.2.1"
|
||||
},
|
||||
"stringImportPaths": [
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
"fileVersion": 1,
|
||||
"versions": {
|
||||
"arsd-official": "12.0.0",
|
||||
"d2sqlite3": "1.0.0",
|
||||
"zstd": "0.2.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module cdcdb.dblite;
|
||||
|
||||
import arsd.sqlite : Sqlite, SqliteResult, DatabaseException;
|
||||
import d2sqlite3;
|
||||
|
||||
import std.string : join, replace, toLower;
|
||||
import std.algorithm : canFind;
|
||||
|
@ -91,19 +91,29 @@ struct DBSnapshotChunkData {
|
|||
ubyte[32] zSha256; /// Хеш сжатого содержимого.
|
||||
}
|
||||
|
||||
final class DBLite : Sqlite
|
||||
final class DBLite
|
||||
{
|
||||
private:
|
||||
string _dbPath; /// Путь к файлу БД.
|
||||
size_t _maxRetries; /// Максимум повторов при `busy/locked`.
|
||||
Database _db; /// Соединение с БД (d2sqlite3).
|
||||
|
||||
// SQL-схема (массив строковых запросов).
|
||||
mixin(import("scheme.d"));
|
||||
|
||||
/// Выполняет SQL с повторными попытками при `locked/busy`.
|
||||
SqliteResult sql(T...)(string queryText, T args)
|
||||
ResultRange sql(T...)(string queryText, T args)
|
||||
{
|
||||
// Готовим стейтмент сами, чтобы bindAll() работал и для BLOB.
|
||||
auto attempt = () {
|
||||
auto st = _db.prepare(queryText);
|
||||
static if (T.length > 0)
|
||||
st.bindAll(args);
|
||||
return st.execute();
|
||||
};
|
||||
|
||||
if (_maxRetries == 0) {
|
||||
return cast(SqliteResult) query(queryText, args);
|
||||
return attempt();
|
||||
}
|
||||
|
||||
string msg;
|
||||
|
@ -111,10 +121,11 @@ private:
|
|||
|
||||
while (tryNo) {
|
||||
try {
|
||||
return cast(SqliteResult) query(queryText, args);
|
||||
} catch (DatabaseException e) {
|
||||
return attempt();
|
||||
} catch (SqliteException e) {
|
||||
msg = e.msg;
|
||||
if (msg.toLower.canFind("locked", "busy")) {
|
||||
const code = e.code;
|
||||
if (code == SQLITE_BUSY || code == SQLITE_LOCKED) {
|
||||
if (--tryNo == 0) {
|
||||
throw new Exception(
|
||||
"Не удалось выполнить запрос к базе данных после %d неудачных попыток: %s"
|
||||
|
@ -123,17 +134,18 @@ private:
|
|||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
break; // другие ошибки — дальше по стеку
|
||||
}
|
||||
}
|
||||
throw new Exception(msg);
|
||||
// До сюда не дойдём, но для формальной полноты:
|
||||
throw new Exception(msg.length ? msg : "SQLite error");
|
||||
}
|
||||
|
||||
/// Проверяет наличие обязательных таблиц.
|
||||
/// Если все отсутствуют — создаёт схему; если отсутствует часть — бросает ошибку.
|
||||
void check()
|
||||
{
|
||||
SqliteResult queryResult = sql(
|
||||
auto queryResult = sql(
|
||||
q{
|
||||
WITH required(name)
|
||||
AS (VALUES ("snapshots"), ("blobs"), ("snapshot_chunks"), ("users"), ("processes"), ("files"))
|
||||
|
@ -151,7 +163,7 @@ private:
|
|||
|
||||
foreach (row; queryResult)
|
||||
{
|
||||
missingTables ~= row["missing_table"].to!string;
|
||||
missingTables ~= row["missing_table"].as!string;
|
||||
}
|
||||
|
||||
enforce(missingTables.length == 0 || missingTables.length == 6,
|
||||
|
@ -171,16 +183,16 @@ public:
|
|||
this(string database, size_t busyTimeout, size_t maxRetries)
|
||||
{
|
||||
_dbPath = database;
|
||||
super(database);
|
||||
_db = Database(database);
|
||||
|
||||
check();
|
||||
|
||||
_maxRetries = maxRetries;
|
||||
|
||||
query("PRAGMA journal_mode=WAL");
|
||||
query("PRAGMA synchronous=NORMAL");
|
||||
query("PRAGMA foreign_keys=ON");
|
||||
query("PRAGMA busy_timeout=%d".format(busyTimeout));
|
||||
_db.execute("PRAGMA journal_mode=WAL");
|
||||
_db.execute("PRAGMA synchronous=NORMAL");
|
||||
_db.execute("PRAGMA foreign_keys=ON");
|
||||
_db.execute("PRAGMA busy_timeout=%d".format(busyTimeout));
|
||||
}
|
||||
|
||||
/// BEGIN IMMEDIATE.
|
||||
|
@ -192,13 +204,13 @@ public:
|
|||
/// COMMIT.
|
||||
void commit()
|
||||
{
|
||||
sql("COMMIT");
|
||||
_db.commit();
|
||||
}
|
||||
|
||||
/// ROLLBACK.
|
||||
void rollback()
|
||||
{
|
||||
sql("ROLLBACK");
|
||||
_db.rollback();
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
|
@ -218,8 +230,8 @@ public:
|
|||
{
|
||||
DBFile file;
|
||||
|
||||
file.id = cast(ubyte[]) row["id"].dup;
|
||||
file.path = row["name"].to!string;
|
||||
file.id = row["id"].as!Blob(Blob.init);
|
||||
file.path = row["name"].as!string;
|
||||
|
||||
files ~= file;
|
||||
}
|
||||
|
@ -236,10 +248,10 @@ public:
|
|||
|
||||
DBFile file;
|
||||
|
||||
if (!queryResult.empty()) {
|
||||
auto data = queryResult.front();
|
||||
if (!queryResult.empty) {
|
||||
auto data = queryResult.front;
|
||||
|
||||
file.id = cast(ubyte[]) data["id"].dup;
|
||||
file.id = data["id"].as!Blob(Blob.init);
|
||||
file.path = path;
|
||||
}
|
||||
|
||||
|
@ -257,18 +269,18 @@ public:
|
|||
|
||||
DBFile file;
|
||||
|
||||
if (!queryResult.empty()) {
|
||||
auto data = queryResult.front();
|
||||
if (!queryResult.empty) {
|
||||
auto data = queryResult.front;
|
||||
|
||||
file.id = id;
|
||||
file.path = data["name"].to!string;
|
||||
file.path = data["name"].as!string;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
DBFile addFile(string path) {
|
||||
SqliteResult queryResult;
|
||||
ResultRange queryResult;
|
||||
UUID uuid;
|
||||
|
||||
// Исключение одинакового UUID первичного ключа
|
||||
|
@ -279,7 +291,7 @@ public:
|
|||
SELECT id FROM files WHERE id = ?1
|
||||
}, uuid.data[]
|
||||
);
|
||||
} while (!queryResult.empty());
|
||||
} while (!queryResult.empty);
|
||||
|
||||
queryResult = sql(
|
||||
q{
|
||||
|
@ -289,7 +301,7 @@ public:
|
|||
}, uuid.data[], path
|
||||
);
|
||||
|
||||
enforce(!queryResult.empty(), "Не удалось добавить новый файл в базу данных");
|
||||
enforce(!queryResult.empty, "Не удалось добавить новый файл в базу данных");
|
||||
|
||||
return DBFile(Identifier(uuid.data), path);
|
||||
}
|
||||
|
@ -307,8 +319,8 @@ public:
|
|||
{
|
||||
DBFile file;
|
||||
|
||||
file.id = cast(ubyte[]) row["id"].dup;
|
||||
file.path = row["name"].to!string;
|
||||
file.id = row["id"].as!Blob(Blob.init);
|
||||
file.path = row["name"].as!string;
|
||||
|
||||
files ~= file;
|
||||
}
|
||||
|
@ -339,8 +351,8 @@ public:
|
|||
{
|
||||
DBFile file;
|
||||
|
||||
file.id = cast(ubyte[]) row["id"].dup;
|
||||
file.path = row["name"].to!string;
|
||||
file.id = row["id"].as!Blob(Blob.init);
|
||||
file.path = row["name"].as!string;
|
||||
|
||||
files ~= file;
|
||||
}
|
||||
|
@ -350,12 +362,12 @@ public:
|
|||
|
||||
bool deleteFile(Identifier id) {
|
||||
auto queryResult = sql("DELETE FROM files WHERE id = ?1 RETURNING id", id[]);
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
bool deleteFile(string path) {
|
||||
auto queryResult = sql("DELETE FROM files WHERE name = ?1 RETURNING id", path);
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -376,8 +388,8 @@ public:
|
|||
}, id[], sha256[]
|
||||
);
|
||||
|
||||
if (!queryResult.empty())
|
||||
return queryResult.front()["is_last"].to!long > 0;
|
||||
if (!queryResult.empty)
|
||||
return queryResult.front["is_last"].as!long > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -393,7 +405,7 @@ public:
|
|||
}, uid, name
|
||||
);
|
||||
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
DBProcess getProcess(string name) {
|
||||
|
@ -405,10 +417,10 @@ public:
|
|||
|
||||
DBProcess process;
|
||||
|
||||
if (!queryResult.empty()) {
|
||||
auto data = queryResult.front();
|
||||
if (!queryResult.empty) {
|
||||
auto data = queryResult.front;
|
||||
|
||||
process.id = cast(ubyte[]) data["id"].dup;
|
||||
process.id = data["id"].as!Blob(Blob.init);
|
||||
process.name = name;
|
||||
}
|
||||
|
||||
|
@ -426,18 +438,18 @@ public:
|
|||
|
||||
DBProcess process;
|
||||
|
||||
if (!queryResult.empty()) {
|
||||
auto data = queryResult.front();
|
||||
if (!queryResult.empty) {
|
||||
auto data = queryResult.front;
|
||||
|
||||
process.id = id;
|
||||
process.name = data["name"].to!string;
|
||||
process.name = data["name"].as!string;
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
DBProcess addProcess(string name) {
|
||||
SqliteResult queryResult;
|
||||
ResultRange queryResult;
|
||||
UUID uuid;
|
||||
|
||||
// Исключение одинакового UUID первичного ключа
|
||||
|
@ -448,7 +460,7 @@ public:
|
|||
SELECT id FROM processes WHERE id = ?1
|
||||
}, uuid.data[]
|
||||
);
|
||||
} while (!queryResult.empty());
|
||||
} while (!queryResult.empty);
|
||||
|
||||
queryResult = sql(
|
||||
q{
|
||||
|
@ -458,7 +470,7 @@ public:
|
|||
}, uuid.data[], name
|
||||
);
|
||||
|
||||
enforce(!queryResult.empty(), "Не удалось добавить новый файл в базу данных");
|
||||
enforce(!queryResult.empty, "Не удалось добавить новый файл в базу данных");
|
||||
|
||||
return DBProcess(Identifier(uuid.data), name);
|
||||
}
|
||||
|
@ -467,7 +479,7 @@ public:
|
|||
|
||||
bool addSnapshot(ref DBSnapshot snapshot)
|
||||
{
|
||||
SqliteResult queryResult;
|
||||
ResultRange queryResult;
|
||||
UUID uuid;
|
||||
|
||||
// Исключение одинакового UUID первичного ключа
|
||||
|
@ -478,7 +490,7 @@ public:
|
|||
SELECT id FROM snapshots WHERE id = ?1
|
||||
}, uuid.data[]
|
||||
);
|
||||
} while (!queryResult.empty());
|
||||
} while (!queryResult.empty);
|
||||
|
||||
import std.datetime : Clock;
|
||||
|
||||
|
@ -524,7 +536,7 @@ public:
|
|||
snapshot.status.to!int // ?15
|
||||
);
|
||||
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -564,7 +576,7 @@ public:
|
|||
blob.zstd.to!int // ?8
|
||||
);
|
||||
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
bool addSnapshotChunk(DBSnapshotChunk snapshotChunk)
|
||||
|
@ -581,7 +593,7 @@ public:
|
|||
snapshotChunk.sha256[]
|
||||
);
|
||||
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
|
||||
DBSnapshotChunkData[] getChunks(Identifier id)
|
||||
|
@ -603,14 +615,22 @@ public:
|
|||
{
|
||||
DBSnapshotChunkData sdch;
|
||||
|
||||
sdch.chunkIndex = row["chunk_index"].to!long;
|
||||
sdch.offset = row["offset"].to!long;
|
||||
sdch.size = row["size"].to!long;
|
||||
sdch.content = cast(ubyte[]) row["content"].dup;
|
||||
sdch.zstd = cast(bool) row["zstd"].to!int;
|
||||
sdch.zSize = row["z_size"].to!long;
|
||||
sdch.sha256 = cast(ubyte[]) row["sha256"].dup;
|
||||
sdch.zSha256 = cast(ubyte[]) row["z_sha256"].dup;
|
||||
sdch.chunkIndex = row["chunk_index"].as!long;
|
||||
sdch.offset = row["offset"].as!long;
|
||||
sdch.size = row["size"].as!long;
|
||||
|
||||
// content может быть NULL
|
||||
auto contentBlob = cast(ubyte[]) row["content"].as!Blob(Blob.init);
|
||||
sdch.content = contentBlob.length ? contentBlob.dup : null;
|
||||
|
||||
sdch.zstd = row["zstd"].as!int != 0;
|
||||
sdch.zSize = row["z_size"].as!long;
|
||||
|
||||
auto sha = cast(ubyte[]) row["sha256"].as!Blob(Blob.init);
|
||||
if (sha.length) sdch.sha256[] = sha;
|
||||
|
||||
auto zsha = cast(ubyte[]) row["z_sha256"].as!Blob(Blob.init);
|
||||
if (zsha.length) sdch.zSha256[] = zsha;
|
||||
|
||||
sdchs ~= sdch;
|
||||
}
|
||||
|
@ -657,28 +677,28 @@ public:
|
|||
{
|
||||
DBSnapshot snapshot;
|
||||
|
||||
snapshot.id = cast(ubyte[]) row["id"].dup;
|
||||
snapshot.id = row["id"].as!Blob(Blob.init);
|
||||
snapshot.file = DBFile(
|
||||
Identifier(cast(ubyte[]) row["file_id"].dup),
|
||||
row["file_name"].to!string
|
||||
Identifier(row["file_id"].as!Blob(Blob.init)),
|
||||
row["file_name"].as!string
|
||||
);
|
||||
snapshot.sha256 = cast(ubyte[]) row["sha256"].dup;
|
||||
snapshot.description = row["description"].to!string;
|
||||
snapshot.createdUtc = row["created_utc"].to!long;
|
||||
snapshot.sourceLength = row["source_length"].to!long;
|
||||
snapshot.algoMin = row["algo_min"].to!long;
|
||||
snapshot.algoNormal = row["algo_normal"].to!long;
|
||||
snapshot.algoMax = row["algo_max"].to!long;
|
||||
snapshot.maskS = row["mask_s"].to!long;
|
||||
snapshot.maskL = row["mask_l"].to!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].to!int;
|
||||
snapshot.uid = row["uid"].to!long;
|
||||
snapshot.ruid = row["ruid"].to!long;
|
||||
snapshot.uidName = row["uid_name"].to!string;
|
||||
snapshot.ruidName = row["ruid_name"].to!string;
|
||||
snapshot.sha256 = row["sha256"].as!Blob(Blob.init);
|
||||
snapshot.description = row["description"].as!string(""); // может быть NULL
|
||||
snapshot.createdUtc = row["created_utc"].as!long;
|
||||
snapshot.sourceLength = row["source_length"].as!long;
|
||||
snapshot.algoMin = row["algo_min"].as!long;
|
||||
snapshot.algoNormal = row["algo_normal"].as!long;
|
||||
snapshot.algoMax = row["algo_max"].as!long;
|
||||
snapshot.maskS = row["mask_s"].as!long;
|
||||
snapshot.maskL = row["mask_l"].as!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].as!int;
|
||||
snapshot.uid = row["uid"].as!long;
|
||||
snapshot.ruid = row["ruid"].as!long;
|
||||
snapshot.uidName = row["uid_name"].as!string;
|
||||
snapshot.ruidName = row["ruid_name"].as!string;
|
||||
snapshot.process = DBProcess(
|
||||
Identifier(cast(ubyte[]) row["process_id"].dup),
|
||||
row["process_name"].to!string
|
||||
Identifier(row["process_id"].as!Blob(Blob.init)),
|
||||
row["process_name"].as!string
|
||||
);
|
||||
|
||||
snapshots ~= snapshot;
|
||||
|
@ -727,30 +747,29 @@ public:
|
|||
{
|
||||
DBSnapshot snapshot;
|
||||
|
||||
snapshot.id = cast(ubyte[]) row["id"].dup;
|
||||
snapshot.id = row["id"].as!Blob(Blob.init);
|
||||
snapshot.file = DBFile(
|
||||
Identifier(cast(ubyte[]) row["file_id"].dup),
|
||||
row["file_name"].to!string
|
||||
Identifier(row["file_id"].as!Blob(Blob.init)),
|
||||
row["file_name"].as!string
|
||||
);
|
||||
snapshot.sha256 = cast(ubyte[]) row["sha256"].dup;
|
||||
snapshot.description = row["description"].to!string;
|
||||
snapshot.createdUtc = row["created_utc"].to!long;
|
||||
snapshot.sourceLength = row["source_length"].to!long;
|
||||
snapshot.algoMin = row["algo_min"].to!long;
|
||||
snapshot.algoNormal = row["algo_normal"].to!long;
|
||||
snapshot.algoMax = row["algo_max"].to!long;
|
||||
snapshot.maskS = row["mask_s"].to!long;
|
||||
snapshot.maskL = row["mask_l"].to!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].to!int;
|
||||
snapshot.uid = row["uid"].to!long;
|
||||
snapshot.ruid = row["ruid"].to!long;
|
||||
snapshot.uidName = row["uid_name"].to!string;
|
||||
snapshot.ruidName = row["ruid_name"].to!string;
|
||||
snapshot.sha256 = row["sha256"].as!Blob(Blob.init);
|
||||
snapshot.description = row["description"].as!string("");
|
||||
snapshot.createdUtc = row["created_utc"].as!long;
|
||||
snapshot.sourceLength = row["source_length"].as!long;
|
||||
snapshot.algoMin = row["algo_min"].as!long;
|
||||
snapshot.algoNormal = row["algo_normal"].as!long;
|
||||
snapshot.algoMax = row["algo_max"].as!long;
|
||||
snapshot.maskS = row["mask_s"].as!long;
|
||||
snapshot.maskL = row["mask_l"].as!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].as!int;
|
||||
snapshot.uid = row["uid"].as!long;
|
||||
snapshot.ruid = row["ruid"].as!long;
|
||||
snapshot.uidName = row["uid_name"].as!string;
|
||||
snapshot.ruidName = row["ruid_name"].as!string;
|
||||
snapshot.process = DBProcess(
|
||||
Identifier(cast(ubyte[]) row["process_id"].dup),
|
||||
row["process_name"].to!string
|
||||
Identifier(row["process_id"].as!Blob(Blob.init)),
|
||||
row["process_name"].as!string
|
||||
);
|
||||
|
||||
snapshots ~= snapshot;
|
||||
}
|
||||
|
||||
|
@ -793,31 +812,31 @@ public:
|
|||
|
||||
DBSnapshot snapshot;
|
||||
|
||||
if (!queryResult.empty()) {
|
||||
auto data = queryResult.front();
|
||||
if (!queryResult.empty) {
|
||||
auto data = queryResult.front;
|
||||
|
||||
snapshot.id = cast(ubyte[]) data["id"].dup;
|
||||
snapshot.id = data["id"].as!Blob(Blob.init);
|
||||
snapshot.file = DBFile(
|
||||
Identifier(cast(ubyte[]) data["file_id"].dup),
|
||||
data["file_name"].to!string
|
||||
Identifier(data["file_id"].as!Blob(Blob.init)),
|
||||
data["file_name"].as!string
|
||||
);
|
||||
snapshot.sha256 = cast(ubyte[]) data["sha256"].dup;
|
||||
snapshot.description = data["description"].to!string;
|
||||
snapshot.createdUtc = data["created_utc"].to!long;
|
||||
snapshot.sourceLength = data["source_length"].to!long;
|
||||
snapshot.algoMin = data["algo_min"].to!long;
|
||||
snapshot.algoNormal = data["algo_normal"].to!long;
|
||||
snapshot.algoMax = data["algo_max"].to!long;
|
||||
snapshot.maskS = data["mask_s"].to!long;
|
||||
snapshot.maskL = data["mask_l"].to!long;
|
||||
snapshot.status = cast(SnapshotStatus) data["status"].to!int;
|
||||
snapshot.uid = data["uid"].to!long;
|
||||
snapshot.ruid = data["ruid"].to!long;
|
||||
snapshot.uidName = data["uid_name"].to!string;
|
||||
snapshot.ruidName = data["ruid_name"].to!string;
|
||||
snapshot.sha256 = data["sha256"].as!Blob(Blob.init);
|
||||
snapshot.description = data["description"].as!string("");
|
||||
snapshot.createdUtc = data["created_utc"].as!long;
|
||||
snapshot.sourceLength = data["source_length"].as!long;
|
||||
snapshot.algoMin = data["algo_min"].as!long;
|
||||
snapshot.algoNormal = data["algo_normal"].as!long;
|
||||
snapshot.algoMax = data["algo_max"].as!long;
|
||||
snapshot.maskS = data["mask_s"].as!long;
|
||||
snapshot.maskL = data["mask_l"].as!long;
|
||||
snapshot.status = cast(SnapshotStatus) data["status"].as!int;
|
||||
snapshot.uid = data["uid"].as!long;
|
||||
snapshot.ruid = data["ruid"].as!long;
|
||||
snapshot.uidName = data["uid_name"].as!string;
|
||||
snapshot.ruidName = data["ruid_name"].as!string;
|
||||
snapshot.process = DBProcess(
|
||||
Identifier(cast(ubyte[]) data["process_id"].dup),
|
||||
data["process_name"].to!string
|
||||
Identifier(data["process_id"].as!Blob(Blob.init)),
|
||||
data["process_name"].as!string
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -870,28 +889,28 @@ public:
|
|||
{
|
||||
DBSnapshot snapshot;
|
||||
|
||||
snapshot.id = cast(ubyte[]) row["id"].dup;
|
||||
snapshot.id = row["id"].as!Blob(Blob.init);
|
||||
snapshot.file = DBFile(
|
||||
Identifier(cast(ubyte[]) row["file_id"].dup),
|
||||
row["file_name"].to!string
|
||||
Identifier(row["file_id"].as!Blob(Blob.init)),
|
||||
row["file_name"].as!string
|
||||
);
|
||||
snapshot.sha256 = cast(ubyte[]) row["sha256"].dup;
|
||||
snapshot.description = row["description"].to!string;
|
||||
snapshot.createdUtc = row["created_utc"].to!long;
|
||||
snapshot.sourceLength = row["source_length"].to!long;
|
||||
snapshot.algoMin = row["algo_min"].to!long;
|
||||
snapshot.algoNormal = row["algo_normal"].to!long;
|
||||
snapshot.algoMax = row["algo_max"].to!long;
|
||||
snapshot.maskS = row["mask_s"].to!long;
|
||||
snapshot.maskL = row["mask_l"].to!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].to!int;
|
||||
snapshot.uid = row["uid"].to!long;
|
||||
snapshot.ruid = row["ruid"].to!long;
|
||||
snapshot.uidName = row["uid_name"].to!string;
|
||||
snapshot.ruidName = row["ruid_name"].to!string;
|
||||
snapshot.sha256 = row["sha256"].as!Blob(Blob.init);
|
||||
snapshot.description = row["description"].as!string("");
|
||||
snapshot.createdUtc = row["created_utc"].as!long;
|
||||
snapshot.sourceLength = row["source_length"].as!long;
|
||||
snapshot.algoMin = row["algo_min"].as!long;
|
||||
snapshot.algoNormal = row["algo_normal"].as!long;
|
||||
snapshot.algoMax = row["algo_max"].as!long;
|
||||
snapshot.maskS = row["mask_s"].as!long;
|
||||
snapshot.maskL = row["mask_l"].as!long;
|
||||
snapshot.status = cast(SnapshotStatus) row["status"].as!int;
|
||||
snapshot.uid = row["uid"].as!long;
|
||||
snapshot.ruid = row["ruid"].as!long;
|
||||
snapshot.uidName = row["uid_name"].as!string;
|
||||
snapshot.ruidName = row["ruid_name"].as!string;
|
||||
snapshot.process = DBProcess(
|
||||
Identifier(cast(ubyte[]) row["process_id"].dup),
|
||||
row["process_name"].to!string
|
||||
Identifier(row["process_id"].as!Blob(Blob.init)),
|
||||
row["process_name"].as!string
|
||||
);
|
||||
|
||||
snapshots ~= snapshot;
|
||||
|
@ -902,6 +921,6 @@ public:
|
|||
|
||||
bool deleteSnapshot(Identifier id) {
|
||||
auto queryResult = sql("DELETE FROM snapshots WHERE id = ? RETURNING id", id[]);
|
||||
return !queryResult.empty();
|
||||
return !queryResult.empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,12 +60,24 @@ public:
|
|||
_data = data;
|
||||
}
|
||||
|
||||
this(immutable(ubyte[]) data)
|
||||
{
|
||||
assert(data.length <= 16);
|
||||
_data = data.dup;
|
||||
}
|
||||
|
||||
this(ref const ubyte[16] data)
|
||||
{
|
||||
assert(data.length <= 16);
|
||||
_data = data.dup;
|
||||
}
|
||||
|
||||
void opAssign(immutable(ubyte[]) data)
|
||||
{
|
||||
assert(data.length <= 16);
|
||||
_data = data.dup;
|
||||
}
|
||||
|
||||
void opAssign(ubyte[] data)
|
||||
{
|
||||
assert(data.length <= 16);
|
||||
|
|
14
test/app.d
14
test/app.d
|
@ -72,13 +72,13 @@ void main()
|
|||
}
|
||||
|
||||
// Удаление файла
|
||||
if (storage.deleteFile("example_file"))
|
||||
writeln("Файл example_file удален.");
|
||||
// if (storage.deleteFile("example_file"))
|
||||
// writeln("Файл example_file удален.");
|
||||
|
||||
// Проверка: снимки удалены
|
||||
auto remaining = storage.getSnapshots("example_file");
|
||||
assert(remaining.length == 0);
|
||||
writeln("Все снимки удалены.");
|
||||
// // Проверка: снимки удалены
|
||||
// auto remaining = storage.getSnapshots("example_file");
|
||||
// assert(remaining.length == 0);
|
||||
// writeln("Все снимки удалены.");
|
||||
|
||||
writeln("Версия библиотеки: ", storage.getVersion());
|
||||
// writeln("Версия библиотеки: ", storage.getVersion());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue