2018-02-09 06:54:14 +03:00
|
|
|
/*
|
2019-06-20 02:58:25 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2018-02-09 06:54:14 +03:00
|
|
|
*
|
2019-06-20 02:58:25 +03:00
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
2018-02-09 06:54:14 +03:00
|
|
|
*/
|
2019-10-11 15:26:59 +03:00
|
|
|
|
2018-02-09 06:54:14 +03:00
|
|
|
#include "eden/fs/sqlite/Sqlite.h"
|
|
|
|
using folly::StringPiece;
|
|
|
|
using folly::Synchronized;
|
|
|
|
using folly::to;
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
namespace facebook {
|
|
|
|
namespace eden {
|
|
|
|
|
|
|
|
// Given a sqlite result code, if the result was not successful
|
|
|
|
// (SQLITE_OK), format an error message and throw an exception.
|
|
|
|
void checkSqliteResult(sqlite3* db, int result) {
|
|
|
|
if (result == SQLITE_OK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Sometimes the db instance holds more useful context
|
|
|
|
if (db) {
|
|
|
|
throw std::runtime_error(to<string>(
|
|
|
|
"sqlite error: ",
|
|
|
|
result,
|
|
|
|
": ",
|
|
|
|
sqlite3_errstr(result),
|
|
|
|
" ",
|
|
|
|
sqlite3_errmsg(db)));
|
|
|
|
}
|
|
|
|
// otherwise resort to a simpler number->string mapping
|
|
|
|
throw std::runtime_error(
|
|
|
|
to<string>("sqlite error: ", result, ": ", sqlite3_errstr(result)));
|
|
|
|
}
|
|
|
|
|
|
|
|
SqliteDatabase::SqliteDatabase(AbsolutePathPiece path) {
|
2018-06-21 02:24:02 +03:00
|
|
|
sqlite3* db = nullptr;
|
|
|
|
auto result = sqlite3_open(path.copy().c_str(), &db);
|
|
|
|
if (result != SQLITE_OK) {
|
|
|
|
// On most error conditions sqlite3_open() does allocate the DB object,
|
|
|
|
// and it needs to be closed afterwards if it is non-null.
|
|
|
|
sqlite3_close(db);
|
|
|
|
checkSqliteResult(nullptr, result);
|
|
|
|
}
|
2018-02-09 06:54:14 +03:00
|
|
|
db_ = db;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SqliteDatabase::close() {
|
|
|
|
auto db = db_.wlock();
|
|
|
|
if (*db) {
|
|
|
|
sqlite3_close(*db);
|
|
|
|
*db = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SqliteDatabase::~SqliteDatabase() {
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
Synchronized<sqlite3*>::LockedPtr SqliteDatabase::lock() {
|
|
|
|
return db_.wlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
SqliteStatement::SqliteStatement(
|
|
|
|
folly::Synchronized<sqlite3*>::LockedPtr& db,
|
|
|
|
folly::StringPiece query)
|
|
|
|
: db_{*db} {
|
|
|
|
checkSqliteResult(
|
|
|
|
db_,
|
2020-04-27 07:12:07 +03:00
|
|
|
sqlite3_prepare_v2(
|
|
|
|
db_, query.data(), unsignedNoToInt(query.size()), &stmt_, nullptr));
|
2018-02-09 06:54:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SqliteStatement::step() {
|
|
|
|
auto result = sqlite3_step(stmt_);
|
|
|
|
switch (result) {
|
|
|
|
case SQLITE_ROW:
|
|
|
|
return true;
|
|
|
|
case SQLITE_DONE:
|
|
|
|
sqlite3_reset(stmt_);
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
checkSqliteResult(db_, result);
|
|
|
|
folly::assume_unreachable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SqliteStatement::bind(
|
|
|
|
size_t paramNo,
|
|
|
|
folly::StringPiece blob,
|
|
|
|
void (*bindType)(void*)) {
|
2020-04-27 07:12:07 +03:00
|
|
|
auto param = unsignedNoToInt(paramNo);
|
2018-02-09 06:54:14 +03:00
|
|
|
checkSqliteResult(
|
|
|
|
db_,
|
|
|
|
sqlite3_bind_blob64(
|
2020-04-27 07:12:07 +03:00
|
|
|
stmt_, param, blob.data(), sqlite3_uint64(blob.size()), bindType));
|
2018-02-09 06:54:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
StringPiece SqliteStatement::columnBlob(size_t colNo) const {
|
2020-04-27 07:12:07 +03:00
|
|
|
auto col = unsignedNoToInt(colNo);
|
2018-02-09 06:54:14 +03:00
|
|
|
return StringPiece(
|
2020-04-27 07:12:07 +03:00
|
|
|
reinterpret_cast<const char*>(sqlite3_column_blob(stmt_, col)),
|
|
|
|
sqlite3_column_bytes(stmt_, col));
|
2018-02-09 06:54:14 +03:00
|
|
|
}
|
|
|
|
|
2020-04-23 22:38:56 +03:00
|
|
|
uint64_t SqliteStatement::columnUint64(size_t colNo) const {
|
2020-04-27 07:12:07 +03:00
|
|
|
return sqlite3_column_int64(stmt_, unsignedNoToInt(colNo));
|
2020-04-23 22:38:56 +03:00
|
|
|
}
|
|
|
|
|
2018-02-09 06:54:14 +03:00
|
|
|
SqliteStatement::~SqliteStatement() {
|
|
|
|
sqlite3_finalize(stmt_);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace eden
|
|
|
|
} // namespace facebook
|