Bug fixing

This commit is contained in:
Your Name
2025-05-25 12:57:13 +12:00
parent ed998347b5
commit 21d079f285
2 changed files with 50 additions and 75 deletions

View File

@@ -11,8 +11,7 @@ bool Database::createObjectsTable() {
const char* create_table_sql =
"CREATE TABLE IF NOT EXISTS objects ("
"hash TEXT PRIMARY KEY,"
"labels TEXT NOT NULL," // JSON array of labels
"tags TEXT NOT NULL," // JSON array of tags
"label_tags TEXT NOT NULL," // JSON array of label:tag pairs
"metadata TEXT NOT NULL"
");";
@@ -187,10 +186,10 @@ bool Database::get(const std::string& key, dbEntry& entry) {
std::string sql;
if (key.find(':') != std::string::npos) {
// Query by label:tag
sql = "SELECT hash, labels, tags, metadata FROM objects WHERE labels LIKE ? AND tags LIKE ?;";
sql = "SELECT hash, label_tags, metadata FROM objects WHERE label_tags LIKE ?;";
} else {
// Query by hash
sql = "SELECT hash, labels, tags, metadata FROM objects WHERE hash = ?;";
sql = "SELECT hash, label_tags, metadata FROM objects WHERE hash = ?;";
}
sqlite3_stmt* stmt;
@@ -199,17 +198,9 @@ bool Database::get(const std::string& key, dbEntry& entry) {
}
if (key.find(':') != std::string::npos) {
// Split label:tag
size_t pos = key.find(':');
std::string label = key.substr(0, pos);
std::string tag = key.substr(pos + 1);
// Create JSON array patterns for LIKE query
std::string label_pattern = "%\"" + label + "\"%";
std::string tag_pattern = "%\"" + tag + "\"%";
sqlite3_bind_text(stmt, 1, label_pattern.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, tag_pattern.c_str(), -1, SQLITE_STATIC);
// Create JSON array pattern for LIKE query
std::string label_tag_pattern = "%\"" + key + "\"%";
sqlite3_bind_text(stmt, 1, label_tag_pattern.c_str(), -1, SQLITE_STATIC);
} else {
sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC);
}
@@ -220,12 +211,10 @@ bool Database::get(const std::string& key, dbEntry& entry) {
}
entry.hash = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
std::string labels_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
std::string label_tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
entry.labels = nlohmann::json::parse(labels_str).get<std::vector<std::string>>();
entry.tags = nlohmann::json::parse(tags_str).get<std::vector<std::string>>();
entry.label_tags = nlohmann::json::parse(label_tags_str).get<std::vector<std::string>>();
entry.metadata = nlohmann::json::parse(metadata_str);
sqlite3_finalize(stmt);
@@ -233,7 +222,7 @@ bool Database::get(const std::string& key, dbEntry& entry) {
}
bool Database::list(std::vector<dbEntry>& entries) {
std::string sql = "SELECT hash, labels, tags, metadata FROM objects;";
std::string sql = "SELECT hash, label_tags, metadata FROM objects;";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
@@ -244,12 +233,10 @@ bool Database::list(std::vector<dbEntry>& entries) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
dbEntry entry;
entry.hash = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
std::string labels_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
std::string label_tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
entry.labels = nlohmann::json::parse(labels_str).get<std::vector<std::string>>();
entry.tags = nlohmann::json::parse(tags_str).get<std::vector<std::string>>();
entry.label_tags = nlohmann::json::parse(label_tags_str).get<std::vector<std::string>>();
entry.metadata = nlohmann::json::parse(metadata_str);
entries.push_back(entry);
}
@@ -259,16 +246,13 @@ bool Database::list(std::vector<dbEntry>& entries) {
}
bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_entry, dbEntry& merged) {
// Merge labels and tags
std::set<std::string> merged_labels(existing.labels.begin(), existing.labels.end());
merged_labels.insert(new_entry.labels.begin(), new_entry.labels.end());
std::set<std::string> merged_tags(existing.tags.begin(), existing.tags.end());
merged_tags.insert(new_entry.tags.begin(), new_entry.tags.end());
// Merge label:tag pairs
std::set<std::string> merged_label_tags(existing.label_tags.begin(), existing.label_tags.end());
merged_label_tags.insert(new_entry.label_tags.begin(), new_entry.label_tags.end());
// Create merged entry
merged = new_entry; // Start with new entry's data
merged.labels = std::vector<std::string>(merged_labels.begin(), merged_labels.end());
merged.tags = std::vector<std::string>(merged_tags.begin(), merged_tags.end());
merged.label_tags = std::vector<std::string>(merged_label_tags.begin(), merged_label_tags.end());
// Update metadata - preserve fields from existing entry that aren't in new entry
merged.metadata = existing.metadata; // Start with existing metadata
@@ -277,26 +261,23 @@ bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_
}
// Ensure required fields are set correctly
merged.metadata["labels"] = merged.labels;
merged.metadata["tags"] = merged.tags;
merged.metadata["label_tags"] = merged.label_tags;
merged.metadata["hash"] = merged.hash;
// Update database
std::string sql = "UPDATE objects SET labels = ?, tags = ?, metadata = ? WHERE hash = ?;";
std::string sql = "UPDATE objects SET label_tags = ?, metadata = ? WHERE hash = ?;";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
return false;
}
std::string labels_str = nlohmann::json(merged.labels).dump();
std::string tags_str = nlohmann::json(merged.tags).dump();
std::string label_tags_str = nlohmann::json(merged.label_tags).dump();
std::string metadata_str = merged.metadata.dump();
sqlite3_bind_text(stmt, 1, labels_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, metadata_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, merged.hash.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 1, label_tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, metadata_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, merged.hash.c_str(), -1, SQLITE_STATIC);
bool success = sqlite3_step(stmt) == SQLITE_DONE;
sqlite3_finalize(stmt);
@@ -304,27 +285,24 @@ bool Database::merge_existing_entry(const dbEntry& existing, const dbEntry& new_
}
bool Database::insert_new_entry(const dbEntry& entry) {
std::string sql = "INSERT INTO objects (hash, labels, tags, metadata) VALUES (?, ?, ?, ?);";
std::string sql = "INSERT INTO objects (hash, label_tags, metadata) VALUES (?, ?, ?);";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
return false;
}
// Update metadata to include labels, tags, and hash
// Update metadata to include label_tags and hash
nlohmann::json metadata = entry.metadata;
metadata["labels"] = entry.labels;
metadata["tags"] = entry.tags;
metadata["label_tags"] = entry.label_tags;
metadata["hash"] = entry.hash;
std::string labels_str = nlohmann::json(entry.labels).dump();
std::string tags_str = nlohmann::json(entry.tags).dump();
std::string label_tags_str = nlohmann::json(entry.label_tags).dump();
std::string metadata_str = metadata.dump();
sqlite3_bind_text(stmt, 1, entry.hash.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, labels_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, metadata_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, label_tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, metadata_str.c_str(), -1, SQLITE_STATIC);
bool success = sqlite3_step(stmt) == SQLITE_DONE;
sqlite3_finalize(stmt);
@@ -332,56 +310,54 @@ bool Database::insert_new_entry(const dbEntry& entry) {
}
bool Database::handle_tag_conflicts(const dbEntry& entry) {
for (const auto& label : entry.labels) {
// Find all entries with this label
std::string find_sql = "SELECT hash, labels, tags, metadata FROM objects WHERE labels LIKE ?;";
for (const auto& label_tag : entry.label_tags) {
// Find all entries with this exact label:tag pair
std::string find_sql = "SELECT hash, label_tags, metadata FROM objects WHERE label_tags LIKE ?;";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db_, find_sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
return false;
}
std::string label_pattern = "%\"" + label + "\"%";
sqlite3_bind_text(stmt, 1, label_pattern.c_str(), -1, SQLITE_STATIC);
std::string label_tag_pattern = "%\"" + label_tag + "\"%";
sqlite3_bind_text(stmt, 1, label_tag_pattern.c_str(), -1, SQLITE_STATIC);
while (sqlite3_step(stmt) == SQLITE_ROW) {
std::string other_hash = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
if (other_hash == entry.hash) continue; // Skip our own entry
std::string other_labels_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string other_tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
std::string other_metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
std::string other_label_tags_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
std::string other_metadata_str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
// Parse the other entry
dbEntry other;
other.hash = other_hash;
other.labels = nlohmann::json::parse(other_labels_str).get<std::vector<std::string>>();
other.tags = nlohmann::json::parse(other_tags_str).get<std::vector<std::string>>();
other.label_tags = nlohmann::json::parse(other_label_tags_str).get<std::vector<std::string>>();
other.metadata = nlohmann::json::parse(other_metadata_str);
// Remove any tags that are in our entry
std::vector<std::string> new_tags;
for (const auto& tag : other.tags) {
if (std::find(entry.tags.begin(), entry.tags.end(), tag) == entry.tags.end()) {
new_tags.push_back(tag);
// Remove the exact label:tag pair
std::vector<std::string> new_label_tags;
for (const auto& other_label_tag : other.label_tags) {
if (other_label_tag != label_tag) {
new_label_tags.push_back(other_label_tag);
}
}
// Update the other entry if it had any tags removed
if (new_tags.size() != other.tags.size()) {
other.tags = new_tags;
other.metadata["tags"] = new_tags; // Update metadata to match
// Update the other entry if it had the label:tag pair removed
if (new_label_tags.size() != other.label_tags.size()) {
other.label_tags = new_label_tags;
other.metadata["label_tags"] = new_label_tags; // Update metadata to match
std::string update_sql = "UPDATE objects SET tags = ?, metadata = ? WHERE hash = ?;";
std::string update_sql = "UPDATE objects SET label_tags = ?, metadata = ? WHERE hash = ?;";
sqlite3_stmt* update_stmt;
if (sqlite3_prepare_v2(db_, update_sql.c_str(), -1, &update_stmt, nullptr) != SQLITE_OK) {
sqlite3_finalize(stmt);
return false;
}
std::string new_tags_str = nlohmann::json(new_tags).dump();
std::string new_label_tags_str = nlohmann::json(new_label_tags).dump();
std::string new_metadata_str = other.metadata.dump();
sqlite3_bind_text(update_stmt, 1, new_tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(update_stmt, 1, new_label_tags_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(update_stmt, 2, new_metadata_str.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(update_stmt, 3, other.hash.c_str(), -1, SQLITE_STATIC);

View File

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