Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_btree_sqlite3BtreeTableMoveto.c252 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdio.h>5#include <string.h>6 7/* Global DB and Btree for each test */8static sqlite3 *gDb = NULL;9static Btree *gBtree = NULL;10 11/* Simple helper to assert SQLite OK */12static void assert_ok_int(int rc, const char *msg){13  if( rc!=SQLITE_OK ){14    printf("Unexpected rc=%d at %s\n", rc, msg);15  }16  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, msg);17}18 19/* Create a new INTKEY table and return its root page number */20static Pgno create_intkey_table(void){21  Pgno root = 0;22  int rc = sqlite3BtreeCreateTable(gBtree, &root, BTREE_INTKEY|BTREE_LEAFDATA);23  assert_ok_int(rc, "sqlite3BtreeCreateTable");24  TEST_ASSERT_TRUE_MESSAGE(root>=2, "Root page should be >= 2");25  return root;26}27 28/* Insert a set of integer keys (rowids) into the intkey table. */29static void insert_keys(Pgno root, const i64 *keys, int nKeys){30  BtCursor cur;31  int rc = sqlite3BtreeCursor(gBtree, root, BTREE_WRCSR, NULL, &cur);32  assert_ok_int(rc, "sqlite3BtreeCursor(open write)");33 34  for(int i=0;i<nKeys;i++){35    BtreePayload x;36    memset(&x, 0, sizeof(x));37    x.nKey = keys[i];38    /* Store a 1-byte payload for each row */39    char data = (char)('A' + (i%26));40    x.pData = &data;41    x.nData = 1;42    x.nZero = 0;43    rc = sqlite3BtreeInsert(&cur, &x, 0, 0);44    assert_ok_int(rc, "sqlite3BtreeInsert");45  }46 47  rc = sqlite3BtreeCloseCursor(&cur);48  assert_ok_int(rc, "sqlite3BtreeCloseCursor");49}50 51/* Open a read-only cursor on root page */52static void open_read_cursor(Pgno root, BtCursor *pCur){53  int rc = sqlite3BtreeCursor(gBtree, root, 0, NULL, pCur);54  assert_ok_int(rc, "sqlite3BtreeCursor(open read)");55}56 57/* Close a cursor */58static void close_cursor(BtCursor *pCur){59  int rc = sqlite3BtreeCloseCursor(pCur);60  assert_ok_int(rc, "sqlite3BtreeCloseCursor");61}62 63void setUp(void){64  int rc = sqlite3_open(":memory:", &gDb);65  assert_ok_int(rc, "sqlite3_open");66  TEST_ASSERT_NOT_NULL(gDb);67  /* Main database btree handle */68  gBtree = gDb->aDb[0].pBt;69  TEST_ASSERT_NOT_NULL(gBtree);70  /* Begin write transaction */71  rc = sqlite3BtreeBeginTrans(gBtree, 1, 0);72  assert_ok_int(rc, "sqlite3BtreeBeginTrans");73}74 75void tearDown(void){76  if( gBtree ){77    sqlite3BtreeCommit(gBtree);78    gBtree = NULL;79  }80  if( gDb ){81    sqlite3_close(gDb);82    gDb = NULL;83  }84}85 86/* Test: sqlite3BtreeTableMoveto on empty table */87void test_sqlite3BtreeTableMoveto_empty_table(void){88  Pgno root = create_intkey_table();89 90  BtCursor cur;91  open_read_cursor(root, &cur);92 93  int res = 12345;94  int rc = sqlite3BtreeTableMoveto(&cur, 1, 0, &res);95  assert_ok_int(rc, "sqlite3BtreeTableMoveto(empty)");96  TEST_ASSERT_EQUAL_INT_MESSAGE(-1, res, "Empty table should yield res=-1");97 98  close_cursor(&cur);99}100 101/* Test: exact matches and between-range searches */102void test_sqlite3BtreeTableMoveto_exact_and_range(void){103  Pgno root = create_intkey_table();104  const i64 keys[] = {10, 20, 30, 40};105  insert_keys(root, keys, (int)(sizeof(keys)/sizeof(keys[0])));106 107  BtCursor cur;108  open_read_cursor(root, &cur);109 110  /* Exact hits */111  for(int i=0;i<4;i++){112    int res = 999;113    int rc = sqlite3BtreeTableMoveto(&cur, keys[i], 0, &res);114    assert_ok_int(rc, "sqlite3BtreeTableMoveto(exact)");115    TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "Exact match should set res=0");116    /* Verify cursor points to that rowid */117    i64 k = sqlite3BtreeIntegerKey(&cur);118    TEST_ASSERT_EQUAL_INT64(keys[i], k);119  }120 121  /* Between-range: search 25 should point to 30 with res>0 */122  {123    int res = 999;124    int rc = sqlite3BtreeTableMoveto(&cur, 25, 0, &res);125    assert_ok_int(rc, "sqlite3BtreeTableMoveto(25)");126    TEST_ASSERT_TRUE_MESSAGE(res>0, "25 should yield res>0 (points to larger key)");127    i64 k = sqlite3BtreeIntegerKey(&cur);128    TEST_ASSERT_EQUAL_INT64(30, k);129  }130 131  /* Below all: search 5 should point to 10 with res>0 */132  {133    int res = 999;134    int rc = sqlite3BtreeTableMoveto(&cur, 5, 0, &res);135    assert_ok_int(rc, "sqlite3BtreeTableMoveto(5)");136    TEST_ASSERT_TRUE_MESSAGE(res>0, "5 should yield res>0 (points to larger key)");137    i64 k = sqlite3BtreeIntegerKey(&cur);138    TEST_ASSERT_EQUAL_INT64(10, k);139  }140 141  close_cursor(&cur);142}143 144/* Test: search greater-than-last returns res<0 and leaves cursor at last */145void test_sqlite3BtreeTableMoveto_greater_than_last(void){146  Pgno root = create_intkey_table();147  const i64 keys[] = {10, 20, 30, 40};148  insert_keys(root, keys, (int)(sizeof(keys)/sizeof(keys[0])));149 150  BtCursor cur;151  open_read_cursor(root, &cur);152 153  int res = 999;154  int rc = sqlite3BtreeTableMoveto(&cur, 100, 0, &res);155  assert_ok_int(rc, "sqlite3BtreeTableMoveto(>last)");156  TEST_ASSERT_TRUE_MESSAGE(res<0, ">last should yield res<0");157  /* Cursor should be at last key (40) */158  i64 k = sqlite3BtreeIntegerKey(&cur);159  TEST_ASSERT_EQUAL_INT64(40, k);160 161  close_cursor(&cur);162}163 164/* Test: biasRight flag should not change search result */165void test_sqlite3BtreeTableMoveto_biasRight_independence(void){166  Pgno root = create_intkey_table();167  const i64 keys[] = {10, 20, 30, 40};168  insert_keys(root, keys, (int)(sizeof(keys)/sizeof(keys[0])));169 170  BtCursor cur;171  open_read_cursor(root, &cur);172 173  int res0 = 0, res1 = 0;174  i64 k0 = 0, k1 = 0;175 176  int rc = sqlite3BtreeTableMoveto(&cur, 25, 0, &res0);177  assert_ok_int(rc, "sqlite3BtreeTableMoveto(25,biasRight=0)");178  k0 = sqlite3BtreeIntegerKey(&cur);179 180  rc = sqlite3BtreeTableMoveto(&cur, 25, 1, &res1);181  assert_ok_int(rc, "sqlite3BtreeTableMoveto(25,biasRight=1)");182  k1 = sqlite3BtreeIntegerKey(&cur);183 184  TEST_ASSERT_EQUAL_INT(res0, res1);185  TEST_ASSERT_EQUAL_INT64(k0, k1);186 187  close_cursor(&cur);188}189 190/* Test: AtLast optimization (cursor already at last and key greater) */191void test_sqlite3BtreeTableMoveto_atlast_optimization(void){192  Pgno root = create_intkey_table();193  const i64 keys[] = {10, 20, 30, 40};194  insert_keys(root, keys, (int)(sizeof(keys)/sizeof(keys[0])));195 196  BtCursor cur;197  open_read_cursor(root, &cur);198 199  int pres = 999;200  int rc = sqlite3BtreeLast(&cur, &pres);201  assert_ok_int(rc, "sqlite3BtreeLast");202  TEST_ASSERT_EQUAL_INT(0, pres);203  i64 lastKey = sqlite3BtreeIntegerKey(&cur);204  TEST_ASSERT_EQUAL_INT64(40, lastKey);205 206  /* Now search for a key greater than last; expect res<0 and to remain at last */207  int res = 888;208  rc = sqlite3BtreeTableMoveto(&cur, 1000, 0, &res);209  assert_ok_int(rc, "sqlite3BtreeTableMoveto(atlast greater)");210  TEST_ASSERT_TRUE_MESSAGE(res<0, "At-last and greater search: res<0");211  i64 stillLast = sqlite3BtreeIntegerKey(&cur);212  TEST_ASSERT_EQUAL_INT64(40, stillLast);213 214  close_cursor(&cur);215}216 217/* Test: Fast path when cursor valid at key K and search K+1 with K+1 present */218void test_sqlite3BtreeTableMoveto_fastpath_increment(void){219  Pgno root = create_intkey_table();220  const i64 keys[] = {20, 21, 30};221  insert_keys(root, keys, (int)(sizeof(keys)/sizeof(keys[0])));222 223  BtCursor cur;224  open_read_cursor(root, &cur);225 226  /* Position exactly at 20 first */227  int res = 999;228  int rc = sqlite3BtreeTableMoveto(&cur, 20, 0, &res);229  assert_ok_int(rc, "sqlite3BtreeTableMoveto(20)");230  TEST_ASSERT_EQUAL_INT(0, res);231  TEST_ASSERT_EQUAL_INT64(20, sqlite3BtreeIntegerKey(&cur));232 233  /* Now search for 21, should use fast path and land on 21 */234  res = 777;235  rc = sqlite3BtreeTableMoveto(&cur, 21, 0, &res);236  assert_ok_int(rc, "sqlite3BtreeTableMoveto(21 fastpath)");237  TEST_ASSERT_EQUAL_INT(0, res);238  TEST_ASSERT_EQUAL_INT64(21, sqlite3BtreeIntegerKey(&cur));239 240  close_cursor(&cur);241}242 243int main(void){244  UNITY_BEGIN();245  RUN_TEST(test_sqlite3BtreeTableMoveto_empty_table);246  RUN_TEST(test_sqlite3BtreeTableMoveto_exact_and_range);247  RUN_TEST(test_sqlite3BtreeTableMoveto_greater_than_last);248  RUN_TEST(test_sqlite3BtreeTableMoveto_biasRight_independence);249  RUN_TEST(test_sqlite3BtreeTableMoveto_atlast_optimization);250  RUN_TEST(test_sqlite3BtreeTableMoveto_fastpath_increment);251  return UNITY_END();252}