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());
126 const auto tables_to_be_dropped = getTablesOfDatabase(db_name);
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));
181 if (schemaVersionSet())
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)
192 throw InternalError(
"Could not initialize Database", db_.get());
197 sqlite3_stmt* stmt =
nullptr;
198 if (sqlite3_prepare_v2(db_.get(),
"PRAGMA user_version;", -1, &stmt,
nullptr) != SQLITE_OK)
199 throw InternalError(
"Could not get schema version", db_.get());
201 if (sqlite3_step(stmt_guard.get()) != SQLITE_ROW)
202 throw InternalError(
"Could not get schema version", db_.get());
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))