AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Wrapper for the static function under test (provided by the build) */6int test_fixSelectCb(Walker *p, Select *pSelect);7 8static SrcList* allocSrcList(sqlite3 *db, int n){9 SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList) + sizeof(SrcItem)*(n-1));10 if( p ){11 p->nSrc = n;12 }13 return p;14}15 16void setUp(void) {17 /* Setup code here, or leave empty */18}19 20void tearDown(void) {21 /* Cleanup code here, or leave empty */22}23 24/* Helper to initialize a DbFixer for a given database name index (iDb) */25static void initFixerForDb(sqlite3 *db, Parse *pParse, DbFixer *pFix, int iDb, const char *zType, const char *zObjName){26 Token t;27 t.z = zObjName;28 t.n = (int)strlen(zObjName);29 sqlite3FixInit(pFix, pParse, iDb, zType, &t);30}31 32/* Test: When no explicit zDatabase is present, fixSelectCb should set pSchema and flags. */33void test_fixSelectCb_assigns_schema_and_flags_when_no_dbname(void) {34 sqlite3 *db = 0;35 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));36 Parse parse;37 memset(&parse, 0, sizeof(parse));38 parse.db = db;39 40 DbFixer fixer;41 initFixerForDb(db, &parse, &fixer, 0, "view", "obj"); /* iDb=0 => main */42 43 Select s;44 memset(&s, 0, sizeof(s));45 s.pSrc = allocSrcList(db, 1);46 TEST_ASSERT_NOT_NULL(s.pSrc);47 48 SrcItem *pItem = &s.pSrc->a[0];49 memset(pItem, 0, sizeof(*pItem));50 pItem->fg.isSubquery = 0; /* Not a subquery */51 pItem->fg.fixedSchema = 0; /* Not fixed yet */52 pItem->u4.zDatabase = 0; /* No explicit db qualifier */53 pItem->fg.isUsing = 0; /* Ensure ON-clause check is considered (none set => ok) */54 pItem->u3.pOn = 0;55 56 int rc = test_fixSelectCb(&fixer.w, &s);57 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);58 59 TEST_ASSERT_EQUAL_INT(1, pItem->fg.fixedSchema);60 TEST_ASSERT_EQUAL_INT(1, pItem->fg.fromDDL);61 TEST_ASSERT_NOT_NULL(pItem->u4.pSchema);62 TEST_ASSERT_EQUAL_PTR(db->aDb[0].pSchema, pItem->u4.pSchema);63 TEST_ASSERT_EQUAL_INT(0, pItem->fg.hadSchema);64 TEST_ASSERT_EQUAL_INT(0, pItem->fg.notCte);65 66 sqlite3_close(db);67}68 69/* Test: With explicit matching zDatabase ("main"), it should accept, free zDatabase,70 set notCte/hadSchema, and set pSchema and flags. */71void test_fixSelectCb_handles_matching_dbname(void) {72 sqlite3 *db = 0;73 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));74 Parse parse;75 memset(&parse, 0, sizeof(parse));76 parse.db = db;77 78 DbFixer fixer;79 initFixerForDb(db, &parse, &fixer, 0, "view", "obj"); /* main */80 81 Select s;82 memset(&s, 0, sizeof(s));83 s.pSrc = allocSrcList(db, 1);84 TEST_ASSERT_NOT_NULL(s.pSrc);85 86 SrcItem *pItem = &s.pSrc->a[0];87 memset(pItem, 0, sizeof(*pItem));88 pItem->fg.isSubquery = 0;89 pItem->fg.fixedSchema = 0;90 pItem->u4.zDatabase = sqlite3DbStrDup(db, "main");91 TEST_ASSERT_NOT_NULL(pItem->u4.zDatabase);92 pItem->fg.isUsing = 0;93 pItem->u3.pOn = 0;94 95 int rc = test_fixSelectCb(&fixer.w, &s);96 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);97 98 TEST_ASSERT_EQUAL_INT(1, pItem->fg.fixedSchema);99 TEST_ASSERT_EQUAL_INT(1, pItem->fg.fromDDL);100 TEST_ASSERT_EQUAL_INT(1, pItem->fg.hadSchema);101 TEST_ASSERT_EQUAL_INT(1, pItem->fg.notCte);102 TEST_ASSERT_NOT_NULL(pItem->u4.pSchema);103 TEST_ASSERT_EQUAL_PTR(db->aDb[0].pSchema, pItem->u4.pSchema);104 105 sqlite3_close(db);106}107 108/* Test: With mismatched zDatabase ("temp" while fixing for "main"), it should abort and not modify flags. */109void test_fixSelectCb_aborts_on_mismatched_dbname(void) {110 sqlite3 *db = 0;111 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));112 Parse parse;113 memset(&parse, 0, sizeof(parse));114 parse.db = db;115 116 DbFixer fixer;117 initFixerForDb(db, &parse, &fixer, 0, "view", "obj"); /* fixing for main */118 119 Select s;120 memset(&s, 0, sizeof(s));121 s.pSrc = allocSrcList(db, 1);122 TEST_ASSERT_NOT_NULL(s.pSrc);123 124 SrcItem *pItem = &s.pSrc->a[0];125 memset(pItem, 0, sizeof(*pItem));126 pItem->fg.isSubquery = 0;127 pItem->fg.fixedSchema = 0;128 pItem->u4.zDatabase = sqlite3DbStrDup(db, "temp");129 TEST_ASSERT_NOT_NULL(pItem->u4.zDatabase);130 pItem->fg.isUsing = 0;131 pItem->u3.pOn = 0;132 133 int rc = test_fixSelectCb(&fixer.w, &s);134 TEST_ASSERT_EQUAL_INT(WRC_Abort, rc);135 136 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fixedSchema);137 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fromDDL);138 139 sqlite3_close(db);140}141 142/* Test: When pFix->bTemp==1 (iDb==1 => TEMP), no changes should be applied to pSchema/flags. */143void test_fixSelectCb_no_change_for_temp_schema(void) {144 sqlite3 *db = 0;145 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));146 Parse parse;147 memset(&parse, 0, sizeof(parse));148 parse.db = db;149 150 DbFixer fixer;151 initFixerForDb(db, &parse, &fixer, 1, "view", "obj"); /* iDb=1 => TEMP, bTemp==1 */152 153 Select s;154 memset(&s, 0, sizeof(s));155 s.pSrc = allocSrcList(db, 1);156 TEST_ASSERT_NOT_NULL(s.pSrc);157 158 SrcItem *pItem = &s.pSrc->a[0];159 memset(pItem, 0, sizeof(*pItem));160 pItem->fg.isSubquery = 0;161 pItem->fg.fixedSchema = 0;162 pItem->u4.zDatabase = 0;163 pItem->fg.isUsing = 0;164 pItem->u3.pOn = 0;165 166 int rc = test_fixSelectCb(&fixer.w, &s);167 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);168 169 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fixedSchema);170 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fromDDL);171 TEST_ASSERT_EQUAL_PTR(0, pItem->u4.pSchema);172 173 sqlite3_close(db);174}175 176/* Test: When the SrcItem is a subquery, no changes should be applied to pSchema/flags. */177void test_fixSelectCb_no_change_for_subquery_item(void) {178 sqlite3 *db = 0;179 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));180 Parse parse;181 memset(&parse, 0, sizeof(parse));182 parse.db = db;183 184 DbFixer fixer;185 initFixerForDb(db, &parse, &fixer, 0, "view", "obj"); /* main */186 187 Select s;188 memset(&s, 0, sizeof(s));189 s.pSrc = allocSrcList(db, 1);190 TEST_ASSERT_NOT_NULL(s.pSrc);191 192 SrcItem *pItem = &s.pSrc->a[0];193 memset(pItem, 0, sizeof(*pItem));194 pItem->fg.isSubquery = 1; /* subquery => skip assignments */195 pItem->fg.fixedSchema = 0;196 pItem->u4.zDatabase = 0;197 pItem->fg.isUsing = 0;198 pItem->u3.pOn = 0;199 200 int rc = test_fixSelectCb(&fixer.w, &s);201 TEST_ASSERT_EQUAL_INT(WRC_Continue, rc);202 203 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fixedSchema);204 TEST_ASSERT_EQUAL_INT(0, pItem->fg.fromDDL);205 TEST_ASSERT_EQUAL_PTR(0, pItem->u4.pSchema);206 207 sqlite3_close(db);208}209 210/* Test: Aborts due to ON-clause containing a TK_VARIABLE expression (only if ON-clause walk is compiled in). */211#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)212void test_fixSelectCb_aborts_on_onclause_variable(void) {213 sqlite3 *db = 0;214 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));215 Parse parse;216 memset(&parse, 0, sizeof(parse));217 parse.db = db;218 219 /* Ensure we are not in initialization, so TK_VARIABLE causes error in fixExprCb */220 db->init.busy = 0;221 222 DbFixer fixer;223 initFixerForDb(db, &parse, &fixer, 1, "view", "obj"); /* TEMP to avoid earlier schema modifications */224 225 Select s;226 memset(&s, 0, sizeof(s));227 s.pSrc = allocSrcList(db, 1);228 TEST_ASSERT_NOT_NULL(s.pSrc);229 230 SrcItem *pItem = &s.pSrc->a[0];231 memset(pItem, 0, sizeof(*pItem));232 pItem->fg.isSubquery = 0;233 pItem->fg.fixedSchema = 0;234 pItem->u4.zDatabase = 0;235 pItem->fg.isUsing = 0;236 237 /* Create an ON clause expression that is a TK_VARIABLE to trigger abort in fixExprCb */238 Expr *pVar = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));239 TEST_ASSERT_NOT_NULL(pVar);240 pVar->op = TK_VARIABLE;241 pItem->u3.pOn = pVar;242 243 int rc = test_fixSelectCb(&fixer.w, &s);244 TEST_ASSERT_EQUAL_INT(WRC_Abort, rc);245 246 sqlite3_close(db);247}248#endif249 250int main(void) {251 UNITY_BEGIN();252 RUN_TEST(test_fixSelectCb_assigns_schema_and_flags_when_no_dbname);253 RUN_TEST(test_fixSelectCb_handles_matching_dbname);254 RUN_TEST(test_fixSelectCb_aborts_on_mismatched_dbname);255 RUN_TEST(test_fixSelectCb_no_change_for_temp_schema);256 RUN_TEST(test_fixSelectCb_no_change_for_subquery_item);257#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)258 RUN_TEST(test_fixSelectCb_aborts_on_onclause_variable);259#endif260 return UNITY_END();261}