File size: 4,459 Bytes
7510827 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
#include "sqliteInt.h"
#include "unity.h"
#include <stdlib.h>
#include <string.h>
extern void test_renameWalkWith(Walker *pWalker, Select *pSelect);
static sqlite3 *gDb = NULL;
/* Unity setup/teardown */
void setUp(void) {
int rc = sqlite3_open(":memory:", &gDb);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(gDb);
}
void tearDown(void) {
if (gDb) {
sqlite3_close(gDb);
gDb = NULL;
}
}
/* Helper: allocate a minimal Select with given selFlags */
static Select *allocSelect(u32 selFlags){
Select *p = (Select*)sqlite3DbMallocZero(gDb, sizeof(Select));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "allocSelect failed");
p->selFlags = selFlags;
return p;
}
/* Helper: allocate a With object with nCte entries and the provided Selects */
static With *allocWith(int nCte, Select **apSel){
/* With uses a flexible array member a[1] */
int nByte = (int)(sizeof(With) + (nCte-1) * sizeof(p->a[0]));
With *p = (With*)sqlite3DbMallocZero(gDb, nByte);
TEST_ASSERT_NOT_NULL_MESSAGE(p, "allocWith failed");
p->nCte = nCte;
p->pOuter = 0;
for(int i=0; i<nCte; i++){
p->a[i].pSelect = apSel ? apSel[i] : 0;
p->a[i].pCols = 0; /* keep NULL to avoid rename mapping side-effects */
p->a[i].zName = 0; /* not needed for these tests */
p->a[i].zCteErr = 0;
}
return p;
}
/* Walker select callback that increments a counter in walker.u.p */
static int countSelectCb(Walker *pWalker, Select *pSel){
(void)pSel;
int *pCnt = (int*)pWalker->u.p;
if( pCnt ) (*pCnt)++;
return WRC_Continue;
}
/* Test 1: When pSelect->pWith is NULL, nothing happens */
void test_renameWalkWith_no_with_clause(void){
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = gDb;
/* Create a dummy outer WITH to ensure pParse->pWith is not touched */
With *pOuter = allocWith(1, NULL);
sParse.pWith = pOuter;
/* Minimal top-level SELECT with no WITH clause */
Select *pTop = allocSelect(SF_Expanded); /* flags irrelevant here */
pTop->pWith = NULL;
int count = 0;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xSelectCallback = countSelectCb;
w.u.p = &count;
test_renameWalkWith(&w, pTop);
TEST_ASSERT_EQUAL_INT(0, count); /* no CTEs walked */
TEST_ASSERT_EQUAL_PTR(pOuter, sParse.pWith); /* unchanged */
}
/* Test 2: WITH present with SF_Expanded set: walks each CTE; no stack push/pop */
void test_renameWalkWith_expanded_with_multiple_ctes(void){
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = gDb;
With *pOuter = allocWith(1, NULL);
sParse.pWith = pOuter;
/* Create two simple CTE selects with SF_Expanded set */
Select *pCTE1 = allocSelect(SF_Expanded);
Select *pCTE2 = allocSelect(SF_Expanded);
Select *apCTE[2] = { pCTE1, pCTE2 };
With *pWith = allocWith(2, apCTE);
/* Top-level select that carries the WITH clause */
Select *pTop = allocSelect(0);
pTop->pWith = pWith;
int count = 0;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xSelectCallback = countSelectCb;
w.u.p = &count;
test_renameWalkWith(&w, pTop);
TEST_ASSERT_EQUAL_INT(2, count); /* walked both CTEs */
TEST_ASSERT_EQUAL_PTR(pOuter, sParse.pWith); /* no push/pop -> unchanged */
}
/* Test 3: WITH present with SF_Expanded not set: pushes/pops with-stack and walks each CTE */
void test_renameWalkWith_push_and_pop_with_stack(void){
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = gDb;
With *pOuter = allocWith(1, NULL);
sParse.pWith = pOuter;
/* Create three simple CTE selects with SF_Expanded unset to force push/dup */
Select *pCTE1 = allocSelect(0);
Select *pCTE2 = allocSelect(0);
Select *pCTE3 = allocSelect(0);
Select *apCTE[3] = { pCTE1, pCTE2, pCTE3 };
With *pWith = allocWith(3, apCTE);
/* Top-level select that carries the WITH clause */
Select *pTop = allocSelect(0);
pTop->pWith = pWith;
int count = 0;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xSelectCallback = countSelectCb;
w.u.p = &count;
test_renameWalkWith(&w, pTop);
TEST_ASSERT_EQUAL_INT(3, count); /* walked all CTEs */
TEST_ASSERT_EQUAL_PTR(pOuter, sParse.pWith); /* stack restored after pop */
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameWalkWith_no_with_clause);
RUN_TEST(test_renameWalkWith_expanded_with_multiple_ctes);
RUN_TEST(test_renameWalkWith_push_and_pop_with_stack);
return UNITY_END();
} |