|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <string.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
extern int test_renameUnmapSelectCb(Walker *pWalker, Select *p); |
|
|
|
|
|
|
|
|
static int g_expr_walk_count = 0; |
|
|
|
|
|
|
|
|
static int testExprCallback(Walker *pWalker, Expr *pExpr){ |
|
|
(void)pWalker; |
|
|
(void)pExpr; |
|
|
g_expr_walk_count++; |
|
|
return WRC_Continue; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
static ExprList* makeEmptyExprList(sqlite3 *db){ |
|
|
ExprList *p = (ExprList*)sqlite3DbMallocZero(db, sizeof(ExprList)); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate ExprList"); |
|
|
|
|
|
return p; |
|
|
} |
|
|
|
|
|
|
|
|
static SrcList* makeEmptySrcList(sqlite3 *db){ |
|
|
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList)); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList"); |
|
|
|
|
|
return p; |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
sSel.pEList = makeExprListWithN(db, 1); |
|
|
sSel.pSrc = makeSrcListWithN(db, 1); |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(alias, pTokAlias->p); |
|
|
TEST_ASSERT_EQUAL_PTR(tname, pTokTab->p); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
const char *alias1 = "alias1"; |
|
|
const char *alias2 = "alias2"; |
|
|
sSel.pEList->a[0].zEName = (char*)alias1; |
|
|
sSel.pEList->a[0].fg.eEName = ENAME_NAME; |
|
|
sSel.pEList->a[1].zEName = (char*)alias2; |
|
|
sSel.pEList->a[1].fg.eEName = ENAME_NAME + 1; |
|
|
|
|
|
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); |
|
|
TEST_ASSERT_EQUAL_PTR(alias2, pTok2->p); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
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; |
|
|
sSel.pSrc->a[0].u3.pOn = &onExpr; |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tA->p); |
|
|
TEST_ASSERT_EQUAL_PTR(NULL, pTok_tB->p); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u1->p); |
|
|
TEST_ASSERT_EQUAL_PTR(NULL, pTok_u2->p); |
|
|
|
|
|
|
|
|
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(); |
|
|
} |