Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_exprPartidxExprLookup.c258 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Global state for tests */7static sqlite3 *gDb = NULL;8static Parse gParse; /* zeroed in setUp */9static Vdbe *gVdbe = NULL;10 11/* Helper: create a TK_INTEGER expression with EP_IntValue */12static Expr *makeIntExpr(sqlite3 *db, i64 val){13  Expr *e = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));14  TEST_ASSERT_NOT_NULL(e);15  e->op = TK_INTEGER;16  e->flags = EP_IntValue | EP_Leaf | EP_TokenOnly;17  e->u.iValue = val;18  ExprClearVVAProperties(e);19  return e;20}21 22/* Helper: free a single expression allocated with sqlite3DbMallocZero */23static void freeExpr(sqlite3 *db, Expr *e){24  /* Use internal destructor when available */25  if( e ) sqlite3ExprDelete(db, e);26}27 28/* Helper: free pIdxPartExpr list */29static void freeIdxPartExprList(Parse *pParse){30  IndexedExpr *p = pParse->pIdxPartExpr;31  while( p ){32    IndexedExpr *pNext = p->pIENext;33    if( p->pExpr ) freeExpr(pParse->db, p->pExpr);34    sqlite3DbFree(pParse->db, p);35    p = pNext;36  }37  pParse->pIdxPartExpr = NULL;38}39 40void setUp(void) {41  int rc = sqlite3_open(":memory:", &gDb);42  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);43  memset(&gParse, 0, sizeof(gParse));44  gParse.db = gDb;45  gParse.nMem = 100; /* plenty of registers */46  gVdbe = sqlite3VdbeCreate(&gParse);47  TEST_ASSERT_NOT_NULL(gVdbe);48  /* Ensure parse points to vdbe */49  gParse.pVdbe = gVdbe;50  gParse.pIdxPartExpr = NULL;51}52 53void tearDown(void) {54  freeIdxPartExprList(&gParse);55  if( gVdbe ){56    sqlite3VdbeDelete(gVdbe);57    gVdbe = NULL;58    gParse.pVdbe = NULL;59  }60  if( gDb ){61    sqlite3_close(gDb);62    gDb = NULL;63  }64  memset(&gParse, 0, sizeof(gParse));65}66 67/* Utility: fetch op at index */68static VdbeOp *opAt(int i){69  return sqlite3VdbeGetOp(gVdbe, i);70}71 72/* Test: No matching IndexedExpr - should return 0 and emit no ops */73void test_exprPartidxExprLookup_no_match_returns_zero_and_no_ops(void){74  Expr col;75  memset(&col, 0, sizeof(col));76  col.op = TK_COLUMN;77  col.iColumn = 1;78  col.iTable = 2;79 80  int startOps = gVdbe->nOp;81  int ret = test_exprPartidxExprLookup(&gParse, &col, 5);82  TEST_ASSERT_EQUAL_INT(0, ret);83  TEST_ASSERT_EQUAL_INT(startOps, gVdbe->nOp);84}85 86/* Test: Basic match without bMaybeNullRow -> OP_Integer then OP_Affinity */87void test_exprPartidxExprLookup_basic_match_generates_integer_and_affinity(void){88  /* Build matching IndexedExpr */89  IndexedExpr *ie = (IndexedExpr*)sqlite3DbMallocZero(gDb, sizeof(IndexedExpr));90  TEST_ASSERT_NOT_NULL(ie);91  ie->iIdxCol = 1;92  ie->iDataCur = 2;93  ie->iIdxCur = 17; /* arbitrary */94  ie->bMaybeNullRow = 0;95  ie->aff = 'B'; /* TEXT affinity for testing */96  ie->pExpr = makeIntExpr(gDb, 123);97  gParse.pIdxPartExpr = ie;98 99  Expr col;100  memset(&col, 0, sizeof(col));101  col.op = TK_COLUMN;102  col.iColumn = 1;103  col.iTable = 2;104 105  int target = 7;106  int ret = test_exprPartidxExprLookup(&gParse, &col, target);107  TEST_ASSERT_EQUAL_INT(target, ret);108 109  TEST_ASSERT_EQUAL_INT(2, gVdbe->nOp); /* OP_Integer + OP_Affinity */110 111  VdbeOp *op0 = opAt(0);112  VdbeOp *op1 = opAt(1);113  TEST_ASSERT_NOT_NULL(op0);114  TEST_ASSERT_NOT_NULL(op1);115 116  TEST_ASSERT_EQUAL_INT(OP_Integer, op0->opcode);117  TEST_ASSERT_EQUAL_INT(123, op0->p1);118  TEST_ASSERT_EQUAL_INT(target, op0->p2);119 120  TEST_ASSERT_EQUAL_INT(OP_Affinity, op1->opcode);121  TEST_ASSERT_EQUAL_INT(ret, op1->p1);122  TEST_ASSERT_EQUAL_INT(1, op1->p2);123  TEST_ASSERT_EQUAL_INT(0, op1->p3);124  TEST_ASSERT_NOT_NULL(op1->p4.z);125  TEST_ASSERT_EQUAL_INT(ie->aff, (int)(unsigned char)op1->p4.z[0]);126}127 128/* Test: bMaybeNullRow true -> OP_IfNullRow inserted and patched */129void test_exprPartidxExprLookup_maybeNullRow_inserts_and_patches_IfNullRow(void){130  IndexedExpr *ie = (IndexedExpr*)sqlite3DbMallocZero(gDb, sizeof(IndexedExpr));131  TEST_ASSERT_NOT_NULL(ie);132  ie->iIdxCol = 3;133  ie->iDataCur = 4;134  ie->iIdxCur = 5; /* cursor used by IfNullRow */135  ie->bMaybeNullRow = 1;136  ie->aff = 'D'; /* INTEGER affinity */137  ie->pExpr = makeIntExpr(gDb, 77);138  gParse.pIdxPartExpr = ie;139 140  Expr col;141  memset(&col, 0, sizeof(col));142  col.op = TK_COLUMN;143  col.iColumn = 3;144  col.iTable = 4;145 146  int target = 9;147  int ret = test_exprPartidxExprLookup(&gParse, &col, target);148  TEST_ASSERT_EQUAL_INT(target, ret);149 150  TEST_ASSERT_EQUAL_INT(3, gVdbe->nOp); /* IfNullRow + Integer + Affinity */151 152  VdbeOp *op0 = opAt(0);153  VdbeOp *op1 = opAt(1);154  VdbeOp *op2 = opAt(2);155  TEST_ASSERT_NOT_NULL(op0);156  TEST_ASSERT_NOT_NULL(op1);157  TEST_ASSERT_NOT_NULL(op2);158 159  TEST_ASSERT_EQUAL_INT(OP_IfNullRow, op0->opcode);160  TEST_ASSERT_EQUAL_INT(ie->iIdxCur, op0->p1);161  /* p2 is jump destination patched by sqlite3VdbeJumpHere - ensure non-zero */162  TEST_ASSERT(op0->p2 > 0);163  /* p3 patched to ret by sqlite3VdbeChangeP3 */164  TEST_ASSERT_EQUAL_INT(ret, op0->p3);165 166  TEST_ASSERT_EQUAL_INT(OP_Integer, op1->opcode);167  TEST_ASSERT_EQUAL_INT(77, op1->p1);168  TEST_ASSERT_EQUAL_INT(target, op1->p2);169 170  TEST_ASSERT_EQUAL_INT(OP_Affinity, op2->opcode);171  TEST_ASSERT_EQUAL_INT(ret, op2->p1);172  TEST_ASSERT_EQUAL_INT(1, op2->p2);173  TEST_ASSERT_EQUAL_INT(0, op2->p3);174  TEST_ASSERT_NOT_NULL(op2->p4.z);175  TEST_ASSERT_EQUAL_INT(ie->aff, (int)(unsigned char)op2->p4.z[0]);176}177 178/* Test: Multiple nodes - ensure it skips non-matching and uses the matching one */179void test_exprPartidxExprLookup_skips_nonmatching_uses_matching_node(void){180  IndexedExpr *head = (IndexedExpr*)sqlite3DbMallocZero(gDb, sizeof(IndexedExpr));181  IndexedExpr *match = (IndexedExpr*)sqlite3DbMallocZero(gDb, sizeof(IndexedExpr));182  TEST_ASSERT_NOT_NULL(head);183  TEST_ASSERT_NOT_NULL(match);184 185  /* First node - non-matching */186  head->iIdxCol = 10;187  head->iDataCur = 20;188  head->iIdxCur = 30;189  head->bMaybeNullRow = 0;190  head->aff = 'C';191  head->pExpr = makeIntExpr(gDb, 111);192 193  /* Second node - matching */194  match->iIdxCol = 1;195  match->iDataCur = 2;196  match->iIdxCur = 40;197  match->bMaybeNullRow = 0;198  match->aff = 'E'; /* REAL affinity */199  match->pExpr = makeIntExpr(gDb, 222);200 201  head->pIENext = match;202  gParse.pIdxPartExpr = head;203 204  Expr col;205  memset(&col, 0, sizeof(col));206  col.op = TK_COLUMN;207  col.iColumn = 1;208  col.iTable = 2;209 210  int target = 12;211  int ret = test_exprPartidxExprLookup(&gParse, &col, target);212  TEST_ASSERT_EQUAL_INT(target, ret);213 214  TEST_ASSERT_EQUAL_INT(2, gVdbe->nOp);215  VdbeOp *op0 = opAt(0);216  VdbeOp *op1 = opAt(1);217  TEST_ASSERT_EQUAL_INT(OP_Integer, op0->opcode);218  TEST_ASSERT_EQUAL_INT(222, op0->p1);219  TEST_ASSERT_EQUAL_INT(target, op0->p2);220 221  TEST_ASSERT_EQUAL_INT(OP_Affinity, op1->opcode);222  TEST_ASSERT_EQUAL_INT(ret, op1->p1);223  TEST_ASSERT_NOT_NULL(op1->p4.z);224  TEST_ASSERT_EQUAL_INT(match->aff, (int)(unsigned char)op1->p4.z[0]);225}226 227/* Test: Return value is the target register when coding a simple integer expr */228void test_exprPartidxExprLookup_returns_target_register(void){229  IndexedExpr *ie = (IndexedExpr*)sqlite3DbMallocZero(gDb, sizeof(IndexedExpr));230  TEST_ASSERT_NOT_NULL(ie);231  ie->iIdxCol = 7;232  ie->iDataCur = 8;233  ie->iIdxCur = 9;234  ie->bMaybeNullRow = 0;235  ie->aff = 'B';236  ie->pExpr = makeIntExpr(gDb, 5);237  gParse.pIdxPartExpr = ie;238 239  Expr col;240  memset(&col, 0, sizeof(col));241  col.op = TK_COLUMN;242  col.iColumn = 7;243  col.iTable = 8;244 245  int target = 25;246  int ret = test_exprPartidxExprLookup(&gParse, &col, target);247  TEST_ASSERT_EQUAL_INT(target, ret);248}249 250int main(void) {251  UNITY_BEGIN();252  RUN_TEST(test_exprPartidxExprLookup_no_match_returns_zero_and_no_ops);253  RUN_TEST(test_exprPartidxExprLookup_basic_match_generates_integer_and_affinity);254  RUN_TEST(test_exprPartidxExprLookup_maybeNullRow_inserts_and_patches_IfNullRow);255  RUN_TEST(test_exprPartidxExprLookup_skips_nonmatching_uses_matching_node);256  RUN_TEST(test_exprPartidxExprLookup_returns_target_register);257  return UNITY_END();258}