AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6 7/* Unity setUp/tearDown */8void setUp(void) {9 /* no-op */10}11void tearDown(void) {12 /* no-op */13}14 15/* Helper to call sqlite3AnalysisLoad with proper mutex/locks */16static int call_sqlite3AnalysisLoad_with_locks(sqlite3 *db, int iDb){17 int rc;18 sqlite3_mutex_enter(db->mutex);19 sqlite3BtreeEnterAll(db);20 rc = sqlite3AnalysisLoad(db, iDb);21 sqlite3BtreeLeaveAll(db);22 sqlite3_mutex_leave(db->mutex);23 return rc;24}25 26/* Convenience wrappers to find schema objects in "main" */27static Index* findIndex(sqlite3 *db, const char *zName){28 return sqlite3FindIndex(db, zName, "main");29}30static Table* findTable(sqlite3 *db, const char *zName){31 return sqlite3FindTable(db, zName, "main");32}33 34/* Test 1: No sqlite_stat1 present */35void test_sqlite3AnalysisLoad_no_stat_tables(void){36 sqlite3 *db = 0;37 int rc;38 39 rc = sqlite3_open(":memory:", &db);40 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);41 TEST_ASSERT_NOT_NULL(db);42 43 rc = sqlite3_exec(db,44 "CREATE TABLE t1(a,b);"45 "CREATE INDEX i1 ON t1(a);",46 0, 0, 0);47 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);48 49 rc = call_sqlite3AnalysisLoad_with_locks(db, 0);50 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);51 52 Index *pIdx1 = findIndex(db, "i1");53 TEST_ASSERT_NOT_NULL(pIdx1);54 TEST_ASSERT_EQUAL_INT(0, pIdx1->hasStat1);55 56 Table *pTab1 = findTable(db, "t1");57 TEST_ASSERT_NOT_NULL(pTab1);58 TEST_ASSERT_TRUE((pTab1->tabFlags & TF_HasStat1) == 0);59 60 sqlite3_close(db);61}62 63/* Test 2: sqlite_stat1 with index-level and table-level rows */64void test_sqlite3AnalysisLoad_with_stat1_index_and_table(void){65 sqlite3 *db = 0;66 int rc;67 68 rc = sqlite3_open(":memory:", &db);69 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);70 TEST_ASSERT_NOT_NULL(db);71 72 rc = sqlite3_exec(db,73 "CREATE TABLE t1(a,b);"74 "CREATE UNIQUE INDEX i1 ON t1(a,b);"75 "CREATE INDEX i2 ON t1(a);"76 "CREATE TABLE sqlite_stat1(tbl,idx,stat);"77 "INSERT INTO sqlite_stat1(tbl,idx,stat)"78 " VALUES('t1','i1','100 10 1');"79 "INSERT INTO sqlite_stat1(tbl,idx,stat)"80 " VALUES('t1',NULL,'123');",81 0, 0, 0);82 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83 84 rc = call_sqlite3AnalysisLoad_with_locks(db, 0);85 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);86 87 Index *pIdx1 = findIndex(db, "i1");88 Index *pIdx2 = findIndex(db, "i2");89 Table *pTab1 = findTable(db, "t1");90 91 TEST_ASSERT_NOT_NULL(pIdx1);92 TEST_ASSERT_NOT_NULL(pIdx2);93 TEST_ASSERT_NOT_NULL(pTab1);94 95 /* i1 had a row in sqlite_stat1, i2 did not */96 TEST_ASSERT_EQUAL_INT(1, pIdx1->hasStat1);97 TEST_ASSERT_EQUAL_INT(0, pIdx2->hasStat1);98 99 /* tbl-level row present -> TF_HasStat1 should be set */100 TEST_ASSERT_TRUE( (pTab1->tabFlags & TF_HasStat1) != 0 );101 102 sqlite3_close(db);103}104 105/* Test 3: Prior statistics are cleared on reload */106void test_sqlite3AnalysisLoad_stats_cleared_on_reload(void){107 sqlite3 *db = 0;108 int rc;109 110 rc = sqlite3_open(":memory:", &db);111 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);112 TEST_ASSERT_NOT_NULL(db);113 114 rc = sqlite3_exec(db,115 "CREATE TABLE t1(a,b);"116 "CREATE INDEX i1 ON t1(a);"117 "CREATE TABLE sqlite_stat1(tbl,idx,stat);"118 "INSERT INTO sqlite_stat1(tbl,idx,stat)"119 " VALUES('t1','i1','100 50');",120 0, 0, 0);121 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);122 123 /* First load: i1 should have stats */124 rc = call_sqlite3AnalysisLoad_with_locks(db, 0);125 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);126 127 Index *pIdx1 = findIndex(db, "i1");128 TEST_ASSERT_NOT_NULL(pIdx1);129 TEST_ASSERT_EQUAL_INT(1, pIdx1->hasStat1);130 131 /* Remove the i1 row from sqlite_stat1 and reload */132 rc = sqlite3_exec(db, "DELETE FROM sqlite_stat1 WHERE tbl='t1' AND idx='i1';",133 0, 0, 0);134 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);135 136 rc = call_sqlite3AnalysisLoad_with_locks(db, 0);137 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);138 139 /* After reload, hasStat1 should be cleared since no longer present */140 pIdx1 = findIndex(db, "i1");141 TEST_ASSERT_NOT_NULL(pIdx1);142 TEST_ASSERT_EQUAL_INT(0, pIdx1->hasStat1);143 144 sqlite3_close(db);145}146 147int main(void){148 UNITY_BEGIN();149 RUN_TEST(test_sqlite3AnalysisLoad_no_stat_tables);150 RUN_TEST(test_sqlite3AnalysisLoad_with_stat1_index_and_table);151 RUN_TEST(test_sqlite3AnalysisLoad_stats_cleared_on_reload);152 return UNITY_END();153}