sqlite / tests /tests_alter_renameUnmapSelectCb.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>
/* Wrapper for the static function under test (provided in the build) */
extern int test_renameUnmapSelectCb(Walker *pWalker, Select *p);
/* Global counter for expression walker callback invocations */
static int g_expr_walk_count = 0;
/* A simple walker expression callback that increments a counter */
static int testExprCallback(Walker *pWalker, Expr *pExpr){
(void)pWalker;
(void)pExpr;
g_expr_walk_count++;
return WRC_Continue;
}
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Helper: append a RenameToken node to Parse->pRename for a given pointer */
static RenameToken* addRenameToken(Parse *pParse, const void *pTarget){
RenameToken *pTok = (RenameToken*)sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
TEST_ASSERT_NOT_NULL_MESSAGE(pTok, "Failed to allocate RenameToken");
pTok->p = (void*)pTarget;
pTok->pNext = pParse->pRename;
pParse->pRename = pTok;
return pTok;
}
/* Helper: create an empty ExprList object */
static ExprList* makeEmptyExprList(sqlite3 *db){
ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList");
/* nExpr = 0; a may be NULL */
return p;
}
/* Helper: create an empty SrcList object */
static SrcList* makeEmptySrcList(sqlite3 *db){
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList");
/* nSrc = 0; a may be NULL */
return p;
}
/* Helper: allocate an ExprList with n entries */
static ExprList* makeExprListWithN(sqlite3 *db, int n){
ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList");
p->nExpr = n;
if( n>0 ){
p->a = (struct ExprList_item*)sqlite3DbMallocZero(db, sizeof(struct ExprList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate ExprList_item array");
}
return p;
}
/* Helper: allocate a SrcList with n entries */
static SrcList* makeSrcListWithN(sqlite3 *db, int n){
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList");
p->nSrc = n;
if( n>0 ){
p->a = (struct SrcList_item*)sqlite3DbMallocZero(db, sizeof(struct SrcList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate SrcList_item array");
}
return p;
}
/* Helper: create an IdList with n entries and set zName pointers from array */
static IdList* makeIdList(sqlite3 *db, int n, const char **names){
IdList *p = (IdList*)sqlite3DbMallocZero(db, sizeof(IdList));
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate IdList");
p->nId = n;
if( n>0 ){
p->a = (struct IdList_item*)sqlite3DbMallocZero(db, sizeof(struct IdList_item) * n);
TEST_ASSERT_NOT_NULL_MESSAGE(p->a, "Failed to allocate IdList_item array");
for(int i=0; i<n; i++){
p->a[i].zName = (char*)names[i];
}
}
return p;
}
/* Test 1: Returns WRC_Abort if Parse.nErr is non-zero */
void test_renameUnmapSelectCb_returns_abort_if_nErr(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sParse.nErr = 1; /* Trigger abort */
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeEmptyExprList(db);
sSel.pSrc = makeEmptySrcList(db);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Abort, rc);
sqlite3_close(db);
}
/* Test 2: Returns WRC_Prune when SF_View set and does not unmap tokens */
void test_renameUnmapSelectCb_prunes_on_view_and_preserves_tokens(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.selFlags = SF_View; /* Trigger prune path */
sSel.pEList = makeExprListWithN(db, 1);
sSel.pSrc = makeSrcListWithN(db, 1);
/* Prepare alias and table names with RenameTokens */
const char *alias = "aliasA";
const char *tname = "tabA";
sSel.pEList->a[0].zEName = (char*)alias;
sSel.pEList->a[0].fg.eEName = ENAME_NAME;
sSel.pSrc->a[0].zName = (char*)tname;
RenameToken *pTokAlias = addRenameToken(&sParse, alias);
RenameToken *pTokTab = addRenameToken(&sParse, tname);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Prune, rc);
/* Ensure tokens are unchanged (not unmapped) due to prune */
TEST_ASSERT_EQUAL_PTR(alias, pTokAlias->p);
TEST_ASSERT_EQUAL_PTR(tname, pTokTab->p);
sqlite3_close(db);
}
/* Test 3: Unmaps only ENAME_NAME aliases in ExprList */
void test_renameUnmapSelectCb_unmaps_only_ENAME_NAME_aliases(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeExprListWithN(db, 2);
sSel.pSrc = makeEmptySrcList(db); /* empty but non-NULL */
const char *alias1 = "alias1";
const char *alias2 = "alias2";
sSel.pEList->a[0].zEName = (char*)alias1;
sSel.pEList->a[0].fg.eEName = ENAME_NAME; /* should be unmapped */
sSel.pEList->a[1].zEName = (char*)alias2;
sSel.pEList->a[1].fg.eEName = ENAME_NAME + 1; /* different value => unchanged */
RenameToken *pTok1 = addRenameToken(&sParse, alias1);
RenameToken *pTok2 = addRenameToken(&sParse, alias2);
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);
TEST_ASSERT_EQUAL_PTR(NULL, pTok1->p); /* unmapped */
TEST_ASSERT_EQUAL_PTR(alias2, pTok2->p); /* unchanged */
sqlite3_close(db);
}
/* Test 4: Unmaps SrcList names, walks ON expr for isUsing==0, and unmaps USING(IdList) names for isUsing==1 */
void test_renameUnmapSelectCb_unmaps_srclist_and_walks_on_or_using(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
Parse sParse;
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
Walker w;
memset(&w, 0, sizeof(w));
w.pParse = &sParse;
w.xExprCallback = testExprCallback;
Select sSel;
memset(&sSel, 0, sizeof(sSel));
sSel.pEList = makeEmptyExprList(db);
sSel.pSrc = makeSrcListWithN(db, 2);
/* First source: isUsing==0 with ON expression */
const char *tA = "tA";
sSel.pSrc->a[0].zName = (char*)tA;
sSel.pSrc->a[0].fg.isUsing = 0;
Expr onExpr;
memset(&onExpr, 0, sizeof(onExpr));
onExpr.op = TK_NULL; /* simple expression */
sSel.pSrc->a[0].u3.pOn = &onExpr;
/* Second source: isUsing==1 with USING(IdList) */
const char *tB = "tB";
sSel.pSrc->a[1].zName = (char*)tB;
sSel.pSrc->a[1].fg.isUsing = 1;
const char *usingNames[] = { "u1", "u2" };
sSel.pSrc->a[1].u3.pUsing = makeIdList(db, 2, usingNames);
RenameToken *pTok_tA = addRenameToken(&sParse, tA);
RenameToken *pTok_tB = addRenameToken(&sParse, tB);
RenameToken *pTok_u1 = addRenameToken(&sParse, usingNames[0]);
RenameToken *pTok_u2 = addRenameToken(&sParse, usingNames[1]);
g_expr_walk_count = 0;
int rc = test_renameUnmapSelectCb(&w, &sSel);
TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);
/* Table names unmapped */
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tA->p);
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tB->p);
/* USING IdList names unmapped */
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u1->p);
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u2->p);
/* ON expression walker executed at least once */
TEST_ASSERT_TRUE(g_expr_walk_count >= 1);
sqlite3_close(db);
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameUnmapSelectCb_returns_abort_if_nErr);
RUN_TEST(test_renameUnmapSelectCb_prunes_on_view_and_preserves_tokens);
RUN_TEST(test_renameUnmapSelectCb_unmaps_only_ENAME_NAME_aliases);
RUN_TEST(test_renameUnmapSelectCb_unmaps_srclist_and_walks_on_or_using);
return UNITY_END();
}