AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* External wrapper for the static function under test */7extern int test_jsonEachBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo);8 9/* Helper: create a clean sqlite3_index_info with given capacities */10static void initIndexInfo(sqlite3_index_info *p,11 int nConstraint,12 int nOrderBy,13 struct sqlite3_index_constraint *aConstraint,14 struct sqlite3_index_orderby *aOrderBy,15 struct sqlite3_index_constraint_usage *aUsage){16 memset(p, 0, sizeof(*p));17 p->nConstraint = nConstraint;18 p->aConstraint = aConstraint;19 p->nOrderBy = nOrderBy;20 p->aOrderBy = aOrderBy;21 p->aConstraintUsage = aUsage;22 p->estimatedCost = 9999.0; /* sentinel to detect changes */23}24 25/* Constants for json_each column indices (JSON=8, ROOT=9) */26enum { COL_JSON = 8, COL_ROOT = 9 };27 28void setUp(void) {29 /* no-op */30}31void tearDown(void) {32 /* no-op */33}34 35/* Test: no constraints -> idxNum=0, estimatedCost unchanged, SQLITE_OK */36void test_jsonEachBestIndex_no_constraints(void){37 sqlite3_index_info idx;38 initIndexInfo(&idx, 0, 0, NULL, NULL, NULL);39 idx.idxNum = -1; /* marker */40 int rc = test_jsonEachBestIndex(NULL, &idx);41 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);42 TEST_ASSERT_EQUAL_INT(0, idx.idxNum);43 TEST_ASSERT_EQUAL_DOUBLE(9999.0, idx.estimatedCost);44 TEST_ASSERT_EQUAL_INT(0, idx.orderByConsumed);45}46 47/* Test: usable equality constraint on JSON only */48void test_jsonEachBestIndex_eq_json_only(void){49 struct sqlite3_index_constraint cons[1];50 struct sqlite3_index_constraint_usage usage[1];51 memset(cons, 0, sizeof(cons));52 memset(usage, 0, sizeof(usage));53 cons[0].iColumn = COL_JSON;54 cons[0].op = SQLITE_INDEX_CONSTRAINT_EQ;55 cons[0].usable = 1;56 57 sqlite3_index_info idx;58 initIndexInfo(&idx, 1, 0, cons, NULL, usage);59 60 int rc = test_jsonEachBestIndex(NULL, &idx);61 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);62 TEST_ASSERT_EQUAL_INT(1, idx.idxNum);63 TEST_ASSERT_EQUAL_DOUBLE(1.0, idx.estimatedCost);64 TEST_ASSERT_EQUAL_INT(1, idx.aConstraintUsage[0].argvIndex);65 TEST_ASSERT_EQUAL_UINT8(1, idx.aConstraintUsage[0].omit);66}67 68/* Test: usable equality constraints on JSON and ROOT (reverse order) */69void test_jsonEachBestIndex_eq_json_and_root(void){70 struct sqlite3_index_constraint cons[2];71 struct sqlite3_index_constraint_usage usage[2];72 memset(cons, 0, sizeof(cons));73 memset(usage, 0, sizeof(usage));74 /* Put ROOT first and JSON second to ensure mapping by column not order */75 cons[0].iColumn = COL_ROOT; cons[0].op = SQLITE_INDEX_CONSTRAINT_EQ; cons[0].usable = 1;76 cons[1].iColumn = COL_JSON; cons[1].op = SQLITE_INDEX_CONSTRAINT_EQ; cons[1].usable = 1;77 78 sqlite3_index_info idx;79 initIndexInfo(&idx, 2, 0, cons, NULL, usage);80 81 int rc = test_jsonEachBestIndex(NULL, &idx);82 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83 TEST_ASSERT_EQUAL_INT(3, idx.idxNum);84 TEST_ASSERT_EQUAL_DOUBLE(1.0, idx.estimatedCost);85 /* JSON constraint (index 1) should be argvIndex=1 */86 TEST_ASSERT_EQUAL_INT(1, idx.aConstraintUsage[1].argvIndex);87 TEST_ASSERT_EQUAL_UINT8(1, idx.aConstraintUsage[1].omit);88 /* ROOT constraint (index 0) should be argvIndex=2 */89 TEST_ASSERT_EQUAL_INT(2, idx.aConstraintUsage[0].argvIndex);90 TEST_ASSERT_EQUAL_UINT8(1, idx.aConstraintUsage[0].omit);91}92 93/* Test: unusable JSON constraint -> SQLITE_CONSTRAINT */94void test_jsonEachBestIndex_unusable_json_constraint(void){95 struct sqlite3_index_constraint cons[1];96 struct sqlite3_index_constraint_usage usage[1];97 memset(cons, 0, sizeof(cons));98 memset(usage, 0, sizeof(usage));99 cons[0].iColumn = COL_JSON;100 cons[0].op = SQLITE_INDEX_CONSTRAINT_EQ;101 cons[0].usable = 0; /* unusable */102 103 sqlite3_index_info idx;104 initIndexInfo(&idx, 1, 0, cons, NULL, usage);105 106 int rc = test_jsonEachBestIndex(NULL, &idx);107 TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT, rc);108}109 110/* Test: usable JSON eq + unusable ROOT constraint -> SQLITE_CONSTRAINT */111void test_jsonEachBestIndex_json_eq_root_unusable(void){112 struct sqlite3_index_constraint cons[2];113 struct sqlite3_index_constraint_usage usage[2];114 memset(cons, 0, sizeof(cons));115 memset(usage, 0, sizeof(usage));116 cons[0].iColumn = COL_JSON; cons[0].op = SQLITE_INDEX_CONSTRAINT_EQ; cons[0].usable = 1;117 cons[1].iColumn = COL_ROOT; cons[1].op = SQLITE_INDEX_CONSTRAINT_EQ; cons[1].usable = 0; /* unusable */118 119 sqlite3_index_info idx;120 initIndexInfo(&idx, 2, 0, cons, NULL, usage);121 122 int rc = test_jsonEachBestIndex(NULL, &idx);123 TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT, rc);124}125 126/* Test: ORDER BY rowid ascending is consumed */127void test_jsonEachBestIndex_orderby_rowid_asc_consumed(void){128 struct sqlite3_index_constraint cons[1];129 struct sqlite3_index_constraint_usage usage[1];130 struct sqlite3_index_orderby ob[1];131 memset(cons, 0, sizeof(cons));132 memset(usage, 0, sizeof(usage));133 memset(ob, 0, sizeof(ob));134 135 cons[0].iColumn = COL_JSON;136 cons[0].op = SQLITE_INDEX_CONSTRAINT_EQ;137 cons[0].usable = 1;138 139 ob[0].iColumn = -1; /* rowid */140 ob[0].desc = 0; /* ascending */141 142 sqlite3_index_info idx;143 initIndexInfo(&idx, 1, 1, cons, ob, usage);144 145 int rc = test_jsonEachBestIndex(NULL, &idx);146 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);147 TEST_ASSERT_EQUAL_INT(1, idx.orderByConsumed);148}149 150/* Test: non-equality constraint on JSON is ignored -> idxNum=0 */151void test_jsonEachBestIndex_non_eq_ignored(void){152 struct sqlite3_index_constraint cons[1];153 struct sqlite3_index_constraint_usage usage[1];154 memset(cons, 0, sizeof(cons));155 memset(usage, 0, sizeof(usage));156 cons[0].iColumn = COL_JSON;157 cons[0].op = SQLITE_INDEX_CONSTRAINT_LT; /* not equality */158 cons[0].usable = 1;159 160 sqlite3_index_info idx;161 initIndexInfo(&idx, 1, 0, cons, NULL, usage);162 idx.idxNum = -1;163 164 int rc = test_jsonEachBestIndex(NULL, &idx);165 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);166 TEST_ASSERT_EQUAL_INT(0, idx.idxNum);167 TEST_ASSERT_EQUAL_INT(0, idx.aConstraintUsage[0].argvIndex);168 TEST_ASSERT_EQUAL_UINT8(0, idx.aConstraintUsage[0].omit);169}170 171int main(void){172 UNITY_BEGIN();173 RUN_TEST(test_jsonEachBestIndex_no_constraints);174 RUN_TEST(test_jsonEachBestIndex_eq_json_only);175 RUN_TEST(test_jsonEachBestIndex_eq_json_and_root);176 RUN_TEST(test_jsonEachBestIndex_unusable_json_constraint);177 RUN_TEST(test_jsonEachBestIndex_json_eq_root_unusable);178 RUN_TEST(test_jsonEachBestIndex_orderby_rowid_asc_consumed);179 RUN_TEST(test_jsonEachBestIndex_non_eq_ignored);180 return UNITY_END();181}