Hi, I am using SQLite3 to interact with my SQLite database in C++. I have written this function to make select from queries into my database:
std::vector<std::map<std::string, DatabaseValue>> DatabaseManager::queryData(
const std::string& tables,
const std::string &selection,
const std::string &where = "",
const std::string &other = ""
) const {
const std::string sql = "SELECT " + selection + " FROM " + tables + (where.empty() ? "" : " WHERE " + where) + " " + other + ";";
sqlite3_stmt *stmt;
std::cerr << "\n'" << sql << "'\n";
std::vector<std::map<std::string, DatabaseValue>> results;
// std::cerr << sqlite3_prepare_v2(database, sql.c_str(), -1, &stmt, nullptr);
if (sqlite3_prepare_v2(database, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
std::cerr << "Error preparing statement" << std::endl;
return results;
}
const int cols = sqlite3_column_count(stmt);
while (sqlite3_step(stmt) == SQLITE_ROW) {
std::map<std::string, DatabaseValue> row;
for (int col = 0; col < cols; col++) {
const char *colName = sqlite3_column_name(stmt, col);
const auto colValue = new DatabaseValue(stmt, col);
row[colName] = *colValue;
}
results.push_back(row);
}
sqlite3_finalize(stmt);
return results;
}
This function works, for example here in this other class of mine:
LaunchManager::LaunchManager(DatabaseManager db) : db(&db) {
for (const auto& file: std::filesystem::recursive_directory_iterator(std::filesystem::current_path() / "archive")) {
if(file.is_directory()) continue;
if(file.path().extension() != ".tsv") continue;
const auto extractor = new FileExtractor(file.path().c_str());
const auto launch = extractor->toRadiosondeLaunch();
if(
db.queryData(
"LaunchSites",
"WMONumber",
"LaunchSites.WMONumber='" + launch->GetLaunchSite().GetWmoNumber() + "'",
""
).empty()
) {
db.insertIntoTable(
"LaunchSites",
"WMONumber, StationName, Longitude, Latitude",
"'" + launch->GetLaunchSite().GetWmoNumber()
+ "', '" + launch->GetLaunchSite().GetStationName()
+ "', " + std::to_string(launch->GetLaunchSite().GetLongitude())
+ ", " + std::to_string(launch->GetLaunchSite().GetLatitude())
);
}
}
}
However, when I use this function here:
std::map<std::string, std::pair<time_t, std::string>> LaunchManager::fetchTopLaunches(const int limit) const {
auto query = db->queryData(
"RadiosondeLaunches",
"LaunchSites.WMONumber, RadiosondeLaunches.LaunchDate, LaunchSites.StationName",
"",
"JOIN LaunchSites ON LaunchSites.WMONumber = RadiosondeLaunches.LaunchSite"
);
std::map<std::string, std::pair<time_t, std::string>> results = {};
for (auto row : query) {
results[row["LaunchSites.StationName"].asString() + " - " + std::to_string(row["RadiosondeLaunches.LaunchDate"].asTime())]
= std::make_pair(row["RadiosondeLaunches.LaunchDate"].asTime(), row["LaunchSites.WMONumber"].asString());
}
return results;
}
it doesn't like that. It gives the error: Error preparing statement. This error comes from my check in the queryData function when preparing the statement, and when I output this, the prepare function returns 21, which according to the SQLite result codes is a SQLITE_MISUSE or 'Library used incorrectly'.
The statement produced from my function is is:
SELECT LaunchSites.WMONumber, RadiosondeLaunches.LaunchDate, LaunchSites.StationName FROM RadiosondeLaunches JOIN LaunchSites ON LaunchSites.WMONumber = RadiosondeLaunches.LaunchSite;
which when I run in my Jetbrains database tool, works fine. I can't figure out whats wrong so I'm reaching in case anyone might know.