AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Helper: create a simple Select AST for "SELECT 1" (or other constant) */7static Select* makeSelectConst(Parse *pParse, const char *zVal){8 sqlite3 *db = pParse->db;9 Token t;10 t.z = zVal;11 t.n = (int)strlen(zVal);12 Expr *pExpr = sqlite3ExprAlloc(db, TK_INTEGER, &t, 0);13 ExprList *pList = sqlite3ExprListAppend(pParse, 0, pExpr);14 return sqlite3SelectNew(pParse, pList, 0, 0, 0, 0, 0, 0, 0, 0);15}16 17/* Helper: create ExprList for column names like (c1, c2, ...) with 1 entry */18static ExprList* makeOneColName(Parse *pParse, const char *zName){19 sqlite3 *db = pParse->db;20 Token t;21 t.z = zName;22 t.n = (int)strlen(zName);23 Expr *pId = sqlite3ExprAlloc(db, TK_ID, &t, 0);24 return sqlite3ExprListAppend(pParse, 0, pId);25}26 27/* Helper: cleanup resources created on Parse during tests */28static void cleanupParse(Parse *p){29 if( p->pVdbe ){30 sqlite3VdbeDelete(p->pVdbe);31 p->pVdbe = 0;32 }33 if( p->pNewTable ){34 sqlite3DeleteTable(p->db, p->pNewTable);35 p->pNewTable = 0;36 }37 if( p->zErrMsg ){38 sqlite3DbFree(p->db, p->zErrMsg);39 p->zErrMsg = 0;40 }41}42 43void setUp(void) {44 /* Setup code here, or leave empty */45}46 47void tearDown(void) {48 /* Cleanup code here, or leave empty */49}50 51/* Test: Basic successful CREATE VIEW */52void test_sqlite3CreateView_basic_success(void){53 sqlite3 *db = 0;54 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));55 56 Parse p; memset(&p, 0, sizeof(p));57 p.db = db;58 p.isCreate = 1; /* Required by sqlite3StartTable path */59 60 const char *zSql = "CREATE VIEW v_basic AS SELECT 1";61 Token tBegin, tName1, tName2, tLast;62 tBegin.z = zSql; tBegin.n = 6; /* "CREATE" */63 /* Unqualified name: pName1 = "v_basic", pName2 empty */64 const char *zName = strstr(zSql, "v_basic");65 TEST_ASSERT_NOT_NULL(zName);66 tName1.z = zName; tName1.n = (int)strlen("v_basic");67 tName2.z = zSql; tName2.n = 0; /* empty */68 /* Last token is the literal 1 */69 const char *zOne = strrchr(zSql, '1');70 TEST_ASSERT_NOT_NULL(zOne);71 tLast.z = zOne; tLast.n = 1;72 p.sLastToken = tLast;73 74 ExprList *pCNames = makeOneColName(&p, "c1");75 Select *pSel = makeSelectConst(&p, "1");76 77 sqlite3CreateView(&p, &tBegin, &tName1, &tName2, pCNames, pSel, 0, 0);78 79 TEST_ASSERT_EQUAL_INT(0, p.nErr);80 TEST_ASSERT_NOT_NULL(p.pNewTable);81 TEST_ASSERT_EQUAL_INT(TABTYP_VIEW, p.pNewTable->eTabType);82 TEST_ASSERT_NOT_NULL(p.pNewTable->u.view.pSelect);83 TEST_ASSERT_NOT_NULL(p.pNewTable->pCheck); /* stores view column name list copy */84 TEST_ASSERT_EQUAL_INT(1, p.pNewTable->pCheck->nExpr);85 86 /* Check rowid visibility flag behavior */87#ifdef SQLITE_ALLOW_ROWID_IN_VIEW88 /* Bit presence should match runtime config */89 int hasNoVisible = (p.pNewTable->tabFlags & TF_NoVisibleRowid)!=0;90 int cfgRequires = (sqlite3Config.mNoVisibleRowid & TF_NoVisibleRowid)!=0;91 TEST_ASSERT_EQUAL_INT(cfgRequires, hasNoVisible);92#else93 TEST_ASSERT_TRUE((p.pNewTable->tabFlags & TF_NoVisibleRowid)!=0);94#endif95 96 cleanupParse(&p);97 sqlite3_close(db);98}99 100/* Test: parameters are not allowed in views (nVar>0) */101void test_sqlite3CreateView_error_parameters_not_allowed(void){102 sqlite3 *db = 0;103 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));104 105 Parse p; memset(&p, 0, sizeof(p));106 p.db = db;107 p.isCreate = 1;108 p.nVar = 1; /* triggers error */109 110 const char *zSql = "CREATE VIEW v_params AS SELECT 1";111 Token tBegin, tName1, tName2, tLast;112 tBegin.z = zSql; tBegin.n = 6;113 const char *zName = strstr(zSql, "v_params");114 TEST_ASSERT_NOT_NULL(zName);115 tName1.z = zName; tName1.n = (int)strlen("v_params");116 tName2.z = zSql; tName2.n = 0;117 const char *zOne = strrchr(zSql, '1');118 TEST_ASSERT_NOT_NULL(zOne);119 tLast.z = zOne; tLast.n = 1;120 p.sLastToken = tLast;121 122 ExprList *pCNames = makeOneColName(&p, "c1");123 Select *pSel = makeSelectConst(&p, "1");124 125 sqlite3CreateView(&p, &tBegin, &tName1, &tName2, pCNames, pSel, 0, 0);126 127 TEST_ASSERT_TRUE(p.nErr>0);128 TEST_ASSERT_NOT_NULL(p.zErrMsg);129 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "parameters are not allowed in views"));130 TEST_ASSERT_NULL(p.pNewTable);131 132 cleanupParse(&p);133 sqlite3_close(db);134}135 136/* Test: unknown database qualifier (two-part name with unknown db) */137void test_sqlite3CreateView_unknown_database(void){138 sqlite3 *db = 0;139 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));140 141 Parse p; memset(&p, 0, sizeof(p));142 p.db = db;143 p.isCreate = 1;144 145 const char *zSql = "CREATE VIEW nosuchdb.v AS SELECT 1";146 Token tBegin, tName1, tName2, tLast;147 tBegin.z = zSql; tBegin.n = 6;148 const char *zDb = strstr(zSql, "nosuchdb");149 const char *zTbl = strstr(zSql, ".v");150 TEST_ASSERT_NOT_NULL(zDb);151 TEST_ASSERT_NOT_NULL(zTbl);152 tName1.z = zDb; tName1.n = (int)strlen("nosuchdb");153 tName2.z = zTbl+1; tName2.n = 1; /* "v" */154 const char *zOne = strrchr(zSql, '1');155 TEST_ASSERT_NOT_NULL(zOne);156 tLast.z = zOne; tLast.n = 1;157 p.sLastToken = tLast;158 159 ExprList *pCNames = makeOneColName(&p, "c1");160 Select *pSel = makeSelectConst(&p, "1");161 162 sqlite3CreateView(&p, &tBegin, &tName1, &tName2, pCNames, pSel, 0, 0);163 164 TEST_ASSERT_TRUE(p.nErr>0);165 TEST_ASSERT_NOT_NULL(p.zErrMsg);166 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "unknown database"));167 TEST_ASSERT_NULL(p.pNewTable);168 169 cleanupParse(&p);170 sqlite3_close(db);171}172 173/* Test: TEMP view name must be unqualified (isTemp && qualified && db!="temp") */174void test_sqlite3CreateView_temp_must_be_unqualified(void){175 sqlite3 *db = 0;176 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));177 178 Parse p; memset(&p, 0, sizeof(p));179 p.db = db;180 p.isCreate = 1;181 182 const char *zSql = "CREATE TEMP VIEW main.vt AS SELECT 1";183 Token tBegin, tName1, tName2, tLast;184 tBegin.z = zSql; tBegin.n = 6;185 const char *zDb = strstr(zSql, "main");186 const char *zTblDot = strstr(zSql, "main.vt");187 TEST_ASSERT_NOT_NULL(zDb);188 TEST_ASSERT_NOT_NULL(zTblDot);189 tName1.z = zDb; tName1.n = (int)strlen("main");190 tName2.z = zTblDot + 5; tName2.n = (int)strlen("vt"); /* after 'main.' */191 const char *zOne = strrchr(zSql, '1');192 TEST_ASSERT_NOT_NULL(zOne);193 tLast.z = zOne; tLast.n = 1;194 p.sLastToken = tLast;195 196 ExprList *pCNames = makeOneColName(&p, "c1");197 Select *pSel = makeSelectConst(&p, "1");198 199 sqlite3CreateView(&p, &tBegin, &tName1, &tName2, pCNames, pSel, 1 /*isTemp*/, 0);200 201 TEST_ASSERT_TRUE(p.nErr>0);202 TEST_ASSERT_NOT_NULL(p.zErrMsg);203 TEST_ASSERT_NOT_NULL(strstr(p.zErrMsg, "temporary table name must be unqualified"));204 TEST_ASSERT_NULL(p.pNewTable);205 206 cleanupParse(&p);207 sqlite3_close(db);208}209 210/* Test: noErr=true when view already exists should not raise an error */211void test_sqlite3CreateView_noErr_when_exists(void){212 sqlite3 *db = 0;213 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));214 215 /* Pre-create the view using the public API to populate schema */216 TEST_ASSERT_EQUAL(SQLITE_OK,217 sqlite3_exec(db, "CREATE VIEW v_exists AS SELECT 1", 0, 0, 0));218 219 Parse p; memset(&p, 0, sizeof(p));220 p.db = db;221 p.isCreate = 1;222 223 const char *zSql = "CREATE VIEW v_exists AS SELECT 1";224 Token tBegin, tName1, tName2, tLast;225 tBegin.z = zSql; tBegin.n = 6;226 const char *zName = strstr(zSql, "v_exists");227 TEST_ASSERT_NOT_NULL(zName);228 tName1.z = zName; tName1.n = (int)strlen("v_exists");229 tName2.z = zSql; tName2.n = 0;230 const char *zOne = strrchr(zSql, '1');231 TEST_ASSERT_NOT_NULL(zOne);232 tLast.z = zOne; tLast.n = 1;233 p.sLastToken = tLast;234 235 ExprList *pCNames = makeOneColName(&p, "c1");236 Select *pSel = makeSelectConst(&p, "1");237 238 sqlite3CreateView(&p, &tBegin, &tName1, &tName2, pCNames, pSel, 0, 1 /*noErr*/);239 240 /* Should not report an error, and should not create a new table object */241 TEST_ASSERT_EQUAL_INT(0, p.nErr);242 TEST_ASSERT_NULL(p.pNewTable);243 244 cleanupParse(&p);245 sqlite3_close(db);246}247 248int main(void) {249 UNITY_BEGIN();250 RUN_TEST(test_sqlite3CreateView_basic_success);251 RUN_TEST(test_sqlite3CreateView_error_parameters_not_allowed);252 RUN_TEST(test_sqlite3CreateView_unknown_database);253 RUN_TEST(test_sqlite3CreateView_temp_must_be_unqualified);254 RUN_TEST(test_sqlite3CreateView_noErr_when_exists);255 return UNITY_END();256}