Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_sqlite3ExprAnalyzeAggregates.c214 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Forward declaration of the target under test (already provided by includes) */7/* void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr); */8 9static sqlite3* openTestDb(void){10  sqlite3 *db = 0;11  int rc = sqlite3_open(":memory:", &db);12  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Failed to open in-memory DB");13  TEST_ASSERT_NOT_NULL(db);14  return db;15}16 17static void closeTestDb(sqlite3 *db){18  if( db ){19    sqlite3_close(db);20  }21}22 23static void initParse(Parse *pParse, sqlite3 *db){24  memset(pParse, 0, sizeof(*pParse));25  pParse->db = db;26}27 28/* Create a minimal non-NULL SrcList to satisfy the assert in sqlite3ExprAnalyzeAggregates */29static SrcList* makeMinimalSrcList(sqlite3 *db){30  SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));31  /* We don't need to populate it; just non-NULL */32  return p;33}34 35/* Helper: build function expression fName(argExprList) */36static Expr* makeFunctionExpr(Parse *pParse, const char *zFunc, ExprList *pArgs){37  Token tFunc;38  tFunc.z = zFunc;39  tFunc.n = (int)strlen(zFunc);40  return sqlite3ExprFunction(pParse, pArgs, &tFunc);41}42 43/* Helper: create integer literal expression with a given string (e.g., "1") */44static Expr* makeIntegerLiteral(sqlite3 *db, const char *zNum){45  Token tNum;46  tNum.z = zNum;47  tNum.n = (int)strlen(zNum);48  return sqlite3ExprAlloc(db, TK_INTEGER, &tNum, 0);49}50 51/* Helper: append expression to an ExprList (creating the list if NULL) */52static ExprList* appendExprToList(Parse *pParse, ExprList *pList, Expr *pExpr){53  return sqlite3ExprListAppend(pParse, pList, pExpr);54}55 56void setUp(void) {57  /* No global setup */58}59void tearDown(void) {60  /* No global cleanup */61}62 63/* Test 1: NULL expression should be a no-op and not crash. */64static void test_sqlite3ExprAnalyzeAggregates_null_expr_noop(void){65  sqlite3 *db = openTestDb();66  Parse parse;67  initParse(&parse, db);68 69  NameContext nc;70  memset(&nc, 0, sizeof(nc));71  nc.pParse = &parse;72  nc.pSrcList = makeMinimalSrcList(db);73 74  AggInfo agg;75  memset(&agg, 0, sizeof(agg));76  nc.pAggInfo = &agg;77 78  /* Call with NULL expression */79  sqlite3ExprAnalyzeAggregates(&nc, NULL);80 81  /* Expect no changes to AggInfo counts */82  TEST_ASSERT_EQUAL_INT(0, agg.nFunc);83  TEST_ASSERT_EQUAL_INT(0, agg.nColumn);84 85  sqlite3DbFree(db, nc.pSrcList);86  closeTestDb(db);87}88 89/* Test 2: count(1) is an aggregate and should be recorded in AggInfo (nFunc increments). */90static void test_sqlite3ExprAnalyzeAggregates_counts_aggfunc_count(void){91  sqlite3 *db = openTestDb();92  Parse parse;93  initParse(&parse, db);94 95  NameContext nc;96  memset(&nc, 0, sizeof(nc));97  nc.pParse = &parse;98  nc.pSrcList = makeMinimalSrcList(db);99 100  AggInfo agg;101  memset(&agg, 0, sizeof(agg));102  nc.pAggInfo = &agg;103 104  /* Build count(1) */105  Expr *lit1 = makeIntegerLiteral(db, "1");106  TEST_ASSERT_NOT_NULL(lit1);107  ExprList *args = appendExprToList(&parse, NULL, lit1);108  TEST_ASSERT_NOT_NULL(args);109  Expr *fn = makeFunctionExpr(&parse, "count", args);110  TEST_ASSERT_NOT_NULL(fn);111 112  /* Resolve names so the function is identified as aggregate */113  int rc = sqlite3ResolveExprNames(&nc, fn);114  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Name resolution failed for count(1)");115 116  /* Analyze aggregates */117  sqlite3ExprAnalyzeAggregates(&nc, fn);118 119  /* Verify that one aggregate function is recorded */120  TEST_ASSERT_EQUAL_INT(1, agg.nFunc);121 122  /* Cleanup */123  sqlite3ExprDelete(db, fn);124  sqlite3DbFree(db, nc.pSrcList);125  closeTestDb(db);126}127 128/* Test 3: Non-aggregate function abs(1) should not be recorded in AggInfo (nFunc remains 0). */129static void test_sqlite3ExprAnalyzeAggregates_nonaggfunc_noop(void){130  sqlite3 *db = openTestDb();131  Parse parse;132  initParse(&parse, db);133 134  NameContext nc;135  memset(&nc, 0, sizeof(nc));136  nc.pParse = &parse;137  nc.pSrcList = makeMinimalSrcList(db);138 139  AggInfo agg;140  memset(&agg, 0, sizeof(agg));141  nc.pAggInfo = &agg;142 143  /* Build abs(1) which is not an aggregate */144  Expr *lit1 = makeIntegerLiteral(db, "1");145  TEST_ASSERT_NOT_NULL(lit1);146  ExprList *args = appendExprToList(&parse, NULL, lit1);147  TEST_ASSERT_NOT_NULL(args);148  Expr *fn = makeFunctionExpr(&parse, "abs", args);149  TEST_ASSERT_NOT_NULL(fn);150 151  int rc = sqlite3ResolveExprNames(&nc, fn);152  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Name resolution failed for abs(1)");153 154  sqlite3ExprAnalyzeAggregates(&nc, fn);155 156  /* No aggregate functions should have been recorded */157  TEST_ASSERT_EQUAL_INT(0, agg.nFunc);158  TEST_ASSERT_EQUAL_INT(0, agg.nColumn);159 160  sqlite3ExprDelete(db, fn);161  sqlite3DbFree(db, nc.pSrcList);162  closeTestDb(db);163}164 165/* Test 4: Nested aggregate inside non-aggregate: abs(count(1)) should still record one aggregate. */166static void test_sqlite3ExprAnalyzeAggregates_nested_agg_inside_nonagg(void){167  sqlite3 *db = openTestDb();168  Parse parse;169  initParse(&parse, db);170 171  NameContext nc;172  memset(&nc, 0, sizeof(nc));173  nc.pParse = &parse;174  nc.pSrcList = makeMinimalSrcList(db);175 176  AggInfo agg;177  memset(&agg, 0, sizeof(agg));178  nc.pAggInfo = &agg;179 180  /* Build inner: count(1) */181  Expr *lit1 = makeIntegerLiteral(db, "1");182  TEST_ASSERT_NOT_NULL(lit1);183  ExprList *countArgs = appendExprToList(&parse, NULL, lit1);184  TEST_ASSERT_NOT_NULL(countArgs);185  Expr *countFn = makeFunctionExpr(&parse, "count", countArgs);186  TEST_ASSERT_NOT_NULL(countFn);187 188  /* Wrap with abs(...) */189  ExprList *outerArgs = appendExprToList(&parse, NULL, countFn);190  TEST_ASSERT_NOT_NULL(outerArgs);191  Expr *absFn = makeFunctionExpr(&parse, "abs", outerArgs);192  TEST_ASSERT_NOT_NULL(absFn);193 194  int rc = sqlite3ResolveExprNames(&nc, absFn);195  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "Name resolution failed for abs(count(1))");196 197  sqlite3ExprAnalyzeAggregates(&nc, absFn);198 199  /* Expect exactly one aggregate function recorded */200  TEST_ASSERT_EQUAL_INT(1, agg.nFunc);201 202  sqlite3ExprDelete(db, absFn);203  sqlite3DbFree(db, nc.pSrcList);204  closeTestDb(db);205}206 207int main(void) {208  UNITY_BEGIN();209  RUN_TEST(test_sqlite3ExprAnalyzeAggregates_null_expr_noop);210  RUN_TEST(test_sqlite3ExprAnalyzeAggregates_counts_aggfunc_count);211  RUN_TEST(test_sqlite3ExprAnalyzeAggregates_nonaggfunc_noop);212  RUN_TEST(test_sqlite3ExprAnalyzeAggregates_nested_agg_inside_nonagg);213  return UNITY_END();214}