Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_resolve_resolveSelectStep.c217 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Global DB handle for tests */7static sqlite3 *gDb = NULL;8 9/* Helper: create a Parse bound to gDb */10static void initParse(Parse *pParse){11  memset(pParse, 0, sizeof(*pParse));12  pParse->db = gDb;13}14 15/* Helper: allocate an empty SrcList (nSrc=0) using the db allocator */16static SrcList* makeEmptySrcList(sqlite3 *db){17  SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));18  if( p ){19    p->nSrc = 0;20  }21  return p;22}23 24/* Helper: create an integer literal expression from text (e.g., "1") */25static Expr* makeIntExpr(sqlite3 *db, const char *z){26  Token t;27  t.z = z;28  t.n = (int)strlen(z);29  return sqlite3ExprAlloc(db, TK_INTEGER, &t, 0);30}31 32/* Helper: create an identifier expression (e.g., column or alias name) */33static Expr* makeIdExpr(sqlite3 *db, const char *z){34  Token t;35  t.z = z;36  t.n = (int)strlen(z);37  return sqlite3ExprAlloc(db, TK_ID, &t, 0);38}39 40/* Helper: create sum(1) expression */41static Expr* makeSum1Expr(Parse *pParse){42  Token tName;43  ExprList *pArgs = 0;44  pArgs = sqlite3ExprListAppend(pParse, pArgs, makeIntExpr(pParse->db, "1"));45  tName.z = "sum";46  tName.n = 3;47  return sqlite3ExprFunction(pParse, pArgs, &tName);48}49 50/* Helper: create a simple expanded SELECT with constant result: SELECT 1; */51static Select* makeExpandedConstSelect(Parse *pParse){52  Select *p = (Select*)sqlite3DbMallocZero(pParse->db, sizeof(Select));53  if( p==0 ) return 0;54  p->pSrc = makeEmptySrcList(pParse->db);55  p->pEList = sqlite3ExprListAppend(pParse, 0, makeIntExpr(pParse->db, "1"));56  p->selFlags = SF_Expanded; /* Pretend already expanded */57  return p;58}59 60/* Helper: free a Select */61static void freeSelect(Select *p){62  if( p ) sqlite3SelectDelete(gDb, p);63}64 65void setUp(void) {66  int rc = sqlite3_open(":memory:", &gDb);67  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);68  TEST_ASSERT_NOT_NULL(gDb);69}70 71void tearDown(void) {72  if( gDb ){73    sqlite3_close(gDb);74    gDb = NULL;75  }76}77 78/* Test: If SF_Resolved is already set, resolveSelectStep returns WRC_Prune immediately. */79void test_resolveSelectStep_already_resolved_returns_prune(void){80  Parse parse; initParse(&parse);81  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;82 83  Select *p = (Select*)sqlite3DbMallocZero(gDb, sizeof(Select));84  TEST_ASSERT_NOT_NULL(p);85  p->selFlags = SF_Resolved; /* Already resolved */86 87  int rc = test_resolveSelectStep(&w, p);88  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);89 90  freeSelect(p);91}92 93/* Test: Expanded constant-only SELECT resolves successfully and sets SF_Resolved. */94void test_resolveSelectStep_expanded_constant_success(void){95  Parse parse; initParse(&parse);96  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;97 98  Select *p = makeExpandedConstSelect(&parse);99  TEST_ASSERT_NOT_NULL(p);100  TEST_ASSERT_NOT_NULL(p->pSrc);101  TEST_ASSERT_NOT_NULL(p->pEList);102 103  int rc = test_resolveSelectStep(&w, p);104  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);105  TEST_ASSERT_TRUE(p->selFlags & SF_Resolved);106  TEST_ASSERT_EQUAL_INT(0, parse.nErr);107 108  freeSelect(p);109}110 111/* Test: Non-expanded SELECT defers to sqlite3SelectPrep and returns WRC_Prune on success. */112void test_resolveSelectStep_not_expanded_calls_select_prep(void){113  Parse parse; initParse(&parse);114  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;115 116  Select *p = (Select*)sqlite3DbMallocZero(gDb, sizeof(Select));117  TEST_ASSERT_NOT_NULL(p);118  /* Provide minimal valid components */119  p->pSrc = makeEmptySrcList(gDb);120  p->pEList = sqlite3ExprListAppend(&parse, 0, makeIntExpr(gDb, "1"));121  /* selFlags intentionally does NOT include SF_Expanded */122 123  int rc = test_resolveSelectStep(&w, p);124  TEST_ASSERT_EQUAL_INT_MESSAGE(WRC_Prune, rc, "Expected sqlite3SelectPrep path to succeed");125  /* sqlite3SelectPrep should have run and resolved the SELECT */126  TEST_ASSERT_TRUE(p->selFlags & SF_Resolved);127  TEST_ASSERT_EQUAL_INT(0, parse.nErr);128 129  freeSelect(p);130}131 132/* Test: SELECT with aggregate in the result-set sets SF_Aggregate and resolves. */133void test_resolveSelectStep_result_aggregate_sets_flag(void){134  Parse parse; initParse(&parse);135  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;136 137  Select *p = (Select*)sqlite3DbMallocZero(gDb, sizeof(Select));138  TEST_ASSERT_NOT_NULL(p);139  p->pSrc = makeEmptySrcList(gDb);140  p->pEList = 0;141  /* Build sum(1) */142  Expr *pSum = makeSum1Expr(&parse);143  TEST_ASSERT_NOT_NULL(pSum);144  p->pEList = sqlite3ExprListAppend(&parse, p->pEList, pSum);145  TEST_ASSERT_NOT_NULL(p->pEList);146  p->selFlags = SF_Expanded;147 148  int rc = test_resolveSelectStep(&w, p);149  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);150  TEST_ASSERT_TRUE_MESSAGE((p->selFlags & SF_Aggregate)!=0, "SF_Aggregate not set");151  TEST_ASSERT_EQUAL_INT(0, parse.nErr);152 153  freeSelect(p);154}155 156/* Test: HAVING on a non-aggregate query triggers an error and aborts. */157void test_resolveSelectStep_having_on_non_aggregate_aborts(void){158  Parse parse; initParse(&parse);159  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;160 161  Select *p = makeExpandedConstSelect(&parse);162  TEST_ASSERT_NOT_NULL(p);163  /* Add HAVING 1 */164  p->pHaving = makeIntExpr(gDb, "1");165 166  int rc = test_resolveSelectStep(&w, p);167  TEST_ASSERT_EQUAL_INT(WRC_Abort, rc);168  TEST_ASSERT_TRUE(parse.nErr>0);169 170  freeSelect(p);171}172 173/* Test: ORDER BY alias resolves to result-set column (iOrderByCol set). */174void test_resolveSelectStep_order_by_alias_resolves(void){175  Parse parse; initParse(&parse);176  Walker w; memset(&w, 0, sizeof(w)); w.pParse = &parse; w.u.pNC = 0;177 178  Select *p = (Select*)sqlite3DbMallocZero(gDb, sizeof(Select));179  TEST_ASSERT_NOT_NULL(p);180  p->pSrc = makeEmptySrcList(gDb);181  /* Build 1+2 AS x */182  Expr *pLeft = makeIntExpr(gDb, "1");183  Expr *pRight = makeIntExpr(gDb, "2");184  Expr *pPlus = sqlite3PExpr(&parse, TK_PLUS, pLeft, pRight);185  TEST_ASSERT_NOT_NULL(pPlus);186  p->pEList = sqlite3ExprListAppend(&parse, 0, pPlus);187  TEST_ASSERT_NOT_NULL(p->pEList);188  Token tX; tX.z = "x"; tX.n = 1;189  sqlite3ExprListSetName(&parse, p->pEList, &tX, 1);190 191  /* ORDER BY x */192  p->pOrderBy = sqlite3ExprListAppend(&parse, 0, makeIdExpr(gDb, "x"));193 194  p->selFlags = SF_Expanded;195 196  int rc = test_resolveSelectStep(&w, p);197  TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);198  TEST_ASSERT_NOT_NULL(p->pOrderBy);199  TEST_ASSERT_TRUE(p->pOrderBy->nExpr>=1);200  /* iOrderByCol should indicate it matches the first result column */201  TEST_ASSERT_TRUE_MESSAGE(p->pOrderBy->a[0].u.x.iOrderByCol==1 || p->pOrderBy->a[0].u.x.iOrderByCol>0,202                           "ORDER BY alias did not resolve to a result-set column");203  TEST_ASSERT_EQUAL_INT(0, parse.nErr);204 205  freeSelect(p);206}207 208int main(void){209  UNITY_BEGIN();210  RUN_TEST(test_resolveSelectStep_already_resolved_returns_prune);211  RUN_TEST(test_resolveSelectStep_expanded_constant_success);212  RUN_TEST(test_resolveSelectStep_not_expanded_calls_select_prep);213  RUN_TEST(test_resolveSelectStep_result_aggregate_sets_flag);214  RUN_TEST(test_resolveSelectStep_having_on_non_aggregate_aborts);215  RUN_TEST(test_resolveSelectStep_order_by_alias_resolves);216  return UNITY_END();217}