Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_prepare_sqlite3Reprepare.c144 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7 8/* Helper to execute SQL and assert success */9static void exec_ok(sqlite3 *db, const char *sql){10  char *zErr = 0;11  int rc = sqlite3_exec(db, sql, 0, 0, &zErr);12  if( rc!=SQLITE_OK ){13    fprintf(stderr, "SQL error (%d): %s\nSQL: %s\n", rc, zErr ? zErr : "(null)", sql);14  }15  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "exec_ok failed");16  if( zErr ) sqlite3_free(zErr);17}18 19void setUp(void) {20  /* Setup code here, or leave empty */21}22 23void tearDown(void) {24  /* Cleanup code here, or leave empty */25}26 27/* Test that sqlite3Reprepare succeeds and transfers bindings from the old stmt */28void test_sqlite3Reprepare_success_transfers_bindings(void){29  sqlite3 *db = 0;30  sqlite3_stmt *stmt = 0;31  int rc;32 33  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));34 35  /* Prepare a simple statement with parameters */36  rc = sqlite3_prepare_v2(db, "SELECT ?1 + ?2", -1, &stmt, 0);37  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);38  TEST_ASSERT_NOT_NULL(stmt);39 40  /* Bind values */41  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_bind_int(stmt, 1, 7));42  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_bind_int(stmt, 2, 5));43 44  /* Call sqlite3Reprepare with db mutex held to satisfy internal assert */45  sqlite3_mutex_enter(db->mutex);46  rc = sqlite3Reprepare((Vdbe*)stmt);47  sqlite3_mutex_leave(db->mutex);48  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);49 50  /* Step the statement and verify result; bindings should be preserved */51  rc = sqlite3_step(stmt);52  TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);53  TEST_ASSERT_EQUAL_INT(12, sqlite3_column_int(stmt, 0));54  rc = sqlite3_step(stmt);55  TEST_ASSERT_EQUAL_INT(SQLITE_DONE, rc);56 57  sqlite3_finalize(stmt);58  sqlite3_close(db);59}60 61/* Test that sqlite3Reprepare returns SQLITE_LOCKED when the schema is locked by another connection */62void test_sqlite3Reprepare_schema_locked_returns_locked(void){63  const char *dbFile = "test_reprepare_locked.sqlite";64  sqlite3 *db1 = 0;65  sqlite3 *db2 = 0;66  sqlite3_stmt *stmt = 0;67  int rc;68 69  /* Ensure clean start */70  remove(dbFile);71 72  /* Open two connections to the same on-disk database */73  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(dbFile, &db1));74  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(dbFile, &db2));75 76  /* Create an initial table so the database and schema exist */77  exec_ok(db1, "CREATE TABLE IF NOT EXISTS t0(x)");78 79  /* Prepare a trivial statement on db1 (does not reference schema itself) */80  rc = sqlite3_prepare_v2(db1, "SELECT ?1", -1, &stmt, 0);81  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);82  TEST_ASSERT_NOT_NULL(stmt);83  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_bind_int(stmt, 1, 123));84 85  /* In db2, begin an exclusive transaction and perform a schema change, leaving txn open */86  exec_ok(db2, "BEGIN EXCLUSIVE");87  exec_ok(db2, "CREATE TABLE t_lock(y)");88 89  /* Now attempt to reprepare on db1: should detect schema lock and return SQLITE_LOCKED */90  sqlite3_mutex_enter(db1->mutex);91  rc = sqlite3Reprepare((Vdbe*)stmt);92  sqlite3_mutex_leave(db1->mutex);93 94  TEST_ASSERT_EQUAL_INT(SQLITE_LOCKED, rc);95 96  /* Cleanup: rollback db2, finalize/close everything */97  exec_ok(db2, "ROLLBACK");98  sqlite3_finalize(stmt);99  sqlite3_close(db2);100  sqlite3_close(db1);101 102  /* Remove the test db file */103  remove(dbFile);104}105 106/* Test that sqlite3Reprepare returns an error when the SQL becomes invalid after a schema change */107void test_sqlite3Reprepare_invalid_sql_returns_error(void){108  sqlite3 *db = 0;109  sqlite3_stmt *stmt = 0;110  int rc;111 112  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));113 114  /* Create table and prepare a statement that references it */115  exec_ok(db, "CREATE TABLE t(a)");116  rc = sqlite3_prepare_v2(db, "SELECT a FROM t", -1, &stmt, 0);117  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);118  TEST_ASSERT_NOT_NULL(stmt);119 120  /* Drop the table so the SQL becomes invalid */121  exec_ok(db, "DROP TABLE t");122 123  /* Reprepare should now fail due to invalid SQL (no such table) */124  sqlite3_mutex_enter(db->mutex);125  rc = sqlite3Reprepare((Vdbe*)stmt);126  sqlite3_mutex_leave(db->mutex);127 128  /* Expect a non-OK error; per current code path, this is SQLITE_ERROR */129  TEST_ASSERT_NOT_EQUAL_INT(SQLITE_OK, rc);130  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);131 132  sqlite3_finalize(stmt);133  sqlite3_close(db);134}135 136int main(void){137  UNITY_BEGIN();138 139  RUN_TEST(test_sqlite3Reprepare_success_transfers_bindings);140  RUN_TEST(test_sqlite3Reprepare_schema_locked_returns_locked);141  RUN_TEST(test_sqlite3Reprepare_invalid_sql_returns_error);142 143  return UNITY_END();144}