Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_sqlite3ExprCoveredByIndex.c207 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Global database handle used in tests */7static sqlite3 *gDb = NULL;8 9/* Helper: run an SQL statement, assert success */10static void run_sql(const char *zSql){11  char *zErr = NULL;12  int rc = sqlite3_exec(gDb, zSql, 0, 0, &zErr);13  if( rc!=SQLITE_OK ){14    const char *msg = zErr ? zErr : "unknown SQL error";15    TEST_FAIL_MESSAGE(msg);16  }17  if( zErr ) sqlite3_free(zErr);18}19 20/* Helper: fetch Index* by name from "main" schema */21static Index* get_index(const char *zIdxName){22  Index *pIdx = sqlite3FindIndex(gDb, zIdxName, "main");23  return pIdx;24}25 26/* Helper: create a TK_COLUMN Expr node */27static Expr* makeColumnExpr(int iCur, int iCol){28  Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));29  TEST_ASSERT_NOT_NULL(p);30  p->op = TK_COLUMN;31  p->iTable = iCur;32  p->iColumn = iCol;33  return p;34}35 36/* Helper: create a binary Expr node with given op and children */37static Expr* makeBinaryExpr(int op, Expr *pLeft, Expr *pRight){38  Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));39  TEST_ASSERT_NOT_NULL(p);40  p->op = op;41  p->pLeft = pLeft;42  p->pRight = pRight;43  return p;44}45 46/* Helper: create a constant integer Expr node */47static Expr* makeConstIntExpr(void){48  Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));49  TEST_ASSERT_NOT_NULL(p);50  p->op = TK_INTEGER;51  return p;52}53 54void setUp(void) {55  int rc = sqlite3_open(":memory:", &gDb);56  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);57  /* Create a simple table and two indexes for coverage tests */58  run_sql("CREATE TABLE t1(a, b, c);");59  run_sql("CREATE INDEX i_ab ON t1(a, b);");60  run_sql("CREATE INDEX i_c ON t1(c);");61}62 63void tearDown(void) {64  if( gDb ){65    sqlite3_close(gDb);66    gDb = NULL;67  }68}69 70/* Test: single column referenced is covered by index i_ab */71void test_sqlite3ExprCoveredByIndex_single_column_covered(void){72  Index *pIdx = get_index("i_ab");73  TEST_ASSERT_NOT_NULL(pIdx);74 75  int iCur = 1;76  Expr *pColA = makeColumnExpr(iCur, 0); /* column 'a' -> index 0 */77 78  int covered = sqlite3ExprCoveredByIndex(pColA, iCur, pIdx);79  TEST_ASSERT_TRUE(covered);80 81  sqlite3ExprDelete(gDb, pColA);82}83 84/* Test: single column referenced is NOT covered by index i_ab */85void test_sqlite3ExprCoveredByIndex_single_column_not_covered(void){86  Index *pIdx = get_index("i_ab");87  TEST_ASSERT_NOT_NULL(pIdx);88 89  int iCur = 2;90  Expr *pColC = makeColumnExpr(iCur, 2); /* column 'c' -> index 2, not in i_ab */91 92  int covered = sqlite3ExprCoveredByIndex(pColC, iCur, pIdx);93  TEST_ASSERT_FALSE(covered);94 95  sqlite3ExprDelete(gDb, pColC);96}97 98/* Test: expression referencing a different cursor is considered covered */99void test_sqlite3ExprCoveredByIndex_other_cursor_ignored(void){100  Index *pIdx = get_index("i_ab");101  TEST_ASSERT_NOT_NULL(pIdx);102 103  int iCur = 3;104  int otherCur = 99;105  Expr *pColOther = makeColumnExpr(otherCur, 0); /* same column index, different cursor */106 107  int covered = sqlite3ExprCoveredByIndex(pColOther, iCur, pIdx);108  TEST_ASSERT_TRUE(covered);109 110  sqlite3ExprDelete(gDb, pColOther);111}112 113/* Test: composite expression (a + b) fully covered by index i_ab */114void test_sqlite3ExprCoveredByIndex_composite_all_covered(void){115  Index *pIdx = get_index("i_ab");116  TEST_ASSERT_NOT_NULL(pIdx);117 118  int iCur = 4;119  Expr *pA = makeColumnExpr(iCur, 0);120  Expr *pB = makeColumnExpr(iCur, 1);121  Expr *pPlus = makeBinaryExpr(TK_PLUS, pA, pB);122 123  int covered = sqlite3ExprCoveredByIndex(pPlus, iCur, pIdx);124  TEST_ASSERT_TRUE(covered);125 126  sqlite3ExprDelete(gDb, pPlus); /* deletes subtree as well */127}128 129/* Test: composite expression (a + c) NOT fully covered by index i_ab */130void test_sqlite3ExprCoveredByIndex_composite_partial_not_covered(void){131  Index *pIdx = get_index("i_ab");132  TEST_ASSERT_NOT_NULL(pIdx);133 134  int iCur = 5;135  Expr *pA = makeColumnExpr(iCur, 0);136  Expr *pC = makeColumnExpr(iCur, 2);137  Expr *pPlus = makeBinaryExpr(TK_PLUS, pA, pC);138 139  int covered = sqlite3ExprCoveredByIndex(pPlus, iCur, pIdx);140  TEST_ASSERT_FALSE(covered);141 142  sqlite3ExprDelete(gDb, pPlus);143}144 145/* Test: constant expression is always covered (no columns referenced) */146void test_sqlite3ExprCoveredByIndex_constant_expr(void){147  Index *pIdx = get_index("i_ab");148  TEST_ASSERT_NOT_NULL(pIdx);149 150  int iCur = 6;151  Expr *pConst = makeConstIntExpr();152 153  int covered = sqlite3ExprCoveredByIndex(pConst, iCur, pIdx);154  TEST_ASSERT_TRUE(covered);155 156  sqlite3ExprDelete(gDb, pConst);157}158 159/* Test: mixed cursors: part from target cursor covered, part from other cursor */160void test_sqlite3ExprCoveredByIndex_mixed_cursors_other_side_irrelevant(void){161  Index *pIdx = get_index("i_ab");162  TEST_ASSERT_NOT_NULL(pIdx);163 164  int iCur = 7;165  int otherCur = 88;166 167  Expr *pA = makeColumnExpr(iCur, 0);          /* covered by i_ab */168  Expr *pOtherC = makeColumnExpr(otherCur, 2); /* not in i_ab but different cursor */169  Expr *pAnd = makeBinaryExpr(TK_AND, pA, pOtherC);170 171  int covered = sqlite3ExprCoveredByIndex(pAnd, iCur, pIdx);172  TEST_ASSERT_TRUE(covered);173 174  sqlite3ExprDelete(gDb, pAnd);175}176 177/* Test: same-structure but index i_c should cover only column c */178void test_sqlite3ExprCoveredByIndex_with_different_index(void){179  Index *pIdx_c = get_index("i_c");180  TEST_ASSERT_NOT_NULL(pIdx_c);181 182  int iCur = 10;183  Expr *pC = makeColumnExpr(iCur, 2);184  Expr *pB = makeColumnExpr(iCur, 1);185 186  /* c covered by i_c */187  TEST_ASSERT_TRUE(sqlite3ExprCoveredByIndex(pC, iCur, pIdx_c));188 189  /* b not covered by i_c */190  TEST_ASSERT_FALSE(sqlite3ExprCoveredByIndex(pB, iCur, pIdx_c));191 192  sqlite3ExprDelete(gDb, pC);193  sqlite3ExprDelete(gDb, pB);194}195 196int main(void){197  UNITY_BEGIN();198  RUN_TEST(test_sqlite3ExprCoveredByIndex_single_column_covered);199  RUN_TEST(test_sqlite3ExprCoveredByIndex_single_column_not_covered);200  RUN_TEST(test_sqlite3ExprCoveredByIndex_other_cursor_ignored);201  RUN_TEST(test_sqlite3ExprCoveredByIndex_composite_all_covered);202  RUN_TEST(test_sqlite3ExprCoveredByIndex_composite_partial_not_covered);203  RUN_TEST(test_sqlite3ExprCoveredByIndex_constant_expr);204  RUN_TEST(test_sqlite3ExprCoveredByIndex_mixed_cursors_other_side_irrelevant);205  RUN_TEST(test_sqlite3ExprCoveredByIndex_with_different_index);206  return UNITY_END();207}