Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion include/sqlite3db.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,34 @@
} while (0)
#endif // SAFE_SQLITE3_STEP2

/* Forward-declare core proxy types that appear in function pointer prototypes */
class SQLite3_row;
class SQLite3_result;
class SQLite3DB;


#ifndef MAIN_PROXY_SQLITE3
extern int (*proxy_sqlite3_bind_double)(sqlite3_stmt*, int, double);
extern int (*proxy_sqlite3_bind_int)(sqlite3_stmt*, int, int);
extern int (*proxy_sqlite3_bind_int64)(sqlite3_stmt*, int, sqlite3_int64);
extern int (*proxy_sqlite3_bind_null)(sqlite3_stmt*, int);
extern int (*proxy_sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
extern int (*proxy_sqlite3_bind_blob)(sqlite3_stmt*, int, const void*, int, void(*)(void*));
extern const char *(*proxy_sqlite3_column_name)(sqlite3_stmt*, int N);
extern const unsigned char *(*proxy_sqlite3_column_text)(sqlite3_stmt*, int iCol);
extern int (*proxy_sqlite3_column_bytes)(sqlite3_stmt*, int iCol);
extern int (*proxy_sqlite3_column_type)(sqlite3_stmt*, int iCol);
extern int (*proxy_sqlite3_column_count)(sqlite3_stmt *pStmt);
extern int (*proxy_sqlite3_column_int)(sqlite3_stmt*, int iCol);
extern sqlite3_int64 (*proxy_sqlite3_column_int64)(sqlite3_stmt*, int iCol);
extern double (*proxy_sqlite3_column_double)(sqlite3_stmt*, int iCol);
extern sqlite3_int64 (*proxy_sqlite3_last_insert_rowid)(sqlite3*);
extern const char *(*proxy_sqlite3_errstr)(int);
extern sqlite3* (*proxy_sqlite3_db_handle)(sqlite3_stmt*);
extern int (*proxy_sqlite3_enable_load_extension)(sqlite3*, int);
extern int (*proxy_sqlite3_auto_extension)(void(*)(void));
Comment on lines +37 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n '\bMAIN_PROXY_SQLITE3\b'

Repository: ProxySQL/proxysql-vec

Length of output: 186


🏁 Script executed:

head -150 include/sqlite3db.h | cat -n

Repository: ProxySQL/proxysql-vec

Length of output: 7784


🏁 Script executed:

rg -n 'define\s+MAIN_PROXY_SQLITE3' -t c -t cpp -t h

Repository: ProxySQL/proxysql-vec

Length of output: 254


🏁 Script executed:

rg -l 'MAIN_PROXY_SQLITE3' | head -20

Repository: ProxySQL/proxysql-vec

Length of output: 186


🏁 Script executed:

sed -n '82,139p' include/sqlite3db.h | grep -n 'enable_load_extension'

Repository: ProxySQL/proxysql-vec

Length of output: 47


🏁 Script executed:

sed -n '82,139p' include/sqlite3db.h

Repository: ProxySQL/proxysql-vec

Length of output: 2902


Add proxy_sqlite3_enable_load_extension definition to the MAIN_PROXY_SQLITE3 block.

The extern declaration exists at line 43, but the MAIN_PROXY_SQLITE3 definition block (lines 82–139) is missing the corresponding definition. Since MAIN_PROXY_SQLITE3 is actively defined in test files (test/tap/tests/setparser_test.cpp, test/tap/tests/sqlite3-t.cpp, test/tap/tests/setparser_test_common.h), this asymmetry will cause missing symbol definitions in those compilation units.

Fix
sqlite3* (*proxy_sqlite3_db_handle)(sqlite3_stmt*);
+int (*proxy_sqlite3_enable_load_extension)(sqlite3*, int);
int (*proxy_sqlite3_auto_extension)(void(*)(void));
🤖 Prompt for AI Agents
In `@include/sqlite3db.h` around lines 31 - 44, Add the missing definition for
proxy_sqlite3_enable_load_extension inside the MAIN_PROXY_SQLITE3 block so the
symbol declared as extern (int (*proxy_sqlite3_enable_load_extension)(sqlite3*,
int)) has a corresponding definition; follow the pattern used by the other proxy
symbols in that block (declare/initialize the function pointer there, e.g., to
NULL or wired to the real sqlite3_enable_load_extension during init) so test
compilation units that define MAIN_PROXY_SQLITE3 get the symbol.


extern void (*proxy_sqlite3_global_stats_row_step)(SQLite3DB*, sqlite3_stmt*, const char*, ...);
extern const char *(*proxy_sqlite3_errmsg)(sqlite3*);
extern int (*proxy_sqlite3_finalize)(sqlite3_stmt *pStmt);
extern int (*proxy_sqlite3_reset)(sqlite3_stmt *pStmt);
Expand Down Expand Up @@ -77,12 +93,19 @@ int (*proxy_sqlite3_bind_int)(sqlite3_stmt*, int, int);
int (*proxy_sqlite3_bind_int64)(sqlite3_stmt*, int, sqlite3_int64);
int (*proxy_sqlite3_bind_null)(sqlite3_stmt*, int);
int (*proxy_sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*));
int (*proxy_sqlite3_bind_blob)(sqlite3_stmt*, int, const void*, int, void(*)(void*));
sqlite3_int64 (*proxy_sqlite3_column_int64)(sqlite3_stmt*, int iCol);
double (*proxy_sqlite3_column_double)(sqlite3_stmt*, int iCol);
sqlite3_int64 (*proxy_sqlite3_last_insert_rowid)(sqlite3*);
const char *(*proxy_sqlite3_errstr)(int);
sqlite3* (*proxy_sqlite3_db_handle)(sqlite3_stmt*);
const char *(*proxy_sqlite3_column_name)(sqlite3_stmt*, int N);
const unsigned char *(*proxy_sqlite3_column_text)(sqlite3_stmt*, int iCol);
int (*proxy_sqlite3_column_bytes)(sqlite3_stmt*, int iCol);
int (*proxy_sqlite3_column_type)(sqlite3_stmt*, int iCol);
int (*proxy_sqlite3_column_count)(sqlite3_stmt *pStmt);
int (*proxy_sqlite3_column_int)(sqlite3_stmt*, int iCol);
int (*proxy_sqlite3_auto_extension)(void(*)(void));
const char *(*proxy_sqlite3_errmsg)(sqlite3*);
int (*proxy_sqlite3_finalize)(sqlite3_stmt *pStmt);
int (*proxy_sqlite3_reset)(sqlite3_stmt *pStmt);
Expand Down Expand Up @@ -122,7 +145,6 @@ int (*proxy_sqlite3_exec)(
char **errmsg /* Error msg written here */
);
#endif //MAIN_PROXY_SQLITE3

