|
|
@@ -8,35 +8,10 @@
|
|
|
|
|
|
#include "../tool/debuglog.h"
|
|
|
|
|
|
-SQLiteVecManager::SQLiteVecManager(const std::string & databaseName) : dbName(databaseName), db(nullptr)
|
|
|
+SQLiteVecManager::SQLiteVecManager()
|
|
|
{
|
|
|
- int rc = SQLITE_OK;
|
|
|
- sqlite3_stmt* stmt;
|
|
|
-
|
|
|
- rc = sqlite3_open(dbName.c_str(), &db);
|
|
|
- assert(rc == SQLITE_OK);
|
|
|
- if (rc != SQLITE_OK)
|
|
|
- {
|
|
|
- std::string err = "Can't open database: " + std::string(sqlite3_errmsg(db));
|
|
|
- throw std::runtime_error("Can't open database: " + std::string(sqlite3_errmsg(db)));
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化 sqlite-vec 扩展
|
|
|
- char* errMsg = 0;
|
|
|
- rc = sqlite3_vec_init(db, &errMsg, 0);
|
|
|
- assert(rc == SQLITE_OK);
|
|
|
- if (rc != SQLITE_OK)
|
|
|
- {
|
|
|
- std::string err = "Can't init vec: " + std::string(sqlite3_errmsg(db));
|
|
|
- throw std::runtime_error("Can't init vec: " + std::string(sqlite3_errmsg(db)));
|
|
|
- }
|
|
|
-
|
|
|
- rc = sqlite3_prepare_v2(db, "SELECT sqlite_version(), vec_version()", -1, &stmt, NULL);
|
|
|
- assert(rc == SQLITE_OK);
|
|
|
-
|
|
|
- rc = sqlite3_step(stmt);
|
|
|
- DEBUG_HELPER::debug_printf("sqlite_version=%s, vec_version=%s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));
|
|
|
- sqlite3_finalize(stmt);
|
|
|
+ db = NULL;
|
|
|
+ dbName = "";
|
|
|
}
|
|
|
|
|
|
SQLiteVecManager::~SQLiteVecManager()
|
|
|
@@ -49,13 +24,59 @@ SQLiteVecManager::~SQLiteVecManager()
|
|
|
|
|
|
bool SQLiteVecManager::initializeDatabase(int vectorDimension)
|
|
|
{
|
|
|
- int rc;
|
|
|
- char * errMsg = 0;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //初始化数据库
|
|
|
+ std::wstring wsProgramDir = CSystem::GetProgramDir();
|
|
|
+ std::filesystem::path mainDir = wsProgramDir;
|
|
|
+ std::string sMainDir = mainDir.string();
|
|
|
+
|
|
|
+ dbName = sMainDir + "/db/image_features.db"; // SQLite数据库路径
|
|
|
+
|
|
|
+ int rc;
|
|
|
+ char* errMsg = 0;
|
|
|
+
|
|
|
+ sqlite3_stmt* stmt;
|
|
|
+
|
|
|
+ rc = sqlite3_open(dbName.c_str(), &db);
|
|
|
+ assert(rc == SQLITE_OK);
|
|
|
+ if (rc != SQLITE_OK)
|
|
|
+ {
|
|
|
+ std::string err = "Can't open database: " + std::string(sqlite3_errmsg(db));
|
|
|
+ throw std::runtime_error("Can't open database: " + std::string(sqlite3_errmsg(db)));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化 sqlite-vec 扩展
|
|
|
+ rc = sqlite3_vec_init(db, &errMsg, 0);
|
|
|
+ assert(rc == SQLITE_OK);
|
|
|
+ if (rc != SQLITE_OK)
|
|
|
+ {
|
|
|
+ std::string err = "Can't init vec: " + std::string(sqlite3_errmsg(db));
|
|
|
+ throw std::runtime_error("Can't init vec: " + std::string(sqlite3_errmsg(db)));
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = sqlite3_prepare_v2(db, "SELECT sqlite_version(), vec_version()", -1, &stmt, NULL);
|
|
|
+ assert(rc == SQLITE_OK);
|
|
|
+
|
|
|
+ rc = sqlite3_step(stmt);
|
|
|
+ DEBUG_HELPER::debug_printf("sqlite_version=%s, vec_version=%s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));
|
|
|
+ sqlite3_finalize(stmt);
|
|
|
+
|
|
|
+ std::cout << "使用sqlite-vec扩展进行向量存储和搜索" << std::endl;
|
|
|
|
|
|
- std::cout << "使用sqlite-vec扩展进行向量存储和搜索" << std::endl;
|
|
|
+ // 检查数据库是否已存在数据
|
|
|
+ bool databaseExists = this->loadDatabase();
|
|
|
+ std::cout << "数据库加载结果:" << std::boolalpha << databaseExists << std::endl;
|
|
|
+ std::cout << "数据集数量:" << this->getFeatureCount() << std::endl;
|
|
|
+ if (databaseExists && this->getFeatureCount() > 0)
|
|
|
+ {
|
|
|
+ std::cout << "数据库已存在 " << this->getFeatureCount() << " 条特征记录" << std::endl;
|
|
|
|
|
|
- // 创建vec0虚拟表【这里只能用TEXT,不能用CHAR,不然创建表会报错】
|
|
|
- std::string sql = R"(CREATE VIRTUAL TABLE IF NOT EXISTS image_features USING vec0(
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建vec0虚拟表【这里只能用TEXT,不能用CHAR,不然创建表会报错】
|
|
|
+ std::string sql = R"(CREATE VIRTUAL TABLE IF NOT EXISTS image_features USING vec0(
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
food_id TEXT NOT NULL,
|
|
|
food_name TEXT UNIQUE NOT NULL,
|
|
|
@@ -63,11 +84,17 @@ bool SQLiteVecManager::initializeDatabase(int vectorDimension)
|
|
|
image_path TEXT UNIQUE NOT NULL,
|
|
|
feature_vector FLOAT[)" + std::to_string(vectorDimension) + "] distance_metric=cosine)";
|
|
|
|
|
|
- rc = sqlite3_exec(db, sql.c_str(), 0, 0, &errMsg);
|
|
|
- if (rc != SQLITE_OK)
|
|
|
+ rc = sqlite3_exec(db, sql.c_str(), 0, 0, &errMsg);
|
|
|
+ if (rc != SQLITE_OK)
|
|
|
+ {
|
|
|
+ std::string err = std::string("Failed to create vec0 table: ") + errMsg;
|
|
|
+ sqlite3_free(errMsg);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (const std::exception& ex)
|
|
|
{
|
|
|
- std::string err = std::string("Failed to create vec0 table: ") + errMsg;
|
|
|
- sqlite3_free(errMsg);
|
|
|
+ std::cerr << "Error initializing database: " << ex.what() << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -195,4 +222,36 @@ bool SQLiteVecManager::isEmpty() const
|
|
|
float SQLiteVecManager::distanceToSimilarity(float distance)
|
|
|
{
|
|
|
return 1.0f - distance;
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<std::pair<std::string, std::string>> SQLiteVecManager::GetFoodXueXiImageInfoByFoodId(const std::string& foodId)
|
|
|
+{
|
|
|
+ std::vector<std::pair<std::string, std::string>> results;
|
|
|
+
|
|
|
+ std::string sql = "SELECT image_name, image_path FROM image_features WHERE food_id = ?;";
|
|
|
+
|
|
|
+ sqlite3_stmt* stmt;
|
|
|
+
|
|
|
+ int rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL);
|
|
|
+
|
|
|
+ if (rc != SQLITE_OK)
|
|
|
+ {
|
|
|
+ std::string err = sqlite3_errmsg(db);
|
|
|
+ std::cerr << "Failed to prepare statement: " << err << std::endl;
|
|
|
+ return results;
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlite3_bind_text(stmt, 1, foodId.c_str(), -1, SQLITE_STATIC);
|
|
|
+
|
|
|
+ while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
|
|
+ {
|
|
|
+ const char* imageName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
|
|
|
+ const char* imagePath = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
|
|
|
+
|
|
|
+ results.emplace_back(std::string(imageName), std::string(imagePath));
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlite3_finalize(stmt);
|
|
|
+
|
|
|
+ return results;
|
|
|
}
|