18static sqlite3*
db = NULL;
21 "CREATE TABLE IF NOT EXISTS test_suites ("
22 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
23 " title TEXT NOT NULL,"
25 " system_prompt TEXT NOT NULL,"
26 " model TEXT NOT NULL"
28 "CREATE TABLE IF NOT EXISTS user_prompts ("
29 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
30 " prompt TEXT NOT NULL,"
31 " test_suite_id INTEGER NOT NULL,"
32 " FOREIGN KEY (test_suite_id) REFERENCES test_suites(id) ON DELETE CASCADE"
45 int rc = sqlite3_open(db_path, &
db);
46 if (rc != SQLITE_OK) {
47 fprintf(stderr,
"Cannot open database: %s\n", sqlite3_errmsg(
db));
55 rc = sqlite3_exec(
db,
"PRAGMA foreign_keys = ON;", NULL, NULL, &err_msg);
56 if (rc != SQLITE_OK) {
57 fprintf(stderr,
"Failed to enable foreign keys: %s\n", err_msg);
58 sqlite3_free(err_msg);
65 if (rc != SQLITE_OK) {
66 fprintf(stderr,
"SQL error: %s\n", err_msg);
67 sqlite3_free(err_msg);
86 const char* system_prompt,
const char* model) {
87 if (!
db || !title || !system_prompt || !model) {
91 const char* sql =
"INSERT INTO test_suites (title, description, system_prompt, model) "
92 "VALUES (?, ?, ?, ?);";
95 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
96 if (rc != SQLITE_OK) {
97 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
101 sqlite3_bind_text(stmt, 1, title, -1, SQLITE_TRANSIENT);
102 sqlite3_bind_text(stmt, 2, description ? description :
"", -1, SQLITE_TRANSIENT);
103 sqlite3_bind_text(stmt, 3, system_prompt, -1, SQLITE_TRANSIENT);
104 sqlite3_bind_text(stmt, 4, model, -1, SQLITE_TRANSIENT);
106 rc = sqlite3_step(stmt);
107 sqlite3_finalize(stmt);
109 if (rc != SQLITE_DONE) {
110 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
114 return (
int)sqlite3_last_insert_rowid(
db);
118 if (!
db ||
id <= 0) {
122 const char* sql =
"SELECT id, title, description, system_prompt, model "
123 "FROM test_suites WHERE id = ?;";
126 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
127 if (rc != SQLITE_OK) {
128 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
132 sqlite3_bind_int(stmt, 1,
id);
134 rc = sqlite3_step(stmt);
135 if (rc != SQLITE_ROW) {
136 sqlite3_finalize(stmt);
142 sqlite3_finalize(stmt);
146 suite->
id = sqlite3_column_int(stmt, 0);
147 suite->
title = strdup((
const char*)sqlite3_column_text(stmt, 1));
148 suite->
description = strdup((
const char*)sqlite3_column_text(stmt, 2));
149 suite->
system_prompt = strdup((
const char*)sqlite3_column_text(stmt, 3));
150 suite->
model = strdup((
const char*)sqlite3_column_text(stmt, 4));
152 sqlite3_finalize(stmt);
163 const char* sql =
"SELECT id, title, description, system_prompt, model FROM test_suites;";
166 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
167 if (rc != SQLITE_OK) {
168 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
175 sqlite3_finalize(stmt);
179 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
180 if (*count >= capacity) {
185 sqlite3_finalize(stmt);
194 sqlite3_finalize(stmt);
198 suite->
id = sqlite3_column_int(stmt, 0);
199 suite->
title = strdup((
const char*)sqlite3_column_text(stmt, 1));
200 suite->
description = strdup((
const char*)sqlite3_column_text(stmt, 2));
201 suite->
system_prompt = strdup((
const char*)sqlite3_column_text(stmt, 3));
202 suite->
model = strdup((
const char*)sqlite3_column_text(stmt, 4));
204 suites[*count] = suite;
208 sqlite3_finalize(stmt);
219 const char* system_prompt,
const char* model) {
220 if (!
db ||
id <= 0) {
224 if (!title && !description && !system_prompt && !model) {
228 char sql[512] =
"UPDATE test_suites SET ";
232 strcat(sql,
"title = ?");
236 if (!first) strcat(sql,
", ");
237 strcat(sql,
"description = ?");
241 if (!first) strcat(sql,
", ");
242 strcat(sql,
"system_prompt = ?");
246 if (!first) strcat(sql,
", ");
247 strcat(sql,
"model = ?");
250 strcat(sql,
" WHERE id = ?;");
253 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
254 if (rc != SQLITE_OK) {
255 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
260 if (title) sqlite3_bind_text(stmt, param++, title, -1, SQLITE_TRANSIENT);
261 if (description) sqlite3_bind_text(stmt, param++, description, -1, SQLITE_TRANSIENT);
262 if (system_prompt) sqlite3_bind_text(stmt, param++, system_prompt, -1, SQLITE_TRANSIENT);
263 if (model) sqlite3_bind_text(stmt, param++, model, -1, SQLITE_TRANSIENT);
264 sqlite3_bind_int(stmt, param,
id);
266 rc = sqlite3_step(stmt);
267 sqlite3_finalize(stmt);
269 if (rc != SQLITE_DONE) {
270 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
278 if (!
db ||
id <= 0) {
282 const char* sql =
"DELETE FROM test_suites WHERE id = ?;";
285 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
286 if (rc != SQLITE_OK) {
287 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
291 sqlite3_bind_int(stmt, 1,
id);
293 rc = sqlite3_step(stmt);
294 sqlite3_finalize(stmt);
296 if (rc != SQLITE_DONE) {
297 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
316 for (
int i = 0; i < count; i++) {
326 if (!
db || !prompt || test_suite_id <= 0) {
330 const char* sql =
"INSERT INTO user_prompts (prompt, test_suite_id) VALUES (?, ?);";
333 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
334 if (rc != SQLITE_OK) {
335 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
339 sqlite3_bind_text(stmt, 1, prompt, -1, SQLITE_TRANSIENT);
340 sqlite3_bind_int(stmt, 2, test_suite_id);
342 rc = sqlite3_step(stmt);
343 sqlite3_finalize(stmt);
345 if (rc != SQLITE_DONE) {
346 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
350 return (
int)sqlite3_last_insert_rowid(
db);
354 if (!
db ||
id <= 0) {
358 const char* sql =
"SELECT id, prompt, test_suite_id FROM user_prompts WHERE id = ?;";
361 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
362 if (rc != SQLITE_OK) {
363 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
367 sqlite3_bind_int(stmt, 1,
id);
369 rc = sqlite3_step(stmt);
370 if (rc != SQLITE_ROW) {
371 sqlite3_finalize(stmt);
377 sqlite3_finalize(stmt);
381 prompt->
id = sqlite3_column_int(stmt, 0);
382 prompt->
prompt = strdup((
const char*)sqlite3_column_text(stmt, 1));
385 sqlite3_finalize(stmt);
390 if (!
db || test_suite_id <= 0 || !count) {
396 const char* sql =
"SELECT id, prompt, test_suite_id FROM user_prompts WHERE test_suite_id = ?;";
399 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
400 if (rc != SQLITE_OK) {
401 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
405 sqlite3_bind_int(stmt, 1, test_suite_id);
410 sqlite3_finalize(stmt);
414 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
415 if (*count >= capacity) {
420 sqlite3_finalize(stmt);
423 prompts = new_prompts;
429 sqlite3_finalize(stmt);
433 prompt->
id = sqlite3_column_int(stmt, 0);
434 prompt->
prompt = strdup((
const char*)sqlite3_column_text(stmt, 1));
437 prompts[*count] = prompt;
441 sqlite3_finalize(stmt);
458 const char* sql =
"SELECT id, prompt, test_suite_id FROM user_prompts;";
461 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
462 if (rc != SQLITE_OK) {
463 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
470 sqlite3_finalize(stmt);
474 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
475 if (*count >= capacity) {
480 sqlite3_finalize(stmt);
483 prompts = new_prompts;
489 sqlite3_finalize(stmt);
493 prompt->
id = sqlite3_column_int(stmt, 0);
494 prompt->
prompt = strdup((
const char*)sqlite3_column_text(stmt, 1));
497 prompts[*count] = prompt;
501 sqlite3_finalize(stmt);
512 if (!
db ||
id <= 0) {
516 if (!prompt && test_suite_id <= 0) {
520 char sql[256] =
"UPDATE user_prompts SET ";
522 if (prompt && test_suite_id > 0) {
523 strcat(sql,
"prompt = ?, test_suite_id = ? WHERE id = ?;");
525 strcat(sql,
"prompt = ? WHERE id = ?;");
527 strcat(sql,
"test_suite_id = ? WHERE id = ?;");
531 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
532 if (rc != SQLITE_OK) {
533 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
538 if (prompt) sqlite3_bind_text(stmt, param++, prompt, -1, SQLITE_TRANSIENT);
539 if (test_suite_id > 0) sqlite3_bind_int(stmt, param++, test_suite_id);
540 sqlite3_bind_int(stmt, param,
id);
542 rc = sqlite3_step(stmt);
543 sqlite3_finalize(stmt);
545 if (rc != SQLITE_DONE) {
546 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
554 if (!
db ||
id <= 0) {
558 const char* sql =
"DELETE FROM user_prompts WHERE id = ?;";
561 int rc = sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL);
562 if (rc != SQLITE_OK) {
563 fprintf(stderr,
"Failed to prepare statement: %s\n", sqlite3_errmsg(
db));
567 sqlite3_bind_int(stmt, 1,
id);
569 rc = sqlite3_step(stmt);
570 sqlite3_finalize(stmt);
572 if (rc != SQLITE_DONE) {
573 fprintf(stderr,
"Execution failed: %s\n", sqlite3_errmsg(
db));
589 for (
int i = 0; i < count; i++) {
int db_delete_test_suite(int id)
Delete a test suite (cascading deletes associated user prompts).
UserPrompt ** db_get_user_prompts_by_suite(int test_suite_id, int *count)
Retrieve all user prompts for a specific test suite.
static const char * CREATE_TABLES_SQL
void db_close(void)
Close the database connection and release any resources.
TestSuite * db_get_test_suite(int id)
Retrieve a test suite by ID.
void db_free_test_suite(TestSuite *suite)
Free a TestSuite structure.
int db_create_user_prompt(const char *prompt, int test_suite_id)
Create a new user prompt associated with a test suite.
int db_update_test_suite(int id, const char *title, const char *description, const char *system_prompt, const char *model)
Update an existing test suite.
UserPrompt * db_get_user_prompt(int id)
Retrieve a user prompt by ID.
void db_free_user_prompts(UserPrompt **prompts, int count)
Free an array of UserPrompt structures.
UserPrompt ** db_get_all_user_prompts(int *count)
Retrieve all user prompts.
int db_init(const char *db_path)
Initialize the database.
void db_free_user_prompt(UserPrompt *prompt)
Free a UserPrompt structure.
int db_update_user_prompt(int id, const char *prompt, int test_suite_id)
Update an existing user prompt.
TestSuite ** db_get_all_test_suites(int *count)
Retrieve all test suites.
int db_delete_user_prompt(int id)
Delete a user prompt.
int db_create_test_suite(const char *title, const char *description, const char *system_prompt, const char *model)
Create a new test suite.
void db_free_test_suites(TestSuite **suites, int count)
Free an array of TestSuite structures.
Represents a test suite in the database.
Represents a user prompt associated with a test suite.