AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6static sqlite3 *gDb = NULL;7 8/* Helpers */9static void initParse(Parse *pParse, sqlite3 *db){10 memset(pParse, 0, sizeof(*pParse));11 pParse->db = db;12}13 14static Token makeToken(const char *z){15 Token t;16 t.z = z;17 t.n = (int)strlen(z);18 return t;19}20 21static Expr* makeIdExpr(sqlite3 *db, const char *zId){22 Token t = makeToken(zId);23 return sqlite3ExprAlloc(db, TK_ID, &t, 0);24}25 26static Expr* makeIntExpr(sqlite3 *db, const char *zNum){27 Token t = makeToken(zNum);28 return sqlite3ExprAlloc(db, TK_INTEGER, &t, 0);29}30 31void setUp(void) {32 int rc = sqlite3_open(":memory:", &gDb);33 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);34 /* Create a main-schema table and a temp table for tests */35 rc = sqlite3_exec(gDb,36 "CREATE TABLE t1(a, b);"37 "CREATE TEMP TABLE tt(x);",38 0, 0, 039 );40 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);41}42 43void tearDown(void) {44 if( gDb ){45 sqlite3_close(gDb);46 gDb = NULL;47 }48}49 50/* Test: NULL expression and list -> SQLITE_OK */51void test_sqlite3ResolveSelfReference_NullExprAndList_ReturnsOK(void){52 Parse sParse;53 initParse(&sParse, gDb);54 55 int rc = sqlite3ResolveSelfReference(&sParse, NULL, 0, NULL, NULL);56 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);57 TEST_ASSERT_EQUAL_INT(0, sParse.nErr);58}59 60/* Test: Resolve a simple column in a CHECK-like context */61void test_sqlite3ResolveSelfReference_ResolveColumnInCheckContext(void){62 Parse sParse;63 initParse(&sParse, gDb);64 65 Table *pTab = sqlite3FindTable(gDb, "t1", "main");66 TEST_ASSERT_NOT_NULL(pTab);67 68 /* Build expression referencing column "a" */69 Expr *pExpr = makeIdExpr(gDb, "a");70 TEST_ASSERT_NOT_NULL(pExpr);71 72 int rc = sqlite3ResolveSelfReference(&sParse, pTab, NC_IsCheck, pExpr, NULL);73 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);74 TEST_ASSERT_EQUAL_INT(0, sParse.nErr);75 76 /* After resolution:77 - pExpr->op == TK_COLUMN78 - pExpr->iTable == -1 (special for self-reference contexts)79 - pExpr->iColumn == 0 (column "a")80 - pExpr->pTab == pTab81 */82 TEST_ASSERT_EQUAL_INT(TK_COLUMN, pExpr->op);83 TEST_ASSERT_EQUAL_INT(-1, pExpr->iTable);84 TEST_ASSERT_EQUAL_INT(0, pExpr->iColumn);85 TEST_ASSERT_EQUAL_PTR(pTab, pExpr->pTab);86 87 sqlite3ExprDelete(gDb, pExpr);88}89 90/* Test: No table context (type==0), column reference should be an error */91void test_sqlite3ResolveSelfReference_NoTable_ColumnRefCausesError(void){92 Parse sParse;93 initParse(&sParse, gDb);94 95 /* Column reference "a" with no table in NameContext and type==0 */96 Expr *pExpr = makeIdExpr(gDb, "a");97 TEST_ASSERT_NOT_NULL(pExpr);98 99 int rc = sqlite3ResolveSelfReference(&sParse, NULL, 0, pExpr, NULL);100 TEST_ASSERT_NOT_EQUAL(SQLITE_OK, rc);101 TEST_ASSERT_TRUE(sParse.nErr > 0);102 103 sqlite3ExprDelete(gDb, pExpr);104}105 106/* Test: EP_FromDDL is set on TK_FUNCTION nodes for non-temp schema */107void test_sqlite3ResolveSelfReference_FromDDL_FunctionExpr_MainSchema(void){108 Parse sParse;109 initParse(&sParse, gDb);110 111 Table *pTab = sqlite3FindTable(gDb, "t1", "main");112 TEST_ASSERT_NOT_NULL(pTab);113 114 /* Build function expression: abs(1) */115 ExprList *pArgs = NULL;116 pArgs = sqlite3ExprListAppend(&sParse, pArgs, makeIntExpr(gDb, "1"));117 TEST_ASSERT_NOT_NULL(pArgs);118 119 Token tFunc = makeToken("abs");120 Expr *pFunc = sqlite3ExprFunction(gDb, pArgs, &tFunc);121 TEST_ASSERT_NOT_NULL(pFunc);122 123 int rc = sqlite3ResolveSelfReference(&sParse, pTab, NC_IsCheck, pFunc, NULL);124 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);125 TEST_ASSERT_EQUAL_INT(0, sParse.nErr);126 127 /* EP_FromDDL should be set because pTab is in main (non-temp) schema */128 TEST_ASSERT_TRUE( ExprHasProperty(pFunc, EP_FromDDL) );129 130 sqlite3ExprDelete(gDb, pFunc); /* This also deletes pArgs */131}132 133/* Test: EP_FromDDL is NOT set on TK_FUNCTION nodes for temp schema */134void test_sqlite3ResolveSelfReference_FromDDL_FunctionExpr_TempSchema(void){135 Parse sParse;136 initParse(&sParse, gDb);137 138 Table *pTempTab = sqlite3FindTable(gDb, "tt", "temp");139 TEST_ASSERT_NOT_NULL(pTempTab);140 141 /* Build function expression: abs(1) */142 ExprList *pArgs = NULL;143 pArgs = sqlite3ExprListAppend(&sParse, pArgs, makeIntExpr(gDb, "1"));144 TEST_ASSERT_NOT_NULL(pArgs);145 146 Token tFunc = makeToken("abs");147 Expr *pFunc = sqlite3ExprFunction(gDb, pArgs, &tFunc);148 TEST_ASSERT_NOT_NULL(pFunc);149 150 int rc = sqlite3ResolveSelfReference(&sParse, pTempTab, NC_IsCheck, pFunc, NULL);151 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);152 TEST_ASSERT_EQUAL_INT(0, sParse.nErr);153 154 /* EP_FromDDL should NOT be set because pTab is in TEMP schema */155 TEST_ASSERT_FALSE( ExprHasProperty(pFunc, EP_FromDDL) );156 157 sqlite3ExprDelete(gDb, pFunc); /* This also deletes pArgs */158}159 160/* Test: Resolve an ExprList of multiple columns in a CHECK-like context */161void test_sqlite3ResolveSelfReference_ResolveExprList_MultipleColumns(void){162 Parse sParse;163 initParse(&sParse, gDb);164 165 Table *pTab = sqlite3FindTable(gDb, "t1", "main");166 TEST_ASSERT_NOT_NULL(pTab);167 168 ExprList *pList = NULL;169 pList = sqlite3ExprListAppend(&sParse, pList, makeIdExpr(gDb, "a"));170 TEST_ASSERT_NOT_NULL(pList);171 pList = sqlite3ExprListAppend(&sParse, pList, makeIdExpr(gDb, "b"));172 TEST_ASSERT_NOT_NULL(pList);173 174 int rc = sqlite3ResolveSelfReference(&sParse, pTab, NC_IsCheck, NULL, pList);175 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);176 TEST_ASSERT_EQUAL_INT(0, sParse.nErr);177 178 /* Verify both list expressions resolved to TK_COLUMN with iTable -1 */179 TEST_ASSERT_EQUAL_INT(2, pList->nExpr);180 TEST_ASSERT_EQUAL_INT(TK_COLUMN, pList->a[0].pExpr->op);181 TEST_ASSERT_EQUAL_INT(-1, pList->a[0].pExpr->iTable);182 TEST_ASSERT_EQUAL_INT(0, pList->a[0].pExpr->iColumn); /* "a" -> 0 */183 184 TEST_ASSERT_EQUAL_INT(TK_COLUMN, pList->a[1].pExpr->op);185 TEST_ASSERT_EQUAL_INT(-1, pList->a[1].pExpr->iTable);186 TEST_ASSERT_EQUAL_INT(1, pList->a[1].pExpr->iColumn); /* "b" -> 1 */187 188 sqlite3ExprListDelete(gDb, pList);189}190 191int main(void) {192 UNITY_BEGIN();193 194 RUN_TEST(test_sqlite3ResolveSelfReference_NullExprAndList_ReturnsOK);195 RUN_TEST(test_sqlite3ResolveSelfReference_ResolveColumnInCheckContext);196 RUN_TEST(test_sqlite3ResolveSelfReference_NoTable_ColumnRefCausesError);197 RUN_TEST(test_sqlite3ResolveSelfReference_FromDDL_FunctionExpr_MainSchema);198 RUN_TEST(test_sqlite3ResolveSelfReference_FromDDL_FunctionExpr_TempSchema);199 RUN_TEST(test_sqlite3ResolveSelfReference_ResolveExprList_MultipleColumns);200 201 return UNITY_END();202}