class SQLite3_row {
public:
int cnt;
Expand Down
22 changes: 11 additions & 11 deletions lib/Admin_Bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ using json = nlohmann::json;
*
* @see https://github.com/asg017/sqlite-vec for sqlite-vec documentation
*/
extern "C" int sqlite3_vec_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
extern "C" int sqlite3_rembed_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
extern "C" int (*proxy_sqlite3_vec_init)(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
extern "C" int (*proxy_sqlite3_rembed_init)(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
#include "microhttpd.h"

#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || defined(__mips__)) && defined(__linux)
Expand Down Expand Up @@ -572,7 +572,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* SELECT rowid, distance FROM vec_data WHERE vector MATCH json('[0.1, 0.2, ...]');
* @endcode
*
* @see sqlite3_vec_init() for extension initialization
* @see (*proxy_sqlite3_vec_init)() for extension initialization
* @see deps/sqlite3/README.md for integration documentation
* @see https://github.com/asg017/sqlite-vec for sqlite-vec documentation
*/
Expand All @@ -592,7 +592,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* Allows loading SQLite extensions at runtime. This is required for
* sqlite-vec to be registered when the database is opened.
*/
sqlite3_enable_load_extension(admindb->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(admindb->get_db(),1);

/**
* @brief Register sqlite-vec extension for auto-loading
Expand All @@ -609,8 +609,8 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* @note The sqlite3_vec_init function is cast to a function pointer
* for SQLite's auto-extension mechanism.
*/
sqlite3_auto_extension( (void(*)(void))sqlite3_vec_init);
sqlite3_auto_extension( (void(*)(void))sqlite3_rembed_init);
if (proxy_sqlite3_vec_init) (*proxy_sqlite3_auto_extension)( (void(*)(void))proxy_sqlite3_vec_init);
if (proxy_sqlite3_rembed_init) (*proxy_sqlite3_auto_extension)( (void(*)(void))proxy_sqlite3_rembed_init);

/**
* @brief Open the stats database with shared cache mode
Expand All @@ -627,7 +627,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* Allows loading SQLite extensions at runtime. This enables sqlite-vec to be
* registered in the stats database for advanced analytics operations.
*/
sqlite3_enable_load_extension(statsdb->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(statsdb->get_db(),1);

// check if file exists , see #617
bool admindb_file_exists=Proxy_file_exists(GloVars.admindb);
Expand Down Expand Up @@ -657,7 +657,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* - Configuration optimization with vector-based recommendations
* - Intelligent grouping of similar configurations
*/
sqlite3_enable_load_extension(configdb->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(configdb->get_db(),1);
// Fully synchronous is not required. See to #1055
// https://sqlite.org/pragma.html#pragma_synchronous
configdb->execute("PRAGMA synchronous=0");
Expand All @@ -682,7 +682,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* - Clustering similar server performance metrics
* - Predictive monitoring based on historical vector patterns
*/
sqlite3_enable_load_extension(monitordb->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(monitordb->get_db(),1);

statsdb_disk = new SQLite3DB();
/**
Expand All @@ -704,7 +704,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* - Clustering similar query digests for optimization insights
* - Long-term performance monitoring with vector-based analytics
*/
sqlite3_enable_load_extension(statsdb_disk->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(statsdb_disk->get_db(),1);
// char *dbname = (char *)malloc(strlen(GloVars.statsdb_disk)+50);
// sprintf(dbname,"%s?mode=memory&cache=shared",GloVars.statsdb_disk);
// statsdb_disk->open(dbname, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_FULLMUTEX);
Expand Down Expand Up @@ -733,7 +733,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
* Allows loading SQLite extensions at runtime. This enables sqlite-vec to be
* registered for vector similarity searches in the catalog.
*/
sqlite3_enable_load_extension(mcpdb->get_db(),1);
(*proxy_sqlite3_enable_load_extension)(mcpdb->get_db(),1);

tables_defs_admin=new std::vector<table_def_t *>;
tables_defs_stats=new std::vector<table_def_t *>;
Expand Down
90 changes: 45 additions & 45 deletions lib/Anomaly_Detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,24 +449,24 @@ AnomalyResult Anomaly_Detector::check_embedding_similarity(const std::string& qu
// Execute search
sqlite3* db = vector_db->get_db();
sqlite3_stmt* stmt = NULL;
int rc = sqlite3_prepare_v2(db, search, -1, &stmt, NULL);
int rc = (*proxy_sqlite3_prepare_v2)(db, search, -1, &stmt, NULL);

if (rc != SQLITE_OK) {
proxy_debug(PROXY_DEBUG_ANOMALY, 3, "Embedding search prepare failed: %s", sqlite3_errmsg(db));
proxy_debug(PROXY_DEBUG_ANOMALY, 3, "Embedding search prepare failed: %s", (*proxy_sqlite3_errmsg)(db));
return result;
}

// Check if any threat patterns matched
rc = sqlite3_step(stmt);
rc = (*proxy_sqlite3_step)(stmt);
if (rc == SQLITE_ROW) {
// Found similar threat pattern
result.is_anomaly = true;

// Extract pattern info
const char* pattern_name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
const char* pattern_type = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
int severity = sqlite3_column_int(stmt, 2);
double distance = sqlite3_column_double(stmt, 3);
const char* pattern_name = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 0));
const char* pattern_type = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 1));
int severity = (*proxy_sqlite3_column_int)(stmt, 2);
double distance = (*proxy_sqlite3_column_double)(stmt, 3);

// Calculate risk score based on severity and similarity
// - Base score from severity (1-10) -> 0.1-1.0
Expand Down Expand Up @@ -497,7 +497,7 @@ AnomalyResult Anomaly_Detector::check_embedding_similarity(const std::string& qu
pattern_name ? pattern_name : "unknown", result.risk_score);
}

sqlite3_finalize(stmt);
(*proxy_sqlite3_finalize)(stmt);

proxy_debug(PROXY_DEBUG_ANOMALY, 3,
"Anomaly: Embedding similarity check performed\n");
Expand Down Expand Up @@ -752,42 +752,42 @@ int Anomaly_Detector::add_threat_pattern(const std::string& pattern_name,
"(pattern_name, pattern_type, query_example, embedding, severity) "
"VALUES (?, ?, ?, ?, ?)";

int rc = sqlite3_prepare_v2(db, insert, -1, &stmt, NULL);
int rc = (*proxy_sqlite3_prepare_v2)(db, insert, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
proxy_error("Anomaly: Failed to prepare pattern insert: %s\n", sqlite3_errmsg(db));
proxy_error("Anomaly: Failed to prepare pattern insert: %s\n", (*proxy_sqlite3_errmsg)(db));
return -1;
}

// Bind values
sqlite3_bind_text(stmt, 1, pattern_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, pattern_type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, query_example.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_blob(stmt, 4, embedding.data(), embedding.size() * sizeof(float), SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, severity);
(*proxy_sqlite3_bind_text)(stmt, 1, pattern_name.c_str(), -1, SQLITE_TRANSIENT);
(*proxy_sqlite3_bind_text)(stmt, 2, pattern_type.c_str(), -1, SQLITE_TRANSIENT);
(*proxy_sqlite3_bind_text)(stmt, 3, query_example.c_str(), -1, SQLITE_TRANSIENT);
(*proxy_sqlite3_bind_blob)(stmt, 4, embedding.data(), embedding.size() * sizeof(float), SQLITE_TRANSIENT);
(*proxy_sqlite3_bind_int)(stmt, 5, severity);

// Execute insert
rc = sqlite3_step(stmt);
rc = (*proxy_sqlite3_step)(stmt);
if (rc != SQLITE_DONE) {
proxy_error("Anomaly: Failed to insert pattern: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(stmt);
proxy_error("Anomaly: Failed to insert pattern: %s\n", (*proxy_sqlite3_errmsg)(db));
(*proxy_sqlite3_finalize)(stmt);
return -1;
}

sqlite3_finalize(stmt);
(*proxy_sqlite3_finalize)(stmt);

// Get the inserted rowid
sqlite3_int64 rowid = sqlite3_last_insert_rowid(db);
sqlite3_int64 rowid = (*proxy_sqlite3_last_insert_rowid)(db);

// Update virtual table (sqlite-vec needs explicit rowid insertion)
char update_vec[256];
snprintf(update_vec, sizeof(update_vec),
"INSERT INTO anomaly_patterns_vec(rowid) VALUES (%lld)", rowid);

char* err = NULL;
rc = sqlite3_exec(db, update_vec, NULL, NULL, &err);
rc = (*proxy_sqlite3_exec)(db, update_vec, NULL, NULL, &err);
if (rc != SQLITE_OK) {
proxy_error("Anomaly: Failed to update vec table: %s\n", err ? err : "unknown");
if (err) sqlite3_free(err);
if (err) (*proxy_sqlite3_free)(err);
return -1;
}

Expand All @@ -812,28 +812,28 @@ std::string Anomaly_Detector::list_threat_patterns() {
"FROM anomaly_patterns ORDER BY severity DESC";

sqlite3_stmt* stmt = NULL;
int rc = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
int rc = (*proxy_sqlite3_prepare_v2)(db, query, -1, &stmt, NULL);

if (rc != SQLITE_OK) {
proxy_error("Anomaly: Failed to query threat patterns: %s\n", sqlite3_errmsg(db));
proxy_error("Anomaly: Failed to query threat patterns: %s\n", (*proxy_sqlite3_errmsg)(db));
return "[]";
}

while (sqlite3_step(stmt) == SQLITE_ROW) {
while ((*proxy_sqlite3_step)(stmt) == SQLITE_ROW) {
json pattern;
pattern["id"] = sqlite3_column_int64(stmt, 0);
const char* name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
const char* type = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
const char* example = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
pattern["id"] = (*proxy_sqlite3_column_int64)(stmt, 0);
const char* name = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 1));
const char* type = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 2));
const char* example = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 3));
pattern["pattern_name"] = name ? name : "";
pattern["pattern_type"] = type ? type : "";
pattern["query_example"] = example ? example : "";
pattern["severity"] = sqlite3_column_int(stmt, 4);
pattern["created_at"] = sqlite3_column_int64(stmt, 5);
pattern["severity"] = (*proxy_sqlite3_column_int)(stmt, 4);
pattern["created_at"] = (*proxy_sqlite3_column_int64)(stmt, 5);
patterns.push_back(pattern);
}

sqlite3_finalize(stmt);
(*proxy_sqlite3_finalize)(stmt);

return patterns.dump();
}
Expand All @@ -858,19 +858,19 @@ bool Anomaly_Detector::remove_threat_pattern(int pattern_id) {
char del_vec[256];
snprintf(del_vec, sizeof(del_vec), "DELETE FROM anomaly_patterns_vec WHERE rowid = %d", pattern_id);
char* err = NULL;
int rc = sqlite3_exec(db, del_vec, NULL, NULL, &err);
int rc = (*proxy_sqlite3_exec)(db, del_vec, NULL, NULL, &err);
if (rc != SQLITE_OK) {
proxy_error("Anomaly: Failed to delete from vec table: %s\n", err ? err : "unknown");
if (err) sqlite3_free(err);
if (err) (*proxy_sqlite3_free)(err);
return false;
}

// Then, remove from main table
snprintf(del_vec, sizeof(del_vec), "DELETE FROM anomaly_patterns WHERE id = %d", pattern_id);
rc = sqlite3_exec(db, del_vec, NULL, NULL, &err);
rc = (*proxy_sqlite3_exec)(db, del_vec, NULL, NULL, &err);
if (rc != SQLITE_OK) {
proxy_error("Anomaly: Failed to delete pattern: %s\n", err ? err : "unknown");
if (err) sqlite3_free(err);
if (err) (*proxy_sqlite3_free)(err);
return false;
}

Expand Down Expand Up @@ -912,30 +912,30 @@ std::string Anomaly_Detector::get_statistics() {
sqlite3* db = vector_db->get_db();
const char* count_query = "SELECT COUNT(*) FROM anomaly_patterns";
sqlite3_stmt* stmt = NULL;
int rc = sqlite3_prepare_v2(db, count_query, -1, &stmt, NULL);
int rc = (*proxy_sqlite3_prepare_v2)(db, count_query, -1, &stmt, NULL);

if (rc == SQLITE_OK) {
rc = sqlite3_step(stmt);
rc = (*proxy_sqlite3_step)(stmt);
if (rc == SQLITE_ROW) {
stats["threat_patterns_count"] = sqlite3_column_int(stmt, 0);
stats["threat_patterns_count"] = (*proxy_sqlite3_column_int)(stmt, 0);
}
sqlite3_finalize(stmt);
(*proxy_sqlite3_finalize)(stmt);
}

// Count by pattern type
const char* type_query = "SELECT pattern_type, COUNT(*) FROM anomaly_patterns GROUP BY pattern_type";
rc = sqlite3_prepare_v2(db, type_query, -1, &stmt, NULL);
rc = (*proxy_sqlite3_prepare_v2)(db, type_query, -1, &stmt, NULL);

if (rc == SQLITE_OK) {
json by_type = json::object();
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char* type = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
int count = sqlite3_column_int(stmt, 1);
while ((*proxy_sqlite3_step)(stmt) == SQLITE_ROW) {
const char* type = reinterpret_cast<const char*>((*proxy_sqlite3_column_text)(stmt, 0));
int count = (*proxy_sqlite3_column_int)(stmt, 1);
if (type) {
by_type[type] = count;
}
}
sqlite3_finalize(stmt);
(*proxy_sqlite3_finalize)(stmt);
stats["threat_patterns_by_type"] = by_type;
}
}
Expand Down
Loading