35 #include <boost/make_shared.hpp> 36 #include <boost/format.hpp> 47 int busy_handler(
void* ,
int times_called_before)
49 constexpr
auto wait_interval =
54 std::this_thread::sleep_for((times_called_before + 1) * wait_interval);
70 if (sqlite3_open(
uri_.c_str(), &s) != SQLITE_OK)
76 if (sqlite3_busy_handler(
db_.get(), busy_handler,
nullptr) != SQLITE_OK)
87 return static_cast<bool>(
db_);
92 std::ostringstream query_builder;
95 const auto select_query = query_builder.str();
96 sqlite3_stmt* raw_stmt =
nullptr;
97 if (sqlite3_prepare_v2(
db_.get(), select_query.c_str(), select_query.size() + 1, &raw_stmt,
nullptr) != SQLITE_OK)
99 throw InternalError(
"Prepare statement for getTablesOfDatabase() failed",
db_.get());
102 if (sqlite3_bind_text(stmt.get(), 1, db_name.c_str(), db_name.size(), SQLITE_STATIC) != SQLITE_OK)
104 throw InternalError(
"Bind parameter for getTablesOfDatabase() failed",
db_.get());
106 std::vector<std::string> tables;
107 for (
int res = sqlite3_step(stmt.get()); res != SQLITE_DONE; res = sqlite3_step(stmt.get()))
109 if (res == SQLITE_ROW)
111 tables.emplace_back(reinterpret_cast<const char*>(sqlite3_column_text(stmt.get(), 0)),
112 sqlite3_column_bytes(stmt.get(), 0));
116 throw InternalError(
"Get results for getTablesOfDatabase() failed",
db_.get());
127 std::ostringstream query_builder;
128 for (
const auto& table : tables_to_be_dropped)
133 <<
" == '" << escaped_table_string <<
"'; ";
134 query_builder <<
"DROP TABLE " << escaped_table_identifier <<
";";
136 query_builder <<
"COMMIT;";
137 const auto query = query_builder.str();
138 if (sqlite3_exec(
db_.get(),
"BEGIN TRANSACTION;",
nullptr,
nullptr,
nullptr) == SQLITE_OK)
140 if (sqlite3_exec(
db_.get(), query.c_str(),
nullptr,
nullptr,
nullptr) == SQLITE_OK)
144 sqlite3_exec(
db_.get(),
"ROLLBACK;",
nullptr,
nullptr,
nullptr);
151 const std::string& collection_name)
155 std::ostringstream query_builder;
158 const auto query = query_builder.str();
159 sqlite3_stmt* stmt =
nullptr;
160 if (sqlite3_prepare_v2(
db_.get(), query.c_str(), query.size() + 1, &stmt,
nullptr) != SQLITE_OK)
162 throw InternalError(
"Prepare statement for messageType() failed",
db_.get());
166 if (sqlite3_bind_text(stmt, 1, mangled_name.c_str(), mangled_name.size(), SQLITE_STATIC) != SQLITE_OK)
167 throw InternalError(
"Bind parameter for getTablesOfDatabase() failed",
db_.get());
168 switch (sqlite3_step(stmt))
174 throw InternalError(
"Get result for getTablesOfDatabase() failed",
db_.get());
176 return std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes(stmt, 0));
183 std::ostringstream query_builder;
189 const auto query = query_builder.str();
190 ROS_DEBUG_NAMED(
"warehouse_ros_sqlite",
"MD5 table init: %s", query.c_str());
191 if (sqlite3_exec(
db_.get(), query.c_str(),
nullptr,
nullptr,
nullptr) != SQLITE_OK)
197 sqlite3_stmt* stmt =
nullptr;
198 if (sqlite3_prepare_v2(
db_.get(),
"PRAGMA user_version;", -1, &stmt,
nullptr) != SQLITE_OK)
201 if (sqlite3_step(stmt_guard.get()) != SQLITE_ROW)
203 const int current_schema_version = sqlite3_column_int(stmt_guard.get(), 0);
204 if (current_schema_version == 0)
219 const std::string& collection_name)
221 return boost::make_shared<warehouse_ros_sqlite::MessageCollectionHelper>(
db_, db_name, collection_name);
226 sqlite3_finalize(stmt);
230 if (sqlite3_close(db) != SQLITE_OK)
232 ROS_ERROR(
"sqlite connection closed when still in use");
237 :
warehouse_ros::WarehouseRosException(
boost::format(
"%1% %2%") % msg % sqlite3_errmsg(db))
static const int BUSY_WAIT_MILLISECS
bool isConnected() override
Returns whether the database is connected.
constexpr const char * M_D5_TABLE_DATABASE_COLUMN
constexpr const char * M_D5_TABLE_NAME
InternalError(const char *msg, sqlite3 *db)
std::string messageType(const std::string &db_name, const std::string &collection_name) override
Return the ROS Message type of a given collection.
void dropDatabase(const std::string &db_name) override
Drop a db and all its collections. A DbClientConnection exception will be thrown if the database is n...
std::string escape_string_literal_without_quotes(const std::string &c)
warehouse_ros::MessageCollectionHelper::Ptr openCollectionHelper(const std::string &db_name, const std::string &collection_name) override
constexpr const char * M_D5_TABLE_TABLE_COLUMN
#define ROS_DEBUG_NAMED(name,...)
constexpr const char * M_D5_TABLE_INDEX_COLUMN
constexpr const char * M_D5_TABLE_M_D5_COLUMN
std::string escape_identifier(const std::string &s)
static const int BUSY_MAX_RETRIES
std::unique_ptr< sqlite3_stmt, Sqlite3StmtDeleter > sqlite3_stmt_ptr
WAREHOUSE_ROS_SQLITE_EXPORT void sqlite3_delete(sqlite3 *db)
constexpr const char * M_D5_TABLE_DATATYPE_COLUMN
std::vector< std::string > getTablesOfDatabase(const std::string &db_name)
std::string mangle_database_and_collection_name(const std::string &db_name, const std::string &collection_name)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void operator()(sqlite3_stmt *stmt) const