Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_resolve_resolveExprStep.c270 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Declare the test wrapper for the static function */6extern int test_resolveExprStep(Walker *pWalker, Expr *pExpr);7 8static sqlite3 *gDb = NULL;9 10void setUp(void) {11  int rc = sqlite3_open(":memory:", &gDb);12  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13  TEST_ASSERT_NOT_NULL(gDb);14}15 16void tearDown(void) {17  if (gDb) {18    sqlite3_close(gDb);19    gDb = NULL;20  }21}22 23/* Helper: initialize a minimal Parse and NameContext and Walker */24static void initParseNcWalker(Parse *pParse, NameContext *pNC, Walker *pWalker){25  memset(pParse, 0, sizeof(*pParse));26  pParse->db = gDb;27  memset(pNC, 0, sizeof(*pNC));28  pNC->pParse = pParse;29  memset(pWalker, 0, sizeof(*pWalker));30  pWalker->xExprCallback = test_resolveExprStep;31  pWalker->pParse = pParse;32  pWalker->u.pNC = pNC;33}34 35/* Test: NOT NULL strength reduction applies in WHERE with non-nullable LHS */36void test_resolveExprStep_notnull_optimized_in_where(void){37  Parse sParse;38  NameContext sNC;39  Walker w;40  initParseNcWalker(&sParse, &sNC, &w);41 42  /* Mark this as WHERE context to allow optimization */43  sNC.ncFlags = NC_Where;44 45  /* Create expression: (123) IS NOT NULL */46  Expr *pLeft = sqlite3Expr(gDb, TK_INTEGER, "123");47  TEST_ASSERT_NOT_NULL(pLeft);48  Expr *pTop = sqlite3PExpr(&sParse, TK_NOTNULL, pLeft, 0);49  TEST_ASSERT_NOT_NULL(pTop);50 51  /* Capture nRef to ensure it is restored after optimization */52  sNC.nRef = 42;53 54  int rc = test_resolveExprStep(&w, pTop);55  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);56 57  /* After optimization, expression becomes integer constant 1 */58  TEST_ASSERT_EQUAL_INT(TK_INTEGER, pTop->op);59  TEST_ASSERT_TRUE( ExprHasProperty(pTop, EP_IntValue) );60  TEST_ASSERT_EQUAL_INT(1, pTop->u.iValue);61  TEST_ASSERT_NULL(pTop->pLeft); /* Left subtree deleted */62  TEST_ASSERT_EQUAL_INT(42, sNC.nRef); /* nRef restored */63 64  sqlite3ExprDelete(gDb, pTop);65}66 67/* Test: IS NULL strength reduction applies in WHERE with non-nullable LHS */68void test_resolveExprStep_isnull_optimized_in_where(void){69  Parse sParse;70  NameContext sNC;71  Walker w;72  initParseNcWalker(&sParse, &sNC, &w);73  sNC.ncFlags = NC_Where;74 75  Expr *pLeft = sqlite3Expr(gDb, TK_INTEGER, "999");76  TEST_ASSERT_NOT_NULL(pLeft);77  Expr *pTop = sqlite3PExpr(&sParse, TK_ISNULL, pLeft, 0);78  TEST_ASSERT_NOT_NULL(pTop);79 80  sNC.nRef = 77;81 82  int rc = test_resolveExprStep(&w, pTop);83  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);84 85  /* Becomes 0 */86  TEST_ASSERT_EQUAL_INT(TK_INTEGER, pTop->op);87  TEST_ASSERT_TRUE( ExprHasProperty(pTop, EP_IntValue) );88  TEST_ASSERT_EQUAL_INT(0, pTop->u.iValue);89  TEST_ASSERT_NULL(pTop->pLeft);90  TEST_ASSERT_EQUAL_INT(77, sNC.nRef);91 92  sqlite3ExprDelete(gDb, pTop);93}94 95/* Test: Strength reduction does not apply if not in WHERE */96void test_resolveExprStep_notnull_not_optimized_outside_where(void){97  Parse sParse;98  NameContext sNC;99  Walker w;100  initParseNcWalker(&sParse, &sNC, &w);101  sNC.ncFlags = 0; /* Not a WHERE clause */102 103  Expr *pLeft = sqlite3Expr(gDb, TK_INTEGER, "1");104  TEST_ASSERT_NOT_NULL(pLeft);105  Expr *pTop = sqlite3PExpr(&sParse, TK_NOTNULL, pLeft, 0);106  TEST_ASSERT_NOT_NULL(pTop);107 108  sNC.nRef = 5;109 110  int rc = test_resolveExprStep(&w, pTop);111  /* When not optimizing, it still returns PRUNE for this case */112  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);113 114  /* No change */115  TEST_ASSERT_EQUAL_INT(TK_NOTNULL, pTop->op);116  TEST_ASSERT_NOT_NULL(pTop->pLeft);117  TEST_ASSERT_EQUAL_INT(5, sNC.nRef);118 119  sqlite3ExprDelete(gDb, pTop);120}121 122/* Test: Strength reduction does not apply if LHS can be NULL */123void test_resolveExprStep_isnull_not_optimized_if_can_be_null(void){124  Parse sParse;125  NameContext sNC;126  Walker w;127  initParseNcWalker(&sParse, &sNC, &w);128  sNC.ncFlags = NC_Where;129 130  /* LHS is TK_NULL -> can be NULL */131  Expr *pLeft = sqlite3Expr(gDb, TK_NULL, 0);132  TEST_ASSERT_NOT_NULL(pLeft);133  Expr *pTop = sqlite3PExpr(&sParse, TK_ISNULL, pLeft, 0);134  TEST_ASSERT_NOT_NULL(pTop);135 136  sNC.nRef = 11;137 138  int rc = test_resolveExprStep(&w, pTop);139  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);140 141  /* No change */142  TEST_ASSERT_EQUAL_INT(TK_ISNULL, pTop->op);143  TEST_ASSERT_NOT_NULL(pTop->pLeft);144  TEST_ASSERT_EQUAL_INT(11, sNC.nRef);145 146  sqlite3ExprDelete(gDb, pTop);147}148 149/* Test: Function unlikely(X, 0.5) sets probability correctly */150void test_resolveExprStep_function_unlikely_probability_valid(void){151  Parse sParse;152  NameContext sNC;153  Walker w;154  initParseNcWalker(&sParse, &sNC, &w);155 156  /* Build argument list: unlikely(1, 0.5) */157  Expr *pArg0 = sqlite3Expr(gDb, TK_INTEGER, "1");158  Expr *pArg1 = sqlite3Expr(gDb, TK_FLOAT, "0.5");159  TEST_ASSERT_NOT_NULL(pArg0);160  TEST_ASSERT_NOT_NULL(pArg1);161 162  ExprList *pList = 0;163  pList = sqlite3ExprListAppend(&sParse, pList, pArg0);164  TEST_ASSERT_NOT_NULL(pList);165  pList = sqlite3ExprListAppend(&sParse, pList, pArg1);166  TEST_ASSERT_NOT_NULL(pList);167 168  Token tFunc;169  memset(&tFunc, 0, sizeof(tFunc));170  tFunc.z = "unlikely";171  tFunc.n = (int)strlen(tFunc.z);172  Expr *pFunc = sqlite3ExprFunction(&sParse, pList, &tFunc, 0);173  TEST_ASSERT_NOT_NULL(pFunc);174 175  int rc = test_resolveExprStep(&w, pFunc);176  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);177 178  /* EP_Unlikely should be set, and iTable should be 0.5 * 2^27 = 67108864 */179  TEST_ASSERT_TRUE( ExprHasProperty(pFunc, EP_Unlikely) );180  TEST_ASSERT_EQUAL_INT(67108864, pFunc->iTable);181 182  /* No error should be recorded */183  TEST_ASSERT_EQUAL_INT(0, sParse.nErr);184 185  sqlite3ExprDelete(gDb, pFunc);186}187 188/* Test: Function unlikely(X, 1.5) - invalid probability -> error */189void test_resolveExprStep_function_unlikely_probability_invalid(void){190  Parse sParse;191  NameContext sNC;192  Walker w;193  initParseNcWalker(&sParse, &sNC, &w);194 195  /* Build argument list: unlikely(1, 1.5) */196  Expr *pArg0 = sqlite3Expr(gDb, TK_INTEGER, "1");197  Expr *pArg1 = sqlite3Expr(gDb, TK_FLOAT, "1.5");198  TEST_ASSERT_NOT_NULL(pArg0);199  TEST_ASSERT_NOT_NULL(pArg1);200 201  ExprList *pList = 0;202  pList = sqlite3ExprListAppend(&sParse, pList, pArg0);203  TEST_ASSERT_NOT_NULL(pList);204  pList = sqlite3ExprListAppend(&sParse, pList, pArg1);205  TEST_ASSERT_NOT_NULL(pList);206 207  Token tFunc;208  memset(&tFunc, 0, sizeof(tFunc));209  tFunc.z = "unlikely";210  tFunc.n = (int)strlen(tFunc.z);211  Expr *pFunc = sqlite3ExprFunction(&sParse, pList, &tFunc, 0);212  TEST_ASSERT_NOT_NULL(pFunc);213 214  int nErrBefore = sParse.nErr;215  int ncErrBefore = sNC.nNcErr;216 217  int rc = test_resolveExprStep(&w, pFunc);218  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);219 220  /* Probability invalid -> iTable < 0 (specifically -1) and error counted */221  TEST_ASSERT_TRUE( pFunc->iTable < 0 );222  TEST_ASSERT_EQUAL_INT(nErrBefore + 1, sParse.nErr);223  TEST_ASSERT_EQUAL_INT(ncErrBefore + 1, sNC.nNcErr);224 225  sqlite3ExprDelete(gDb, pFunc);226}227 228/* Test: "x IS TRUE" transforms into TK_TRUTH */229void test_resolveExprStep_is_true_transforms_to_truth(void){230  Parse sParse;231  NameContext sNC;232  Walker w;233  initParseNcWalker(&sParse, &sNC, &w);234 235  /* left: 0; right: identifier "TRUE" -> should resolve to TK_TRUEFALSE */236  Expr *pLeft = sqlite3Expr(gDb, TK_INTEGER, "0");237  TEST_ASSERT_NOT_NULL(pLeft);238 239  Token tTrue;240  memset(&tTrue, 0, sizeof(tTrue));241  tTrue.z = "TRUE";242  tTrue.n = (int)strlen(tTrue.z);243 244  Expr *pRight = sqlite3ExprAlloc(gDb, TK_ID, &tTrue, 0);245  TEST_ASSERT_NOT_NULL(pRight);246 247  Expr *pTop = sqlite3PExpr(&sParse, TK_IS, pLeft, pRight);248  TEST_ASSERT_NOT_NULL(pTop);249 250  int rc = test_resolveExprStep(&w, pTop);251 252  /* For IS TRUE case, resolveExprStep returns WRC_Continue and sets TK_TRUTH */253  TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);254  TEST_ASSERT_EQUAL_INT(TK_TRUTH, pTop->op);255  TEST_ASSERT_EQUAL_INT(TK_IS, pTop->op2);256 257  sqlite3ExprDelete(gDb, pTop);258}259 260int main(void) {261  UNITY_BEGIN();262  RUN_TEST(test_resolveExprStep_notnull_optimized_in_where);263  RUN_TEST(test_resolveExprStep_isnull_optimized_in_where);264  RUN_TEST(test_resolveExprStep_notnull_not_optimized_outside_where);265  RUN_TEST(test_resolveExprStep_isnull_not_optimized_if_can_be_null);266  RUN_TEST(test_resolveExprStep_function_unlikely_probability_valid);267  RUN_TEST(test_resolveExprStep_function_unlikely_probability_invalid);268  RUN_TEST(test_resolveExprStep_is_true_transforms_to_truth);269  return UNITY_END();270}