Bug fixing

This commit is contained in:
Your Name
2025-05-25 13:11:13 +12:00
parent 7b3706ebf5
commit f1d6fe661a
5 changed files with 37 additions and 39 deletions

View File

@@ -154,15 +154,15 @@ Database::~Database() {
} }
} }
bool Database::remove(const std::string& label_tag) { bool Database::remove(const std::string& labeltag) {
std::string sql = "DELETE FROM objects WHERE label_tag = ?;"; std::string sql = "DELETE FROM objects WHERE labeltag = ?;";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) { if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
return false; return false;
} }
sqlite3_bind_text(stmt, 1, label_tag.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, labeltag.c_str(), -1, SQLITE_STATIC);
bool success = sqlite3_step(stmt) == SQLITE_DONE; bool success = sqlite3_step(stmt) == SQLITE_DONE;
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return success; return success;
@@ -199,8 +199,8 @@ bool Database::get(const std::string& key, dbEntry& entry) {
if (key.find(':') != std::string::npos) { if (key.find(':') != std::string::npos) {
// Create JSON array pattern for LIKE query // Create JSON array pattern for LIKE query
std::string label_tag_pattern = "%\"" + key + "\"%"; std::string labeltag_pattern = "%\"" + key + "\"%";
sqlite3_bind_text(stmt, 1, label_tag_pattern.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, labeltag_pattern.c_str(), -1, SQLITE_STATIC);
} else { } else {
sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC);
} }
@@ -214,7 +214,7 @@ bool Database::get(const std::string& key, dbEntry& entry) {
std::string labeltags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)); std::string labeltags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2)); std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
entry.label_tags = nlohmann::json::parse(labeltags_str).get<std::vector<std::string>>(); entry.labeltags = nlohmann::json::parse(labeltags_str).get<std::vector<std::string>>();
entry.metadata = nlohmann::json::parse(metadata_str); entry.metadata = nlohmann::json::parse(metadata_str);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
@@ -236,7 +236,7 @@ bool Database::list(std::vector<dbEntry>& entries) {
std::string labeltags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)); std::string labeltags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2)); std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
entry.label_tags = nlohmann::json::parse(labeltags_str).get<std::vector<std::string>>(); entry.labeltags = nlohmann::json::parse(labeltags_str).get<std::vector<std::string>>();
entry.metadata = nlohmann::json::parse(metadata_str); entry.metadata = nlohmann::json::parse(metadata_str);
entries.push_back(entry); entries.push_back(entry);
} }
@@ -247,12 +247,12 @@ bool Database::list(std::vector<dbEntry>& entries) {
bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_entry, dbEntry& merged) { bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_entry, dbEntry& merged) {
// Merge label:tag pairs // Merge label:tag pairs
std::set<std::string> merged_labeltags(existing.label_tags.begin(), existing.label_tags.end()); std::set<std::string> merged_labeltags(existing.labeltags.begin(), existing.labeltags.end());
merged_labeltags.insert(new_entry.label_tags.begin(), new_entry.label_tags.end()); merged_labeltags.insert(new_entry.labeltags.begin(), new_entry.labeltags.end());
// Create merged entry // Create merged entry
merged = new_entry; // Start with new entry's data merged = new_entry; // Start with new entry's data
merged.label_tags = std::vector<std::string>(merged_labeltags.begin(), merged_labeltags.end()); merged.labeltags = std::vector<std::string>(merged_labeltags.begin(), merged_labeltags.end());
// Update metadata - preserve fields from existing entry that aren't in new entry // Update metadata - preserve fields from existing entry that aren't in new entry
merged.metadata = existing.metadata; // Start with existing metadata merged.metadata = existing.metadata; // Start with existing metadata
@@ -261,7 +261,7 @@ bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_
} }
// Ensure required fields are set correctly // Ensure required fields are set correctly
merged.metadata["labeltags"] = merged.label_tags; merged.metadata["labeltags"] = merged.labeltags;
merged.metadata["hash"] = merged.hash; merged.metadata["hash"] = merged.hash;
// Update database // Update database
@@ -272,7 +272,7 @@ bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_
return false; return false;
} }
std::string labeltags_str = nlohmann::json(merged.label_tags).dump(); std::string labeltags_str = nlohmann::json(merged.labeltags).dump();
std::string metadata_str = merged.metadata.dump(); std::string metadata_str = merged.metadata.dump();
sqlite3_bind_text(stmt, 1, labeltags_str.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, labeltags_str.c_str(), -1, SQLITE_STATIC);
@@ -294,10 +294,10 @@ bool Database::insert_new_entry(const dbEntry& entry) {
// Update metadata to include labeltags and hash // Update metadata to include labeltags and hash
nlohmann::json metadata = entry.metadata; nlohmann::json metadata = entry.metadata;
metadata["labeltags"] = entry.label_tags; metadata["labeltags"] = entry.labeltags;
metadata["hash"] = entry.hash; metadata["hash"] = entry.hash;
std::string labeltags_str = nlohmann::json(entry.label_tags).dump(); std::string labeltags_str = nlohmann::json(entry.labeltags).dump();
std::string metadata_str = metadata.dump(); std::string metadata_str = metadata.dump();
sqlite3_bind_text(stmt, 1, entry.hash.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, entry.hash.c_str(), -1, SQLITE_STATIC);
@@ -310,7 +310,7 @@ bool Database::insert_new_entry(const dbEntry& entry) {
} }
bool Database::handle_tag_conflicts(const dbEntry& entry) { bool Database::handle_tag_conflicts(const dbEntry& entry) {
for (const auto& label_tag : entry.label_tags) { for (const auto& labeltag : entry.labeltags) {
// Find all entries with this exact label:tag pair // Find all entries with this exact label:tag pair
std::string find_sql = "SELECT hash, labeltags, metadata FROM objects WHERE labeltags LIKE ?;"; std::string find_sql = "SELECT hash, labeltags, metadata FROM objects WHERE labeltags LIKE ?;";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
@@ -318,8 +318,8 @@ bool Database::handle_tag_conflicts(const dbEntry& entry) {
return false; return false;
} }
std::string label_tag_pattern = "%\"" + label_tag + "\"%"; std::string labeltag_pattern = "%\"" + labeltag + "\"%";
sqlite3_bind_text(stmt, 1, label_tag_pattern.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, labeltag_pattern.c_str(), -1, SQLITE_STATIC);
while (sqlite3_step(stmt) == SQLITE_ROW) { while (sqlite3_step(stmt) == SQLITE_ROW) {
std::string other_hash = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)); std::string other_hash = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
@@ -331,20 +331,20 @@ bool Database::handle_tag_conflicts(const dbEntry& entry) {
// Parse the other entry // Parse the other entry
dbEntry other; dbEntry other;
other.hash = other_hash; other.hash = other_hash;
other.label_tags = nlohmann::json::parse(other_labeltags_str).get<std::vector<std::string>>(); other.labeltags = nlohmann::json::parse(other_labeltags_str).get<std::vector<std::string>>();
other.metadata = nlohmann::json::parse(other_metadata_str); other.metadata = nlohmann::json::parse(other_metadata_str);
// Remove the exact label:tag pair // Remove the exact label:tag pair
std::vector<std::string> new_labeltags; std::vector<std::string> new_labeltags;
for (const auto& other_label_tag : other.label_tags) { for (const auto& other_labeltag : other.labeltags) {
if (other_label_tag != label_tag) { if (other_labeltag != labeltag) {
new_labeltags.push_back(other_label_tag); new_labeltags.push_back(other_labeltag);
} }
} }
// Update the other entry if it had the label:tag pair removed // Update the other entry if it had the label:tag pair removed
if (new_labeltags.size() != other.label_tags.size()) { if (new_labeltags.size() != other.labeltags.size()) {
other.label_tags = new_labeltags; other.labeltags = new_labeltags;
other.metadata["labeltags"] = new_labeltags; // Update metadata to match other.metadata["labeltags"] = new_labeltags; // Update metadata to match
std::string update_sql = "UPDATE objects SET labeltags = ?, metadata = ? WHERE hash = ?;"; std::string update_sql = "UPDATE objects SET labeltags = ?, metadata = ? WHERE hash = ?;";

View File

@@ -12,7 +12,7 @@ namespace simple_object_storage {
class dbEntry { class dbEntry {
public: public:
std::string hash; // unique primary key std::string hash; // unique primary key
std::vector<std::string> label_tags; // multiple label:tag pairs std::vector<std::string> labeltags; // multiple label:tag pairs
nlohmann::json metadata; nlohmann::json metadata;
}; };

View File

@@ -75,14 +75,14 @@ void PutHandler::handle_put_object(const httplib::Request& req, httplib::Respons
} }
// Validate each label:tag pair format // Validate each label:tag pair format
for (const auto& label_tag : metadata["labeltags"]) { for (const auto& labeltag : metadata["labeltags"]) {
if (!label_tag.is_string()) { if (!labeltag.is_string()) {
res.status = 400; res.status = 400;
nlohmann::json response = {{"result", "error"}, {"error", "Invalid label:tag pair format - must be a string"}}; nlohmann::json response = {{"result", "error"}, {"error", "Invalid label:tag pair format - must be a string"}};
res.set_content(response.dump(), "application/json"); res.set_content(response.dump(), "application/json");
return; return;
} }
std::string pair = label_tag.get<std::string>(); std::string pair = labeltag.get<std::string>();
if (pair.find(':') == std::string::npos) { if (pair.find(':') == std::string::npos) {
res.status = 400; res.status = 400;
nlohmann::json response = {{"result", "error"}, {"error", "Invalid label:tag pair format - must contain ':' separator"}}; nlohmann::json response = {{"result", "error"}, {"error", "Invalid label:tag pair format - must contain ':' separator"}};
@@ -165,7 +165,7 @@ void PutHandler::handle_put_object(const httplib::Request& req, httplib::Respons
// Update database index // Update database index
dbEntry entry; dbEntry entry;
entry.hash = std::to_string(hash); entry.hash = std::to_string(hash);
entry.label_tags = metadata["labeltags"].get<std::vector<std::string>>(); entry.labeltags = metadata["labeltags"].get<std::vector<std::string>>();
entry.metadata = metadata; entry.metadata = metadata;
if (!server_.db_->update_or_insert(entry)) { if (!server_.db_->update_or_insert(entry)) {

View File

@@ -236,10 +236,10 @@ void Server::handle_get_object(const httplib::Request& req, httplib::Response& r
} }
void Server::handle_get_hash(const httplib::Request& req, httplib::Response& res) { void Server::handle_get_hash(const httplib::Request& req, httplib::Response& res) {
const auto& label_tag = req.matches[1].str(); const auto& labeltag = req.matches[1].str();
dbEntry entry; dbEntry entry;
if (!db_->get(label_tag, entry)) { if (!db_->get(labeltag, entry)) {
res.status = 404; res.status = 404;
nlohmann::json response = {{"result", "error"}, {"error", "Label:tag not found"}}; nlohmann::json response = {{"result", "error"}, {"error", "Label:tag not found"}};
res.set_content(response.dump(), "application/json"); res.set_content(response.dump(), "application/json");
@@ -262,10 +262,8 @@ void Server::handle_get_directory(const httplib::Request& /*req*/, httplib::Resp
nlohmann::json entries_array = nlohmann::json::array(); nlohmann::json entries_array = nlohmann::json::array();
for (const auto& entry : entries) { for (const auto& entry : entries) {
for (const auto & label : entry.labels) { for (const auto & labeltag : entry.labeltags) {
for (const auto & tag : entry.tags) { entries_array.push_back({{"labeltag", labeltag}, {"hash", entry.hash}});
entries_array.push_back({{"label_tag", label + ":" + tag}, {"hash", entry.hash}});
}
} }
} }
@@ -344,12 +342,12 @@ void Server::handle_get_metadata(const httplib::Request& req, httplib::Response&
res.set_content(response.dump(), "application/json"); res.set_content(response.dump(), "application/json");
} }
std::pair<std::string, std::string> Server::parse_label_tag(const std::string& label_tag) const { std::pair<std::string, std::string> Server::parse_labeltag(const std::string& labeltag) const {
size_t colon_pos = label_tag.find(':'); size_t colon_pos = labeltag.find(':');
if (colon_pos == std::string::npos || colon_pos == 0 || colon_pos == label_tag.length() - 1) { if (colon_pos == std::string::npos || colon_pos == 0 || colon_pos == labeltag.length() - 1) {
return {"", ""}; return {"", ""};
} }
return {label_tag.substr(0, colon_pos), label_tag.substr(colon_pos + 1)}; return {labeltag.substr(0, colon_pos), labeltag.substr(colon_pos + 1)};
} }
void Server::handle_delete_object(const httplib::Request& req, httplib::Response& res) { void Server::handle_delete_object(const httplib::Request& req, httplib::Response& res) {

View File

@@ -20,7 +20,7 @@ public:
bool start(); bool start();
void stop(); void stop();
bool validate_write_request(const httplib::Request& req, httplib::Response& res, const std::vector<std::string>& required_params, std::map<std::string, std::string>& params); bool validate_write_request(const httplib::Request& req, httplib::Response& res, const std::vector<std::string>& required_params, std::map<std::string, std::string>& params);
std::pair<std::string, std::string> parse_label_tag(const std::string& label_tag) const; std::pair<std::string, std::string> parse_labeltag(const std::string& labeltag) const;
// Make these public so PutHandler can access them // Make these public so PutHandler can access them
ServerConfig config_; ServerConfig config_;