mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-27 01:40:09 +02:00
4253318835
commit1eff2d7d67
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 18 19:15:27 2023 +1100 Update PR * Add --source-directory 'path/as/source/' --destination-directory 'path/as/destination' functionality commitad3ddee0ec
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 18 17:32:24 2023 +1100 Update PR * Add --create-directory * Add --remove-directory commit7dfe6b65b7
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 18 12:27:03 2023 +1100 Update PR * Update PR commit75c071e56f
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 18 10:12:05 2023 +1100 Update PR * Update PR commit6db484cdad
Author: abraunegg <alex.braunegg@gmail.com> Date: Mon Oct 16 17:01:25 2023 +1100 Update PR * Update PR commitd893ea5460
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 11 10:43:50 2023 +1100 Update PR * Update PR commit82bd593bf4
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 11 09:14:17 2023 +1100 Update PR * Validate and document --auth-files operation commitc551203f4c
Author: abraunegg <alex.braunegg@gmail.com> Date: Wed Oct 11 05:48:22 2023 +1100 Update PR * Add --create-share-link commitfbf63999ff
Author: abraunegg <alex.braunegg@gmail.com> Date: Tue Oct 10 18:39:21 2023 +1100 Update PR * Update PR commit72a4680035
Author: abraunegg <alex.braunegg@gmail.com> Date: Tue Oct 10 17:43:15 2023 +1100 Update PR * Add --get-file-link * Add --modified-by commit0d3fc3ebf2
Author: abraunegg <alex.braunegg@gmail.com> Date: Tue Oct 10 14:28:10 2023 +1100 Add --display-sync-status * Add --display-sync-status commit1f183ca03e
Author: abraunegg <alex.braunegg@gmail.com> Date: Mon Oct 9 08:18:13 2023 +1100 Update PR * Update PR with doc updates commitb0628d7099
Author: abraunegg <alex.braunegg@gmail.com> Date: Sun Oct 8 10:52:52 2023 +1100 Update PR * Update PR commit7e3df956ce
Author: abraunegg <alex.braunegg@gmail.com> Date: Sat Oct 7 05:31:26 2023 +1100 Update PR * Update PR commitc69f2abc4b
Author: abraunegg <alex.braunegg@gmail.com> Date: Sat Oct 7 05:28:28 2023 +1100 Update PR * Update PR commitea1ca33374
Author: abraunegg <alex.braunegg@gmail.com> Date: Fri Oct 6 14:57:51 2023 +1100 Update PR * Update PR commit1503f969df
Author: abraunegg <alex.braunegg@gmail.com> Date: Fri Oct 6 09:19:04 2023 +1100 Update PR * Update PR commit5127464f2c
Author: abraunegg <alex.braunegg@gmail.com> Date: Fri Oct 6 06:48:20 2023 +1100 Change when the integrity check is performed * Change when the integrity check is performed commitc7cc45d95c
Author: abraunegg <alex.braunegg@gmail.com> Date: Thu Oct 5 19:40:05 2023 +1100 Update maxInotifyWatches location * Update maxInotifyWatches location commitc44ad963a6
Author: abraunegg <alex.braunegg@gmail.com> Date: Thu Oct 5 17:41:31 2023 +1100 Update main.d * Fix --version segfault commit51f0ffcb1f
Author: abraunegg <alex.braunegg@gmail.com> Date: Thu Oct 5 17:24:30 2023 +1100 Uplift to v2.5.0-alpha-2 * Uplift to v2.5.0-alpha-2 commitcbe3e6ea84
Author: abraunegg <alex.braunegg@gmail.com> Date: Thu Oct 5 17:17:26 2023 +1100 Clean up before onedrive-v2.5.0-alpha-2 * Clean up before onedrive-v2.5.0-alpha-2
207 lines
5.3 KiB
D
207 lines
5.3 KiB
D
// What is this module called?
|
|
module sqlite;
|
|
|
|
// What does this module require to function?
|
|
import std.stdio;
|
|
import etc.c.sqlite3;
|
|
import std.string: fromStringz, toStringz;
|
|
import core.stdc.stdlib;
|
|
import std.conv;
|
|
|
|
// What other modules that we have created do we need to import?
|
|
import log;
|
|
|
|
extern (C) immutable(char)* sqlite3_errstr(int); // missing from the std library
|
|
|
|
static this() {
|
|
if (sqlite3_libversion_number() < 3006019) {
|
|
throw new SqliteException("sqlite 3.6.19 or newer is required");
|
|
}
|
|
}
|
|
|
|
private string ifromStringz(const(char)* cstr) {
|
|
return fromStringz(cstr).dup;
|
|
}
|
|
|
|
class SqliteException: Exception {
|
|
@safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
|
|
{
|
|
super(msg, file, line, next);
|
|
}
|
|
|
|
@safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
|
|
{
|
|
super(msg, file, line, next);
|
|
}
|
|
}
|
|
|
|
struct Database {
|
|
private sqlite3* pDb;
|
|
|
|
this(const(char)[] filename) {
|
|
open(filename);
|
|
}
|
|
|
|
~this() {
|
|
close();
|
|
}
|
|
|
|
int db_checkpoint() {
|
|
return sqlite3_wal_checkpoint(pDb, null);
|
|
}
|
|
|
|
void dump_open_statements() {
|
|
log.log("Dumping open statements: \n");
|
|
auto p = sqlite3_next_stmt(pDb, null);
|
|
while (p != null) {
|
|
log.log (" - " ~ ifromStringz(sqlite3_sql(p)) ~ "\n");
|
|
p = sqlite3_next_stmt(pDb, p);
|
|
}
|
|
}
|
|
|
|
|
|
void open(const(char)[] filename) {
|
|
// https://www.sqlite.org/c3ref/open.html
|
|
int rc = sqlite3_open(toStringz(filename), &pDb);
|
|
if (rc == SQLITE_CANTOPEN) {
|
|
// Database cannot be opened
|
|
log.error("\nThe database cannot be opened. Please check the permissions of " ~ filename ~ "\n");
|
|
close();
|
|
exit(-1);
|
|
}
|
|
if (rc != SQLITE_OK) {
|
|
log.error("\nA database access error occurred: " ~ getErrorMessage() ~ "\n");
|
|
close();
|
|
exit(-1);
|
|
}
|
|
sqlite3_extended_result_codes(pDb, 1); // always use extended result codes
|
|
}
|
|
|
|
void exec(const(char)[] sql) {
|
|
// https://www.sqlite.org/c3ref/exec.html
|
|
int rc = sqlite3_exec(pDb, toStringz(sql), null, null, null);
|
|
if (rc != SQLITE_OK) {
|
|
log.error("\nA database execution error occurred: "~ getErrorMessage() ~ "\n");
|
|
log.error("Please retry your command with --resync to fix any local database corruption issues.\n");
|
|
close();
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
int getVersion() {
|
|
int userVersion;
|
|
extern (C) int callback(void* user_version, int count, char** column_text, char** column_name) {
|
|
import core.stdc.stdlib: atoi;
|
|
*(cast(int*) user_version) = atoi(*column_text);
|
|
return 0;
|
|
}
|
|
int rc = sqlite3_exec(pDb, "PRAGMA user_version", &callback, &userVersion, null);
|
|
if (rc != SQLITE_OK) {
|
|
throw new SqliteException(ifromStringz(sqlite3_errmsg(pDb)));
|
|
}
|
|
return userVersion;
|
|
}
|
|
|
|
string getErrorMessage() {
|
|
return ifromStringz(sqlite3_errmsg(pDb));
|
|
}
|
|
|
|
void setVersion(int userVersion) {
|
|
import std.conv: to;
|
|
exec("PRAGMA user_version=" ~ to!string(userVersion));
|
|
}
|
|
|
|
Statement prepare(const(char)[] zSql) {
|
|
Statement s;
|
|
// https://www.sqlite.org/c3ref/prepare.html
|
|
int rc = sqlite3_prepare_v2(pDb, zSql.ptr, cast(int) zSql.length, &s.pStmt, null);
|
|
if (rc != SQLITE_OK) {
|
|
throw new SqliteException(ifromStringz(sqlite3_errmsg(pDb)));
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void close() {
|
|
// https://www.sqlite.org/c3ref/close.html
|
|
sqlite3_close_v2(pDb);
|
|
pDb = null;
|
|
}
|
|
}
|
|
|
|
struct Statement {
|
|
struct Result {
|
|
private sqlite3_stmt* pStmt;
|
|
private const(char)[][] row;
|
|
|
|
private this(sqlite3_stmt* pStmt) {
|
|
this.pStmt = pStmt;
|
|
step(); // initialize the range
|
|
}
|
|
|
|
@property bool empty() {
|
|
return row.length == 0;
|
|
}
|
|
|
|
@property auto front() {
|
|
return row;
|
|
}
|
|
|
|
alias step popFront;
|
|
|
|
void step() {
|
|
// https://www.sqlite.org/c3ref/step.html
|
|
int rc = sqlite3_step(pStmt);
|
|
if (rc == SQLITE_BUSY) {
|
|
// Database is locked by another onedrive process
|
|
log.error("The database is currently locked by another process - cannot sync");
|
|
return;
|
|
}
|
|
if (rc == SQLITE_DONE) {
|
|
row.length = 0;
|
|
} else if (rc == SQLITE_ROW) {
|
|
// https://www.sqlite.org/c3ref/data_count.html
|
|
int count = 0;
|
|
count = sqlite3_data_count(pStmt);
|
|
row = new const(char)[][count];
|
|
foreach (size_t i, ref column; row) {
|
|
// https://www.sqlite.org/c3ref/column_blob.html
|
|
column = fromStringz(sqlite3_column_text(pStmt, to!int(i)));
|
|
}
|
|
} else {
|
|
string errorMessage = ifromStringz(sqlite3_errmsg(sqlite3_db_handle(pStmt)));
|
|
log.error("\nA database statement execution error occurred: "~ errorMessage ~ "\n");
|
|
log.error("Please retry your command with --resync to fix any local database corruption issues.\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sqlite3_stmt* pStmt;
|
|
|
|
~this() {
|
|
// https://www.sqlite.org/c3ref/finalize.html
|
|
sqlite3_finalize(pStmt);
|
|
}
|
|
|
|
void bind(int index, const(char)[] value) {
|
|
reset();
|
|
// https://www.sqlite.org/c3ref/bind_blob.html
|
|
int rc = sqlite3_bind_text(pStmt, index, value.ptr, cast(int) value.length, SQLITE_STATIC);
|
|
if (rc != SQLITE_OK) {
|
|
throw new SqliteException(ifromStringz(sqlite3_errmsg(sqlite3_db_handle(pStmt))));
|
|
}
|
|
}
|
|
|
|
Result exec() {
|
|
reset();
|
|
return Result(pStmt);
|
|
}
|
|
|
|
private void reset() {
|
|
// https://www.sqlite.org/c3ref/reset.html
|
|
int rc = sqlite3_reset(pStmt);
|
|
if (rc != SQLITE_OK) {
|
|
throw new SqliteException(ifromStringz(sqlite3_errmsg(sqlite3_db_handle(pStmt))));
|
|
}
|
|
}
|
|
} |