| #include "sqliteInt.h" |
| #include "unity.h" |
| #include <string.h> |
| #include <stdlib.h> |
|
|
| |
| static sqlite3 *gDb = NULL; |
|
|
| |
| void setUp(void) { |
| int rc = sqlite3_open(":memory:", &gDb); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
| TEST_ASSERT_NOT_NULL(gDb); |
| } |
|
|
| void tearDown(void) { |
| if (gDb) { |
| sqlite3_close(gDb); |
| gDb = NULL; |
| } |
| } |
|
|
| |
| static SrcList* makeSrcList(const char *zName){ |
| Token t; |
| memset(&t, 0, sizeof(t)); |
| t.z = zName; |
| t.n = (int)strlen(zName); |
| return sqlite3SrcListAppend(gDb, 0, &t, 0); |
| } |
|
|
| |
| static void initParse(Parse *p){ |
| memset(p, 0, sizeof(*p)); |
| p->db = gDb; |
| } |
|
|
| |
| void test_sqlite3AlterBeginAddColumn_success_creates_partial_copy(void) { |
| char *err = 0; |
| int rc; |
|
|
| |
| rc = sqlite3_exec(gDb, |
| "CREATE TABLE t(a INTEGER DEFAULT 1, b TEXT, c REAL DEFAULT 3.14);", |
| 0, 0, &err); |
| TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create failed"); |
| if (err) sqlite3_free(err), err = 0; |
|
|
| |
| Table *pOrig = sqlite3FindTable(gDb, "t", "main"); |
| TEST_ASSERT_NOT_NULL(pOrig); |
| TEST_ASSERT_TRUE(pOrig->nCol > 0); |
|
|
| |
| SrcList *pSrc = makeSrcList("t"); |
| TEST_ASSERT_NOT_NULL(pSrc); |
|
|
| Parse parse; |
| initParse(&parse); |
| TEST_ASSERT_NULL(parse.pNewTable); |
|
|
| |
| sqlite3BtreeEnterAll(gDb); |
| sqlite3AlterBeginAddColumn(&parse, pSrc); |
| sqlite3BtreeLeaveAll(gDb); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, parse.nErr); |
| TEST_ASSERT_NOT_NULL(parse.pNewTable); |
|
|
| Table *pNew = parse.pNewTable; |
|
|
| |
| TEST_ASSERT_NOT_NULL(pNew->zName); |
| TEST_ASSERT_EQUAL_STRING("sqlite_altertab_t", pNew->zName); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(pOrig->nCol, pNew->nCol); |
|
|
| |
| for(int i=0; i<pNew->nCol; i++){ |
| Column *cOrig = &pOrig->aCol[i]; |
| Column *cNew = &pNew->aCol[i]; |
| TEST_ASSERT_NOT_NULL(cNew->zCnName); |
| TEST_ASSERT_NOT_NULL(cOrig->zCnName); |
| |
| TEST_ASSERT(cNew->zCnName != cOrig->zCnName); |
| TEST_ASSERT_EQUAL_STRING(cOrig->zCnName, cNew->zCnName); |
| |
| TEST_ASSERT_EQUAL_INT(sqlite3StrIHash(cNew->zCnName), cNew->hName); |
| } |
|
|
| |
| TEST_ASSERT(pNew->pSchema == pOrig->pSchema); |
| TEST_ASSERT_TRUE(pNew->u.tab.addColOffset > 0); |
| TEST_ASSERT_EQUAL_INT(pOrig->u.tab.addColOffset, pNew->u.tab.addColOffset); |
|
|
| |
| if( pOrig->u.tab.pDfltList ){ |
| TEST_ASSERT_NOT_NULL(pNew->u.tab.pDfltList); |
| TEST_ASSERT_NOT_NULL(pOrig->u.tab.pDfltList); |
| TEST_ASSERT(pNew->u.tab.pDfltList != pOrig->u.tab.pDfltList); |
| TEST_ASSERT_EQUAL_INT(pOrig->u.tab.pDfltList->nExpr, |
| pNew->u.tab.pDfltList->nExpr); |
| } |
|
|
| |
| TEST_ASSERT_EQUAL_INT(1, pNew->nTabRef); |
|
|
| |
| sqlite3DeleteTable(gDb, pNew); |
| parse.pNewTable = 0; |
| } |
|
|
| |
| void test_sqlite3AlterBeginAddColumn_on_view_sets_error(void) { |
| char *err = 0; |
| int rc; |
|
|
| rc = sqlite3_exec(gDb, "CREATE VIEW v AS SELECT 1 AS x;", 0, 0, &err); |
| TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create view failed"); |
| if (err) sqlite3_free(err), err = 0; |
|
|
| SrcList *pSrc = makeSrcList("v"); |
| TEST_ASSERT_NOT_NULL(pSrc); |
|
|
| Parse parse; |
| initParse(&parse); |
|
|
| sqlite3BtreeEnterAll(gDb); |
| sqlite3AlterBeginAddColumn(&parse, pSrc); |
| sqlite3BtreeLeaveAll(gDb); |
|
|
| TEST_ASSERT_TRUE(parse.nErr > 0); |
| TEST_ASSERT_NULL(parse.pNewTable); |
| TEST_ASSERT_NOT_NULL(parse.zErrMsg); |
| TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "Cannot add a column to a view")); |
|
|
| sqlite3DbFree(gDb, parse.zErrMsg); |
| parse.zErrMsg = 0; |
| } |
|
|
| |
| void test_sqlite3AlterBeginAddColumn_on_system_table_sets_error(void) { |
| char *err = 0; |
| int rc; |
|
|
| |
| rc = sqlite3_exec(gDb, |
| "CREATE TABLE at(id INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);", |
| 0, 0, &err); |
| TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create autoinc failed"); |
| if (err) sqlite3_free(err), err = 0; |
|
|
| |
| rc = sqlite3_exec(gDb, "INSERT INTO at(b) VALUES('x');", 0, 0, &err); |
| TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "insert failed"); |
| if (err) sqlite3_free(err), err = 0; |
|
|
| |
| SrcList *pSrc = makeSrcList("sqlite_sequence"); |
| TEST_ASSERT_NOT_NULL(pSrc); |
|
|
| Parse parse; |
| initParse(&parse); |
|
|
| sqlite3BtreeEnterAll(gDb); |
| sqlite3AlterBeginAddColumn(&parse, pSrc); |
| sqlite3BtreeLeaveAll(gDb); |
|
|
| TEST_ASSERT_TRUE(parse.nErr > 0); |
| TEST_ASSERT_NULL(parse.pNewTable); |
| TEST_ASSERT_NOT_NULL(parse.zErrMsg); |
| TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "table sqlite_sequence may not be altered")); |
|
|
| sqlite3DbFree(gDb, parse.zErrMsg); |
| parse.zErrMsg = 0; |
| } |
|
|
| |
| void test_sqlite3AlterBeginAddColumn_table_not_found_sets_error(void) { |
| SrcList *pSrc = makeSrcList("no_such_table_123"); |
| TEST_ASSERT_NOT_NULL(pSrc); |
|
|
| Parse parse; |
| initParse(&parse); |
|
|
| sqlite3BtreeEnterAll(gDb); |
| sqlite3AlterBeginAddColumn(&parse, pSrc); |
| sqlite3BtreeLeaveAll(gDb); |
|
|
| TEST_ASSERT_TRUE(parse.nErr > 0); |
| TEST_ASSERT_NULL(parse.pNewTable); |
| TEST_ASSERT_NOT_NULL(parse.zErrMsg); |
| TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "no such table")); |
|
|
| sqlite3DbFree(gDb, parse.zErrMsg); |
| parse.zErrMsg = 0; |
| } |
|
|
| |
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_sqlite3AlterBeginAddColumn_success_creates_partial_copy); |
| RUN_TEST(test_sqlite3AlterBeginAddColumn_on_view_sets_error); |
| RUN_TEST(test_sqlite3AlterBeginAddColumn_on_system_table_sets_error); |
| RUN_TEST(test_sqlite3AlterBeginAddColumn_table_not_found_sets_error); |
| return UNITY_END(); |
| } |