|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
|
|
|
#include <string.h> |
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
static void execSQL(sqlite3 *db, const char *zSql){ |
|
|
char *zErr = 0; |
|
|
int rc = sqlite3_exec(db, zSql, 0, 0, &zErr); |
|
|
if( rc!=SQLITE_OK ){ |
|
|
fprintf(stderr, "SQL error (%d): %s while running: %s\n", rc, zErr?zErr:"(null)", zSql); |
|
|
} |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_exec failed"); |
|
|
if( zErr ) sqlite3_free(zErr); |
|
|
} |
|
|
|
|
|
|
|
|
static SrcList *makeSrcList(sqlite3 *db, const char *zName){ |
|
|
Token tName; |
|
|
tName.z = zName; |
|
|
tName.n = (int)strlen(zName); |
|
|
return sqlite3SrcListAppend(db, 0, &tName, 0); |
|
|
} |
|
|
|
|
|
|
|
|
static void initParse(sqlite3 *db, Parse *p){ |
|
|
memset(p, 0, sizeof(*p)); |
|
|
p->db = db; |
|
|
} |
|
|
|
|
|
|
|
|
static void cleanupParse(sqlite3 *db, Parse *p){ |
|
|
if( p->zErrMsg ){ |
|
|
sqlite3DbFree(db, p->zErrMsg); |
|
|
p->zErrMsg = 0; |
|
|
} |
|
|
if( p->pVdbe ){ |
|
|
sqlite3VdbeDelete(p->pVdbe); |
|
|
p->pVdbe = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_no_such_column(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSQL(db, "CREATE TABLE t1(a, b);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "t1"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "c"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error for non-existent column"); |
|
|
TEST_ASSERT_NOT_NULL(p.zErrMsg); |
|
|
TEST_ASSERT_NOT_EQUAL(-1, (int)sqlite3StrLike("no such column:%", p.zErrMsg, 0)); |
|
|
|
|
|
TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "no such column")); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_drop_primary_key_column(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSQL(db, "CREATE TABLE tpk(a INTEGER PRIMARY KEY, b);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "tpk"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "a"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping PRIMARY KEY column"); |
|
|
TEST_ASSERT_NOT_NULL(p.zErrMsg); |
|
|
TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "PRIMARY KEY")); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_drop_unique_column(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
|
|
|
execSQL(db, "CREATE TABLE tu(a UNIQUE, b);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "tu"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "a"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping UNIQUE column"); |
|
|
TEST_ASSERT_NOT_NULL(p.zErrMsg); |
|
|
TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "UNIQUE")); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_drop_only_remaining_column(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSQL(db, "CREATE TABLE t1col(a);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "t1col"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "a"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping the only column"); |
|
|
TEST_ASSERT_NOT_NULL(p.zErrMsg); |
|
|
TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "no other columns exist")); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_on_view(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSQL(db, "CREATE VIEW v1 AS SELECT 1 AS a, 2 AS b;"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "v1"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "a"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "Expected error dropping column from view"); |
|
|
TEST_ASSERT_NOT_NULL(p.zErrMsg); |
|
|
TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "drop column from view")); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropColumn_success_generates_vdbe(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSQL(db, "CREATE TABLE tgood(a, b, c);"); |
|
|
execSQL(db, "INSERT INTO tgood VALUES(1,2,3);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(db, &p); |
|
|
SrcList *pSrc = makeSrcList(db, "tgood"); |
|
|
|
|
|
Token tCol; |
|
|
tCol.z = "b"; |
|
|
tCol.n = 1; |
|
|
|
|
|
sqlite3BtreeEnterAll(db); |
|
|
sqlite3AlterDropColumn(&p, pSrc, &tCol); |
|
|
sqlite3BtreeLeaveAll(db); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(0, p.nErr, "Unexpected error during valid drop column codegen"); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "Expected VDBE code to be generated"); |
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nMem>0 || p.nTab>0, "Expected some registers/cursors allocated"); |
|
|
|
|
|
cleanupParse(db, &p); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
int main(void){ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_no_such_column); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_drop_primary_key_column); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_drop_unique_column); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_drop_only_remaining_column); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_on_view); |
|
|
RUN_TEST(test_sqlite3AlterDropColumn_success_generates_vdbe); |
|
|
return UNITY_END(); |
|
|
} |