#pragma once #include #include // std::string #include // std::function #include // std::shared_ptr #include // std::vector #include #include "error_code.h" #include "row_extractor.h" #include "journal_mode.h" #include "connection_holder.h" #include "util.h" #include "serializing_util.h" namespace sqlite_orm { namespace internal { struct storage_base; template int getPragmaCallback(void* data, int argc, char** argv, char** x) { return extract_single_value(data, argc, argv, x); } template<> inline int getPragmaCallback>(void* data, int argc, char** argv, char**) { auto& res = *(std::vector*)data; res.reserve(argc); for(decltype(argc) i = 0; i < argc; ++i) { auto rowString = row_extractor().extract(argv[i]); res.push_back(std::move(rowString)); } return 0; } struct pragma_t { using get_connection_t = std::function; pragma_t(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {} void busy_timeout(int value) { this->set_pragma("busy_timeout", value); } int busy_timeout() { return this->get_pragma("busy_timeout"); } sqlite_orm::journal_mode journal_mode() { return this->get_pragma("journal_mode"); } void journal_mode(sqlite_orm::journal_mode value) { this->_journal_mode = -1; this->set_pragma("journal_mode", value); this->_journal_mode = static_cast_journal_mode)>(value); } /** * https://www.sqlite.org/pragma.html#pragma_application_id */ int application_id() { return this->get_pragma("application_id"); } /** * https://www.sqlite.org/pragma.html#pragma_application_id */ void application_id(int value) { this->set_pragma("application_id", value); } int synchronous() { return this->get_pragma("synchronous"); } void synchronous(int value) { this->_synchronous = -1; this->set_pragma("synchronous", value); this->_synchronous = value; } int user_version() { return this->get_pragma("user_version"); } void user_version(int value) { this->set_pragma("user_version", value); } int auto_vacuum() { return this->get_pragma("auto_vacuum"); } void auto_vacuum(int value) { this->set_pragma("auto_vacuum", value); } std::vector integrity_check() { return this->get_pragma>("integrity_check"); } template std::vector integrity_check(T table_name) { std::ostringstream ss; ss << "integrity_check(" << table_name << ")" << std::flush; return this->get_pragma>(ss.str()); } std::vector integrity_check(int n) { std::ostringstream ss; ss << "integrity_check(" << n << ")" << std::flush; return this->get_pragma>(ss.str()); } // will include generated columns in response as opposed to table_info std::vector table_xinfo(const std::string& tableName) const { auto connection = this->get_connection(); std::vector result; std::ostringstream ss; ss << "PRAGMA " "table_xinfo(" << streaming_identifier(tableName) << ")" << std::flush; perform_exec( connection.get(), ss.str(), [](void* data, int argc, char** argv, char**) -> int { auto& res = *(std::vector*)data; if(argc) { auto index = 0; auto cid = std::atoi(argv[index++]); std::string name = argv[index++]; std::string type = argv[index++]; bool notnull = !!std::atoi(argv[index++]); std::string dflt_value = argv[index] ? argv[index] : ""; ++index; auto pk = std::atoi(argv[index++]); auto hidden = std::atoi(argv[index++]); res.emplace_back(cid, std::move(name), std::move(type), notnull, std::move(dflt_value), pk, hidden); } return 0; }, &result); return result; } std::vector table_info(const std::string& tableName) const { auto connection = this->get_connection(); std::ostringstream ss; ss << "PRAGMA " "table_info(" << streaming_identifier(tableName) << ")" << std::flush; std::vector result; perform_exec( connection.get(), ss.str(), [](void* data, int argc, char** argv, char**) -> int { auto& res = *(std::vector*)data; if(argc) { auto index = 0; auto cid = std::atoi(argv[index++]); std::string name = argv[index++]; std::string type = argv[index++]; bool notnull = !!std::atoi(argv[index++]); std::string dflt_value = argv[index] ? argv[index] : ""; ++index; auto pk = std::atoi(argv[index++]); res.emplace_back(cid, std::move(name), std::move(type), notnull, std::move(dflt_value), pk); } return 0; }, &result); return result; } private: friend struct storage_base; int _synchronous = -1; signed char _journal_mode = -1; // if != -1 stores static_cast(journal_mode) get_connection_t get_connection; template T get_pragma(const std::string& name) { auto connection = this->get_connection(); T result; perform_exec(connection.get(), "PRAGMA " + name, getPragmaCallback, &result); return result; } /** * Yevgeniy Zakharov: I wanted to refactor this function with statements and value bindings * but it turns out that bindings in pragma statements are not supported. */ template void set_pragma(const std::string& name, const T& value, sqlite3* db = nullptr) { auto con = this->get_connection(); if(!db) { db = con.get(); } std::stringstream ss; ss << "PRAGMA " << name << " = " << value << std::flush; perform_void_exec(db, ss.str()); } void set_pragma(const std::string& name, const sqlite_orm::journal_mode& value, sqlite3* db = nullptr) { auto con = this->get_connection(); if(!db) { db = con.get(); } std::stringstream ss; ss << "PRAGMA " << name << " = " << to_string(value) << std::flush; perform_void_exec(db, ss.str()); } }; } }