5 #ifndef CVMFS_SQL_IMPL_H_
6 #define CVMFS_SQL_IMPL_H_
20 template <
class DerivedT>
23 : database_(filename, this)
24 , read_write_(kOpenReadWrite == open_mode)
25 , schema_version_(0.0f)
26 , schema_revision_(0) {}
29 template <
class DerivedT>
38 database->set_schema_version(DerivedT::kLatestSchema);
39 database->set_schema_revision(DerivedT::kLatestSchemaRevision);
41 const int open_flags = SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE |
43 if (!database->OpenDatabase(open_flags)) {
48 if (!database->CreatePropertiesTable()) {
49 database->PrintSqlError(
"Failed to create common properties table");
53 if (!database->CreateEmptyDatabase()) {
54 database->PrintSqlError(
"Failed to create empty database");
58 if (!database->PrepareCommonQueries()) {
59 database->PrintSqlError(
"Failed to initialize properties queries");
63 if (!database->StoreSchemaRevision()) {
64 database->PrintSqlError(
"Failed to store initial schema revision");
72 template <
class DerivedT>
79 "Failed to open database file '%s' - errno: %d",
80 filename.c_str(), errno);
84 if (!database->Initialize()) {
92 template <
class DerivedT>
94 const int flags = (read_write_) ? SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE
95 : SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READONLY;
97 bool successful = OpenDatabase(flags) &&
100 PrepareCommonQueries();
107 ReadSchemaRevision();
110 schema_version_, schema_revision_);
112 if (!static_cast<DerivedT*>(
this)->CheckSchemaCompatibility()) {
114 schema_version_, filename().c_str());
119 !static_cast<DerivedT*>(
this)->LiveSchemaUpgradeIfNecessary()) {
128 template <
class DerivedT>
133 int retval = sqlite3_open_v2(filename().c_str(),
134 &database_.sqlite_db,
135 flags | SQLITE_OPEN_EXRESCODE,
137 if (retval != SQLITE_OK) {
139 filename().c_str(), retval, errno);
147 template <
class DerivedT>
150 const bool close_successful =
Close();
156 template <
class DerivedT>
162 (db_file_guard.IsEnabled() ?
"yes" :
"no"));
163 const int result = sqlite3_close(
sqlite_db);
165 if (result != SQLITE_OK) {
167 "failed to close SQLite database '%s' (%d - %s)",
169 delegate_->GetLastErrorMsg().c_str());
174 if (lookaside_buffer != NULL) {
177 lookaside_buffer = NULL;
183 template <
class DerivedT>
202 template <
class DerivedT>
209 fd_readahead = open(
filename().c_str(), O_RDONLY);
210 if (fd_readahead < 0) {
221 if (retval != 0 && errno != EINVAL) {
223 "failed to read-ahead %s: invalid file descrp. or not open for reading",
233 template <
class DerivedT>
239 "WHERE key = :key;");
241 "WHERE key = :key;");
243 "(key, value) VALUES (:key, :value);");
252 template <
class DerivedT>
263 template <
class DerivedT>
270 template <
class DerivedT>
277 template <
class DerivedT>
284 template <
class DerivedT>
287 "CREATE TABLE properties (key TEXT, value TEXT, "
288 "CONSTRAINT pk_properties PRIMARY KEY (key));").
Execute();
292 template <
class DerivedT>
303 template <
class DerivedT>
304 template <
typename T>
315 template <
class DerivedT>
316 template <
typename T>
318 const T default_value)
const {
323 template <
class DerivedT>
324 template <
typename T>
334 template <
class DerivedT>
336 std::string msg = sqlite3_errmsg(
sqlite_db());
341 template <
class DerivedT>
349 template <
class DerivedT>
357 template <
class DerivedT>
359 const int modified_rows = sqlite3_total_changes(
sqlite_db());
360 assert(modified_rows >= 0);
361 return static_cast<unsigned>(modified_rows);
367 template <
class DerivedT>
372 int retval = SQLITE_OK;
373 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_USED,
374 ¤t, &highwater, reset);
377 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_HIT,
378 ¤t, &highwater, reset);
380 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
381 ¤t, &highwater, reset);
383 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
384 ¤t, &highwater, reset);
386 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_CACHE_USED,
387 ¤t, &highwater, reset);
389 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_CACHE_HIT,
390 ¤t, &highwater, reset);
392 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_CACHE_MISS,
393 ¤t, &highwater, reset);
395 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_SCHEMA_USED,
396 ¤t, &highwater, reset);
398 retval |= sqlite3_db_status(
sqlite_db(), SQLITE_DBSTATUS_STMT_USED,
399 ¤t, &highwater, reset);
401 assert(retval == SQLITE_OK);
405 template <
class DerivedT>
407 Sql free_page_count_query(this->
sqlite_db(),
"PRAGMA freelist_count;");
408 Sql page_count_query(this->
sqlite_db(),
"PRAGMA page_count;");
410 const bool retval = page_count_query.
FetchRow() &&
418 return (static_cast<double>(free_pages) / static_cast<double>(pages));
422 template <
class DerivedT>
425 return static_cast<const DerivedT*
>(
this)->CompactDatabase() &&
430 template <
class DerivedT>
436 template <
class DerivedT>
438 template <
class DerivedT>
440 template <
class DerivedT>
450 inline bool Sql::Bind(
const int index,
const int &value) {
451 return this->BindInt64(index, value);
455 inline bool Sql::Bind(
const int index,
const unsigned int &value) {
456 return this->BindInt64(index, static_cast<int>(value));
460 inline bool Sql::Bind(
const int index,
const uint64_t &value) {
461 return this->BindInt64(index, static_cast<int64_t>(value));
465 inline bool Sql::Bind(
const int index,
const sqlite3_int64 &value) {
466 return this->BindInt64(index, value);
470 inline bool Sql::Bind(
const int index,
const std::string &value) {
471 return this->BindTextTransient(index, value);
475 inline bool Sql::Bind(
const int index,
const float &value) {
476 return this->BindDouble(index, value);
480 inline bool Sql::Bind(
const int index,
const double &value) {
481 return this->BindDouble(index, value);
487 return static_cast<int>(this->RetrieveInt64(index));
492 return static_cast<bool>(this->RetrieveInt(index));
497 return this->RetrieveInt64(index);
502 return static_cast<uint64_t
>(this->RetrieveInt64(index));
507 return RetrieveString(index);
512 return static_cast<float>(this->RetrieveDouble(index));
517 return this->RetrieveDouble(index);
522 #endif // CVMFS_SQL_IMPL_H_
bool Bind(const int index, const T &value)
const std::string & filename() const
std::string GetLastErrorMsg() const
double GetFreePageRatio() const
int page_cache_used
Bytes used for caching pages.
const std::string & filename() const
bool PrepareCommonQueries()
bool BeginTransaction() const
void ReadSchemaRevision()
Database(const std::string &filename, const OpenMode open_mode)
assert((mem||(size==0))&&"Out Of Memory")
int stmt_used
Bytes used for prepared statmements (lookaside + heap)
static DerivedT * Open(const std::string &filename, const OpenMode open_mode)
bool CreatePropertiesTable()
T GetProperty(const std::string &key) const
static bool HasInstance()
T GetPropertyDefault(const std::string &key, const T default_value) const
UniquePtr< Sql > set_property_
unsigned GetModifiedRowCount() const
sqlite3_int64 RetrieveInt64(const int idx_column) const
static SqliteMemoryManager * GetInstance()
T Retrieve(const int index)
UniquePtr< Sql > commit_transaction_
UniquePtr< Sql > has_property_
sqlite3 * sqlite_db() const
bool CommitTransaction() const
bool SetProperty(const std::string &key, const T value)
bool OpenDatabase(const int sqlite_open_flags)
bool HasProperty(const std::string &key) const
static const char * kSchemaRevisionKey
unsigned schema_revision_
int schema_used
Bytes used to store db schema.
void GetMemStatistics(MemStatistics *stats) const
void PrintSqlError(const std::string &error_msg)
DatabaseRaiiWrapper database_
static const char * kSchemaVersionKey
UniquePtr< Sql > get_property_
bool StoreSchemaRevision()
UniquePtr< Sql > begin_transaction_
void ReleaseLookasideBuffer(void *buffer)
static DerivedT * Create(const std::string &filename)
void * AssignLookasideBuffer(sqlite3 *db)
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)