AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3 4#include <string.h>5#include <stdio.h>6 7/* Helper: execute SQL and assert success */8static void execSQL(sqlite3 *db, const char *zSql){9 char *zErr = 0;10 int rc = sqlite3_exec(db, zSql, 0, 0, &zErr);11 if( rc!=SQLITE_OK ){12 fprintf(stderr, "SQL error (%d): %s while running: %s\n", rc, zErr?zErr:"(null)", zSql);13 }14 TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_exec failed");15 if( zErr ) sqlite3_free(zErr);16}17 18/* Helper: create a SrcList for a single table name */19static SrcList *makeSrcList(sqlite3 *db, const char *zName){20 Token tName;21 tName.z = zName;22 tName.n = (int)strlen(zName);23 return sqlite3SrcListAppend(db, 0, &tName, 0);24}25 26/* Helper: initialize a Parse object */27static void initParse(sqlite3 *db, Parse *p){28 memset(p, 0, sizeof(*p));29 p->db = db;30}31 32/* Helper: free Parse resources left after calling the target function */33static void cleanupParse(sqlite3 *db, Parse *p){34 if( p->zErrMsg ){35 sqlite3DbFree(db, p->zErrMsg);36 p->zErrMsg = 0;37 }38 if( p->pVdbe ){39 sqlite3VdbeDelete(p->pVdbe);40 p->pVdbe = 0;41 }42}43 44void setUp(void) {45 /* No global setup */46}47 48void tearDown(void) {49 /* No global teardown */50}51 52/* Test: dropping a non-existent column reports an error */53void test_sqlite3AlterDropColumn_no_such_column(void){54 sqlite3 *db = 0;55 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));56 57 execSQL(db, "CREATE TABLE t1(a, b);");58 59 Parse p;60 initParse(db, &p);61 SrcList *pSrc = makeSrcList(db, "t1");62 63 Token tCol;64 tCol.z = "c";65 tCol.n = 1;66 67 sqlite3BtreeEnterAll(db);68 sqlite3AlterDropColumn(&p, pSrc, &tCol);69 sqlite3BtreeLeaveAll(db);70 71 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error for non-existent column");72 TEST_ASSERT_NOT_NULL(p.zErrMsg);73 TEST_ASSERT_NOT_EQUAL(-1, (int)sqlite3StrLike("no such column:%", p.zErrMsg, 0)); /* rough check */74 /* Also check substring for robustness */75 TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "no such column"));76 77 cleanupParse(db, &p);78 sqlite3_close(db);79}80 81/* Test: cannot drop PRIMARY KEY column */82void test_sqlite3AlterDropColumn_drop_primary_key_column(void){83 sqlite3 *db = 0;84 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));85 86 execSQL(db, "CREATE TABLE tpk(a INTEGER PRIMARY KEY, b);");87 88 Parse p;89 initParse(db, &p);90 SrcList *pSrc = makeSrcList(db, "tpk");91 92 Token tCol;93 tCol.z = "a";94 tCol.n = 1;95 96 sqlite3BtreeEnterAll(db);97 sqlite3AlterDropColumn(&p, pSrc, &tCol);98 sqlite3BtreeLeaveAll(db);99 100 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping PRIMARY KEY column");101 TEST_ASSERT_NOT_NULL(p.zErrMsg);102 TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "PRIMARY KEY"));103 104 cleanupParse(db, &p);105 sqlite3_close(db);106}107 108/* Test: cannot drop a column with a column-level UNIQUE constraint */109void test_sqlite3AlterDropColumn_drop_unique_column(void){110 sqlite3 *db = 0;111 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));112 113 /* Column-level UNIQUE to set COLFLAG_UNIQUE */114 execSQL(db, "CREATE TABLE tu(a UNIQUE, b);");115 116 Parse p;117 initParse(db, &p);118 SrcList *pSrc = makeSrcList(db, "tu");119 120 Token tCol;121 tCol.z = "a";122 tCol.n = 1;123 124 sqlite3BtreeEnterAll(db);125 sqlite3AlterDropColumn(&p, pSrc, &tCol);126 sqlite3BtreeLeaveAll(db);127 128 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping UNIQUE column");129 TEST_ASSERT_NOT_NULL(p.zErrMsg);130 TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "UNIQUE"));131 132 cleanupParse(db, &p);133 sqlite3_close(db);134}135 136/* Test: cannot drop the last remaining column of a table */137void test_sqlite3AlterDropColumn_drop_only_remaining_column(void){138 sqlite3 *db = 0;139 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));140 141 execSQL(db, "CREATE TABLE t1col(a);");142 143 Parse p;144 initParse(db, &p);145 SrcList *pSrc = makeSrcList(db, "t1col");146 147 Token tCol;148 tCol.z = "a";149 tCol.n = 1;150 151 sqlite3BtreeEnterAll(db);152 sqlite3AlterDropColumn(&p, pSrc, &tCol);153 sqlite3BtreeLeaveAll(db);154 155 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping the only column");156 TEST_ASSERT_NOT_NULL(p.zErrMsg);157 TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "no other columns exist"));158 159 cleanupParse(db, &p);160 sqlite3_close(db);161}162 163/* Test: cannot drop a column from a view */164void test_sqlite3AlterDropColumn_on_view(void){165 sqlite3 *db = 0;166 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));167 168 execSQL(db, "CREATE VIEW v1 AS SELECT 1 AS a, 2 AS b;");169 170 Parse p;171 initParse(db, &p);172 SrcList *pSrc = makeSrcList(db, "v1");173 174 Token tCol;175 tCol.z = "a";176 tCol.n = 1;177 178 sqlite3BtreeEnterAll(db);179 sqlite3AlterDropColumn(&p, pSrc, &tCol);180 sqlite3BtreeLeaveAll(db);181 182 TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping column from view");183 TEST_ASSERT_NOT_NULL(p.zErrMsg);184 TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "drop column from view"));185 186 cleanupParse(db, &p);187 sqlite3_close(db);188}189 190/* Test: successful generation for dropping a regular column from a table */191void test_sqlite3AlterDropColumn_success_generates_vdbe(void){192 sqlite3 *db = 0;193 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));194 195 execSQL(db, "CREATE TABLE tgood(a, b, c);");196 execSQL(db, "INSERT INTO tgood VALUES(1,2,3);");197 198 Parse p;199 initParse(db, &p);200 SrcList *pSrc = makeSrcList(db, "tgood");201 202 Token tCol;203 tCol.z = "b";204 tCol.n = 1;205 206 sqlite3BtreeEnterAll(db);207 sqlite3AlterDropColumn(&p, pSrc, &tCol);208 sqlite3BtreeLeaveAll(db);209 210 TEST_ASSERT_EQUAL_INT_MESSAGE(0, p.nErr, "Unexpected error during valid drop column codegen");211 TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "Expected VDBE code to be generated");212 TEST_ASSERT_TRUE_MESSAGE(p.nMem>0 || p.nTab>0, "Expected some registers/cursors allocated");213 214 cleanupParse(db, &p);215 sqlite3_close(db);216}217 218int main(void){219 UNITY_BEGIN();220 RUN_TEST(test_sqlite3AlterDropColumn_no_such_column);221 RUN_TEST(test_sqlite3AlterDropColumn_drop_primary_key_column);222 RUN_TEST(test_sqlite3AlterDropColumn_drop_unique_column);223 RUN_TEST(test_sqlite3AlterDropColumn_drop_only_remaining_column);224 RUN_TEST(test_sqlite3AlterDropColumn_on_view);225 RUN_TEST(test_sqlite3AlterDropColumn_success_generates_vdbe);226 return UNITY_END();227}