AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Helpers */6static void initParseWithDb(sqlite3 **pDb, Parse *pParse){7 int rc = sqlite3_open(":memory:", pDb);8 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);9 memset(pParse, 0, sizeof(Parse));10 pParse->db = *pDb;11}12 13static SrcList* makeSrcList(Parse *pParse, int cursor){14 SrcList *p = (SrcList*)sqlite3DbMallocZero(pParse->db, sizeof(SrcList));15 TEST_ASSERT_NOT_NULL(p);16 p->nSrc = 1;17 p->a = (SrcItem*)sqlite3DbMallocZero(pParse->db, sizeof(SrcItem)*1);18 TEST_ASSERT_NOT_NULL(p->a);19 p->a[0].iCursor = cursor;20 return p;21}22 23static void freeSrcList(Parse *pParse, SrcList *p){24 if( !p ) return;25 sqlite3DbFree(pParse->db, p->a);26 sqlite3DbFree(pParse->db, p);27}28 29static void initAggInfo(AggInfo *p){30 memset(p, 0, sizeof(AggInfo));31 p->iFirstReg = 0;32}33 34/* Unity fixtures */35void setUp(void) { }36void tearDown(void) { }37 38/* Tests */39 40void test_analyzeAggregate_column_in_from_adds_agg_column(void){41 sqlite3 *db = 0;42 Parse parse;43 initParseWithDb(&db, &parse);44 45 /* Setup AggInfo */46 AggInfo agg;47 initAggInfo(&agg);48 49 /* Setup SrcList with cursor 1 */50 SrcList *pSrc = makeSrcList(&parse, 1);51 52 /* Setup NameContext and Walker */53 NameContext nc;54 memset(&nc, 0, sizeof(nc));55 nc.pParse = &parse;56 nc.pSrcList = pSrc;57 nc.uNC.pAggInfo = &agg;58 nc.ncFlags = NC_UAggInfo; /* required by analyzeAggregate() assertions */59 60 Walker w;61 memset(&w, 0, sizeof(w));62 w.u.pNC = &nc;63 64 /* Create a column Expr bound to cursor 1, column 2 */65 Table t; memset(&t, 0, sizeof(t));66 Expr e; memset(&e, 0, sizeof(e));67 e.op = TK_COLUMN;68 e.iTable = 1;69 e.iColumn = 2;70 e.y.pTab = &t; /* used by findOrCreateAggInfoColumn */71 72 int rc = test_analyzeAggregate(&w, &e);73 74 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);75 TEST_ASSERT_EQUAL_INT(TK_AGG_COLUMN, e.op);76 TEST_ASSERT_EQUAL_PTR(&agg, e.pAggInfo);77 TEST_ASSERT_EQUAL_INT(0, e.iAgg);78 TEST_ASSERT_EQUAL_INT(1, agg.nColumn);79 TEST_ASSERT_NOT_NULL(agg.aCol);80 TEST_ASSERT_EQUAL_INT(1, agg.aCol[0].iTable);81 TEST_ASSERT_EQUAL_INT(2, agg.aCol[0].iColumn);82 TEST_ASSERT_EQUAL_PTR(&e, agg.aCol[0].pCExpr);83 TEST_ASSERT_EQUAL_INT(0, agg.aCol[0].iSorterColumn);84 TEST_ASSERT_EQUAL_INT(1, agg.nSortingColumn);85 86 /* Cleanup */87 sqlite3DbFree(db, agg.aCol);88 freeSrcList(&parse, pSrc);89 sqlite3_close(db);90}91 92void test_analyzeAggregate_column_not_in_from_no_change(void){93 sqlite3 *db = 0;94 Parse parse;95 initParseWithDb(&db, &parse);96 97 AggInfo agg;98 initAggInfo(&agg);99 100 /* SrcList with cursor 2; Expr uses cursor 1 -> no match */101 SrcList *pSrc = makeSrcList(&parse, 2);102 103 NameContext nc;104 memset(&nc, 0, sizeof(nc));105 nc.pParse = &parse;106 nc.pSrcList = pSrc;107 nc.uNC.pAggInfo = &agg;108 nc.ncFlags = NC_UAggInfo;109 110 Walker w;111 memset(&w, 0, sizeof(w));112 w.u.pNC = &nc;113 114 Table t; memset(&t, 0, sizeof(t));115 Expr e; memset(&e, 0, sizeof(e));116 e.op = TK_COLUMN;117 e.iTable = 1;118 e.iColumn = 3;119 e.y.pTab = &t;120 121 int rc = test_analyzeAggregate(&w, &e);122 123 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);124 TEST_ASSERT_EQUAL_INT(TK_COLUMN, e.op); /* unchanged */125 TEST_ASSERT_NULL(e.pAggInfo);126 TEST_ASSERT_EQUAL_INT(0, agg.nColumn);127 128 freeSrcList(&parse, pSrc);129 sqlite3_close(db);130}131 132void test_analyzeAggregate_default_indexedexpr_inside_agg_prunes(void){133 sqlite3 *db = 0;134 Parse parse;135 initParseWithDb(&db, &parse);136 137 AggInfo agg;138 initAggInfo(&agg);139 140 /* SrcList containing the data cursor that IndexedExpr refers to */141 int dataCur = 4;142 SrcList *pSrc = makeSrcList(&parse, dataCur);143 144 NameContext nc;145 memset(&nc, 0, sizeof(nc));146 nc.pParse = &parse;147 nc.pSrcList = pSrc;148 nc.uNC.pAggInfo = &agg;149 nc.ncFlags = NC_UAggInfo | NC_InAggFunc; /* Inside aggregate function */150 151 Walker w;152 memset(&w, 0, sizeof(w));153 w.u.pNC = &nc;154 155 /* pExpr: integer literal (default case) */156 Expr e; memset(&e, 0, sizeof(e));157 e.op = TK_INTEGER;158 e.flags = EP_IntValue;159 e.u.iValue = 42;160 161 /* Build an IndexedExpr that matches e */162 Expr eIdx; memset(&eIdx, 0, sizeof(eIdx));163 eIdx.op = TK_INTEGER;164 eIdx.flags = EP_IntValue;165 eIdx.u.iValue = 42;166 167 IndexedExpr *pIE = (IndexedExpr*)sqlite3DbMallocZero(db, sizeof(IndexedExpr));168 TEST_ASSERT_NOT_NULL(pIE);169 pIE->iDataCur = dataCur; /* matches SrcList cursor */170 pIE->iIdxCur = 9;171 pIE->iIdxCol = 7;172 pIE->pExpr = &eIdx;173 pIE->pIENext = 0;174 parse.pIdxEpr = pIE;175 176 int rc = test_analyzeAggregate(&w, &e);177 178 TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);179 TEST_ASSERT_EQUAL_PTR(&agg, e.pAggInfo);180 TEST_ASSERT_EQUAL_INT(0, e.iAgg);181 TEST_ASSERT_EQUAL_INT(1, agg.nColumn);182 TEST_ASSERT_NOT_NULL(agg.aCol);183 TEST_ASSERT_EQUAL_INT(9, agg.aCol[0].iTable); /* iIdxCur copied */184 TEST_ASSERT_EQUAL_INT(7, agg.aCol[0].iColumn); /* iIdxCol copied */185 TEST_ASSERT_EQUAL_PTR(&e, agg.aCol[0].pCExpr); /* pCExpr backref to original expr */186 187 sqlite3DbFree(db, agg.aCol);188 sqlite3DbFree(db, pIE);189 freeSrcList(&parse, pSrc);190 sqlite3_close(db);191}192 193void test_analyzeAggregate_agg_function_new_entry_prunes(void){194 sqlite3 *db = 0;195 Parse parse;196 initParseWithDb(&db, &parse);197 198 AggInfo agg;199 initAggInfo(&agg);200 201 SrcList *pSrc = makeSrcList(&parse, 1);202 203 NameContext nc;204 memset(&nc, 0, sizeof(nc));205 nc.pParse = &parse;206 nc.pSrcList = pSrc;207 nc.uNC.pAggInfo = &agg;208 nc.ncFlags = NC_UAggInfo; /* not inside aggregate function */209 210 Walker w;211 memset(&w, 0, sizeof(w));212 w.u.pNC = &nc;213 w.walkerDepth = 2;214 215 /* Build aggregate function expression: count() */216 Expr e; memset(&e, 0, sizeof(e));217 e.op = TK_AGG_FUNCTION;218 e.u.zToken = "count";219 e.op2 = 2; /* must match walkerDepth */220 221 int rc = test_analyzeAggregate(&w, &e);222 223 TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);224 TEST_ASSERT_EQUAL_PTR(&agg, e.pAggInfo);225 TEST_ASSERT_EQUAL_INT(0, e.iAgg);226 TEST_ASSERT_EQUAL_INT(1, agg.nFunc);227 TEST_ASSERT_NOT_NULL(agg.aFunc);228 TEST_ASSERT_EQUAL_PTR(&e, agg.aFunc[0].pFExpr);229 TEST_ASSERT_EQUAL_INT(-1, agg.aFunc[0].iOBTab);230 TEST_ASSERT_EQUAL_INT(-1, agg.aFunc[0].iDistinct);231 232 sqlite3DbFree(db, agg.aFunc);233 freeSrcList(&parse, pSrc);234 sqlite3_close(db);235}236 237void test_analyzeAggregate_agg_function_duplicate_reuses_entry(void){238 sqlite3 *db = 0;239 Parse parse;240 initParseWithDb(&db, &parse);241 242 AggInfo agg;243 initAggInfo(&agg);244 245 SrcList *pSrc = makeSrcList(&parse, 1);246 247 NameContext nc;248 memset(&nc, 0, sizeof(nc));249 nc.pParse = &parse;250 nc.pSrcList = pSrc;251 nc.uNC.pAggInfo = &agg;252 nc.ncFlags = NC_UAggInfo;253 254 Walker w;255 memset(&w, 0, sizeof(w));256 w.u.pNC = &nc;257 w.walkerDepth = 0;258 259 /* First aggregate function: sum(1) */260 Expr arg1; memset(&arg1, 0, sizeof(arg1));261 arg1.op = TK_INTEGER;262 arg1.flags = EP_IntValue;263 arg1.u.iValue = 1;264 265 ExprList *pList = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));266 TEST_ASSERT_NOT_NULL(pList);267 pList->nExpr = 1;268 pList->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item));269 TEST_ASSERT_NOT_NULL(pList->a);270 pList->a[0].pExpr = &arg1;271 272 Expr e1; memset(&e1, 0, sizeof(e1));273 e1.op = TK_AGG_FUNCTION;274 e1.u.zToken = "sum";275 e1.x.pList = pList;276 e1.op2 = 0;277 278 int rc1 = test_analyzeAggregate(&w, &e1);279 TEST_ASSERT_EQUAL_INT(WRC_Prune, rc1);280 TEST_ASSERT_EQUAL_INT(1, agg.nFunc);281 TEST_ASSERT_EQUAL_INT(0, e1.iAgg);282 283 /* Second aggregate function identical to the first */284 Expr arg2; memset(&arg2, 0, sizeof(arg2));285 arg2.op = TK_INTEGER;286 arg2.flags = EP_IntValue;287 arg2.u.iValue = 1;288 289 ExprList *pList2 = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));290 TEST_ASSERT_NOT_NULL(pList2);291 pList2->nExpr = 1;292 pList2->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item));293 TEST_ASSERT_NOT_NULL(pList2->a);294 pList2->a[0].pExpr = &arg2;295 296 Expr e2; memset(&e2, 0, sizeof(e2));297 e2.op = TK_AGG_FUNCTION;298 e2.u.zToken = "sum";299 e2.x.pList = pList2;300 e2.op2 = 0;301 302 int rc2 = test_analyzeAggregate(&w, &e2);303 TEST_ASSERT_EQUAL_INT(WRC_Prune, rc2);304 TEST_ASSERT_EQUAL_PTR(&agg, e2.pAggInfo);305 TEST_ASSERT_EQUAL_INT(0, e2.iAgg); /* reuse existing entry */306 TEST_ASSERT_EQUAL_INT(1, agg.nFunc); /* no new entry added */307 308 /* Cleanup allocated arrays */309 sqlite3DbFree(db, pList->a);310 sqlite3DbFree(db, pList);311 sqlite3DbFree(db, pList2->a);312 sqlite3DbFree(db, pList2);313 sqlite3DbFree(db, agg.aFunc);314 freeSrcList(&parse, pSrc);315 sqlite3_close(db);316}317 318void test_analyzeAggregate_agg_function_distinct_sets_iDistinct(void){319 sqlite3 *db = 0;320 Parse parse;321 initParseWithDb(&db, &parse);322 323 AggInfo agg;324 initAggInfo(&agg);325 326 SrcList *pSrc = makeSrcList(&parse, 3);327 328 NameContext nc;329 memset(&nc, 0, sizeof(nc));330 nc.pParse = &parse;331 nc.pSrcList = pSrc;332 nc.uNC.pAggInfo = &agg;333 nc.ncFlags = NC_UAggInfo;334 335 Walker w;336 memset(&w, 0, sizeof(w));337 w.u.pNC = &nc;338 w.walkerDepth = 5;339 340 /* sum(DISTINCT 2) */341 Expr arg; memset(&arg, 0, sizeof(arg));342 arg.op = TK_INTEGER;343 arg.flags = EP_IntValue;344 arg.u.iValue = 2;345 346 ExprList *pList = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));347 TEST_ASSERT_NOT_NULL(pList);348 pList->nExpr = 1;349 pList->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item));350 TEST_ASSERT_NOT_NULL(pList->a);351 pList->a[0].pExpr = &arg;352 353 Expr e; memset(&e, 0, sizeof(e));354 e.op = TK_AGG_FUNCTION;355 e.u.zToken = "sum";356 e.x.pList = pList;357 e.op2 = 5;358 e.flags |= EP_Distinct;359 360 int rc = test_analyzeAggregate(&w, &e);361 362 TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);363 TEST_ASSERT_EQUAL_INT(1, agg.nFunc);364 TEST_ASSERT_TRUE(agg.aFunc[0].iDistinct >= 0); /* distinct table allocated */365 TEST_ASSERT_EQUAL_INT(-1, agg.aFunc[0].iOBTab); /* no ORDER BY payload */366 367 sqlite3DbFree(db, pList->a);368 sqlite3DbFree(db, pList);369 sqlite3DbFree(db, agg.aFunc);370 freeSrcList(&parse, pSrc);371 sqlite3_close(db);372}373 374void test_analyzeAggregate_agg_function_walkerDepth_mismatch_continue(void){375 sqlite3 *db = 0;376 Parse parse;377 initParseWithDb(&db, &parse);378 379 AggInfo agg;380 initAggInfo(&agg);381 382 SrcList *pSrc = makeSrcList(&parse, 1);383 384 NameContext nc;385 memset(&nc, 0, sizeof(nc));386 nc.pParse = &parse;387 nc.pSrcList = pSrc;388 nc.uNC.pAggInfo = &agg;389 nc.ncFlags = NC_UAggInfo;390 391 Walker w;392 memset(&w, 0, sizeof(w));393 w.u.pNC = &nc;394 w.walkerDepth = 0;395 396 Expr e; memset(&e, 0, sizeof(e));397 e.op = TK_AGG_FUNCTION;398 e.u.zToken = "count";399 e.op2 = 1; /* mismatch with walkerDepth */400 401 int rc = test_analyzeAggregate(&w, &e);402 403 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);404 TEST_ASSERT_EQUAL_INT(0, agg.nFunc);405 406 freeSrcList(&parse, pSrc);407 sqlite3_close(db);408}409 410void test_analyzeAggregate_default_outside_aggfunc_continue(void){411 sqlite3 *db = 0;412 Parse parse;413 initParseWithDb(&db, &parse);414 415 AggInfo agg;416 initAggInfo(&agg);417 418 SrcList *pSrc = makeSrcList(&parse, 1);419 420 NameContext nc;421 memset(&nc, 0, sizeof(nc));422 nc.pParse = &parse;423 nc.pSrcList = pSrc;424 nc.uNC.pAggInfo = &agg;425 nc.ncFlags = NC_UAggInfo; /* not NC_InAggFunc */426 427 Walker w;428 memset(&w, 0, sizeof(w));429 w.u.pNC = &nc;430 431 Expr e; memset(&e, 0, sizeof(e));432 e.op = TK_INTEGER;433 e.flags = EP_IntValue;434 e.u.iValue = 10;435 436 int rc = test_analyzeAggregate(&w, &e);437 438 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);439 TEST_ASSERT_NULL(e.pAggInfo);440 TEST_ASSERT_EQUAL_INT(0, agg.nColumn);441 442 freeSrcList(&parse, pSrc);443 sqlite3_close(db);444}445 446int main(void){447 UNITY_BEGIN();448 RUN_TEST(test_analyzeAggregate_column_in_from_adds_agg_column);449 RUN_TEST(test_analyzeAggregate_column_not_in_from_no_change);450 RUN_TEST(test_analyzeAggregate_default_indexedexpr_inside_agg_prunes);451 RUN_TEST(test_analyzeAggregate_agg_function_new_entry_prunes);452 RUN_TEST(test_analyzeAggregate_agg_function_duplicate_reuses_entry);453 RUN_TEST(test_analyzeAggregate_agg_function_distinct_sets_iDistinct);454 RUN_TEST(test_analyzeAggregate_agg_function_walkerDepth_mismatch_continue);455 RUN_TEST(test_analyzeAggregate_default_outside_aggfunc_continue);456 return UNITY_END();457}