Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_analyze_analyzeOneTable.c221 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper for the static target function (provided by the module) */7extern void test_analyzeOneTable(8  Parse *pParse,9  Table *pTab,10  Index *pOnlyIdx,11  int iStatCur,12  int iMem,13  int iTab14);15 16static void make_db(sqlite3 **pDb){17  int rc = sqlite3_open(":memory:", pDb);18  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);19}20 21static void exec_sql(sqlite3 *db, const char *zSql){22  char *zErr = 0;23  int rc = sqlite3_exec(db, zSql, 0, 0, &zErr);24  if( rc!=SQLITE_OK ){25    const char *msg = zErr ? zErr : "exec_sql error";26    TEST_FAIL_MESSAGE(msg);27  }28  if( zErr ) sqlite3_free(zErr);29}30 31static void init_parse(sqlite3 *db, Parse *p){32  memset(p, 0, sizeof(*p));33  p->db = db;34}35 36static int count_op(Vdbe *v, int op){37  int cnt = 0;38  if( v==0 ) return 0;39  for(int i=0; i<v->nOp; i++){40    if( v->aOp[i].opcode==op ) cnt++;41  }42  return cnt;43}44 45static int count_op_p1(Vdbe *v, int op, int p1){46  int cnt = 0;47  if( v==0 ) return 0;48  for(int i=0; i<v->nOp; i++){49    if( v->aOp[i].opcode==op && v->aOp[i].p1==p1 ) cnt++;50  }51  return cnt;52}53 54void setUp(void) {55  /* No global setup */56}57 58void tearDown(void) {59  /* No global teardown */60}61 62/* Test 1: System table is ignored (should generate no opcodes) */63void test_analyzeOneTable_system_table_noops(void){64  sqlite3 *db = 0;65  make_db(&db);66 67  /* Obtain Table* for sqlite_master */68  Table *pTab = sqlite3FindTable(db, "sqlite_master", db->aDb[0].zDbSName);69  TEST_ASSERT_NOT_NULL(pTab);70 71  Parse p;72  init_parse(db, &p);73 74  /* Use arbitrary cursor/register bases */75  int iStatCur = 1;76  int iMem = 1;77  int iTab = 2;78 79  test_analyzeOneTable(&p, pTab, 0, iStatCur, iMem, iTab);80 81  /* VDBE should exist but have no opcodes emitted */82  TEST_ASSERT_NOT_NULL(p.pVdbe);83  TEST_ASSERT_EQUAL_INT(0, p.pVdbe->nOp);84 85  sqlite3_close(db);86}87 88/* Test 2: Simple user table without indexes generates code including an89** OP_Insert into sqlite_stat1 (cursor iStatCur). */90void test_analyzeOneTable_simple_table_generates_stat1_insert(void){91  sqlite3 *db = 0;92  make_db(&db);93 94  exec_sql(db, "CREATE TABLE t1(a INTEGER, b TEXT);");95 96  Table *pTab = sqlite3FindTable(db, "t1", db->aDb[0].zDbSName);97  TEST_ASSERT_NOT_NULL(pTab);98 99  Parse p;100  init_parse(db, &p);101 102  int iStatCur = 3;103  int iMem = 1;104  int iTab = 2;105 106  test_analyzeOneTable(&p, pTab, 0, iStatCur, iMem, iTab);107 108  TEST_ASSERT_NOT_NULL(p.pVdbe);109  TEST_ASSERT_TRUE(p.pVdbe->nOp > 0);110 111  /* Expect at least one OP_OpenRead (on the table) */112  TEST_ASSERT_TRUE(count_op(p.pVdbe, OP_OpenRead) >= 1);113 114  /* Expect at least one OP_Insert to iStatCur for sqlite_stat1 */115  int nIns = count_op_p1(p.pVdbe, OP_Insert, iStatCur);116  TEST_ASSERT_TRUE_MESSAGE(nIns >= 1, "Expected OP_Insert into stat1 cursor");117 118  sqlite3_close(db);119}120 121/* Test 3: pOnlyIdx limits analysis to that index. With two indexes,122** analyzing only one should produce fewer OP_OpenRead than analyzing all. */123void test_analyzeOneTable_only_specific_index_restricts(void){124  sqlite3 *db = 0;125  make_db(&db);126 127  exec_sql(db, "CREATE TABLE t2(a, b);\n"128               "CREATE INDEX t2_i1 ON t2(a);\n"129               "CREATE INDEX t2_i2 ON t2(b);");130 131  Table *pTab = sqlite3FindTable(db, "t2", db->aDb[0].zDbSName);132  TEST_ASSERT_NOT_NULL(pTab);133 134  Index *pIdx1 = sqlite3FindIndex(db, "t2_i1", db->aDb[0].zDbSName);135  TEST_ASSERT_NOT_NULL(pIdx1);136 137  /* Analyze only index i1 */138  Parse pOne;139  init_parse(db, &pOne);140  int iStatCur = 4;141  int iMem = 1;142  int iTab = 2;143  test_analyzeOneTable(&pOne, pTab, pIdx1, iStatCur, iMem, iTab);144  TEST_ASSERT_NOT_NULL(pOne.pVdbe);145  int nOpenReadOne = count_op(pOne.pVdbe, OP_OpenRead);146 147  /* Analyze all indexes */148  Parse pAll;149  init_parse(db, &pAll);150  test_analyzeOneTable(&pAll, pTab, 0, iStatCur, iMem, iTab);151  TEST_ASSERT_NOT_NULL(pAll.pVdbe);152  int nOpenReadAll = count_op(pAll.pVdbe, OP_OpenRead);153 154  /* Expect at least one more OP_OpenRead when both indexes are analyzed */155  TEST_ASSERT_TRUE(nOpenReadAll >= nOpenReadOne + 1);156 157  sqlite3_close(db);158}159 160/* Test 4: Final table-count entry (NULL idx in stat1) is included only if161** there are no non-partial indexes. Compare a partial-index-only table vs162** a table with a normal (non-partial) index. */163void test_analyzeOneTable_tablecount_depends_on_partial_indexes(void){164  /* Case A: Only partial index -> expect two OP_Insert to iStatCur:165     one for the partial index entry and one for the table-count entry. */166  {167    sqlite3 *db = 0;168    make_db(&db);169    exec_sql(db, "CREATE TABLE t3(x, y);\n"170                 "CREATE INDEX t3_px ON t3(x) WHERE x IS NOT NULL;");171 172    Table *pTab = sqlite3FindTable(db, "t3", db->aDb[0].zDbSName);173    TEST_ASSERT_NOT_NULL(pTab);174 175    Parse p;176    init_parse(db, &p);177    int iStatCur = 5;178    int iMem = 1;179    int iTab = 2;180    test_analyzeOneTable(&p, pTab, 0, iStatCur, iMem, iTab);181 182    int nIns = count_op_p1(p.pVdbe, OP_Insert, iStatCur);183    TEST_ASSERT_TRUE_MESSAGE(nIns >= 2, "Expected table-count+index entries for partial-index-only table");184 185    sqlite3_close(db);186  }187 188  /* Case B: Has a non-partial index -> expect only per-index OP_Insert, no189     extra table-count OP_Insert at the end. */190  {191    sqlite3 *db = 0;192    make_db(&db);193    exec_sql(db, "CREATE TABLE t4(x, y);\n"194                 "CREATE INDEX t4_nx ON t4(x);");195 196    Table *pTab = sqlite3FindTable(db, "t4", db->aDb[0].zDbSName);197    TEST_ASSERT_NOT_NULL(pTab);198 199    Parse p;200    init_parse(db, &p);201    int iStatCur = 6;202    int iMem = 1;203    int iTab = 2;204    test_analyzeOneTable(&p, pTab, 0, iStatCur, iMem, iTab);205 206    int nIns = count_op_p1(p.pVdbe, OP_Insert, iStatCur);207    /* Exactly one OP_Insert expected for the single non-partial index */208    TEST_ASSERT_EQUAL_INT(1, nIns);209 210    sqlite3_close(db);211  }212}213 214int main(void){215  UNITY_BEGIN();216  RUN_TEST(test_analyzeOneTable_system_table_noops);217  RUN_TEST(test_analyzeOneTable_simple_table_generates_stat1_insert);218  RUN_TEST(test_analyzeOneTable_only_specific_index_restricts);219  RUN_TEST(test_analyzeOneTable_tablecount_depends_on_partial_indexes);220  return UNITY_END();221}