| #include "sqliteInt.h" |
| #include "unity.h" |
| #include <string.h> |
| #include <stdlib.h> |
|
|
| |
| static Token mkToken(const char *z){ |
| Token t; |
| t.z = z; |
| t.n = (int)strlen(z); |
| return t; |
| } |
|
|
| static SrcList* makeSrcList(sqlite3 *db, const char *zDbName, const char *zTab){ |
| |
| |
| SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList)); |
| TEST_ASSERT_NOT_NULL_MESSAGE(p, "Failed to allocate SrcList"); |
| p->nAlloc = 1; |
| p->nSrc = 1; |
| p->a[0].zName = sqlite3DbStrDup(db, zTab); |
| TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zName, "Failed to dup table name"); |
| if( zDbName ){ |
| p->a[0].zDatabase = sqlite3DbStrDup(db, zDbName); |
| TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zDatabase, "Failed to dup db name"); |
| } |
| return p; |
| } |
|
|
| static void parseInit(Parse *pParse, sqlite3 *db){ |
| memset(pParse, 0, sizeof(Parse)); |
| pParse->db = db; |
| } |
|
|
| static void parseCleanup(Parse *pParse){ |
| if( pParse->pVdbe ){ |
| sqlite3VdbeDelete(pParse->pVdbe); |
| pParse->pVdbe = NULL; |
| } |
| if( pParse->zErrMsg ){ |
| sqlite3DbFree(pParse->db, pParse->zErrMsg); |
| pParse->zErrMsg = NULL; |
| } |
| } |
|
|
| |
| void setUp(void) { |
| |
| } |
| void tearDown(void) { |
| |
| } |
|
|
| |
|
|
| void test_sqlite3AlterRenameColumn_no_such_table(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| SrcList *pSrc = makeSrcList(db, NULL, "nope_table"); |
| Token oldTok = mkToken("a"); |
| Token newTok = mkToken("b"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_TRUE_MESSAGE(p.nErr>0 || p.zErrMsg!=NULL, "Expected error for missing table"); |
| |
| TEST_ASSERT_NULL(p.pVdbe); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| void test_sqlite3AlterRenameColumn_view_error(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_exec(db, |
| "CREATE TABLE t1(a,b);" |
| "CREATE VIEW v1 AS SELECT a,b FROM t1;", 0, 0, 0)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| SrcList *pSrc = makeSrcList(db, NULL, "v1"); |
| Token oldTok = mkToken("a"); |
| Token newTok = mkToken("x"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_TRUE(p.nErr>0); |
| TEST_ASSERT_NOT_NULL(p.zErrMsg); |
| TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "cannot rename columns of")); |
|
|
| |
| TEST_ASSERT_NULL(p.pVdbe); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| void test_sqlite3AlterRenameColumn_column_not_found(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_exec(db, |
| "CREATE TABLE t1(a,b);", 0, 0, 0)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| SrcList *pSrc = makeSrcList(db, NULL, "t1"); |
| Token oldTok = mkToken("c"); |
| Token newTok = mkToken("d"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_TRUE(p.nErr>0); |
| TEST_ASSERT_NOT_NULL(p.zErrMsg); |
| TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "no such column")); |
|
|
| TEST_ASSERT_NULL(p.pVdbe); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| void test_sqlite3AlterRenameColumn_success_main_db(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_exec(db, |
| "CREATE TABLE t1(a,b,c);", 0, 0, 0)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| SrcList *pSrc = makeSrcList(db, NULL, "t1"); |
| Token oldTok = mkToken("a"); |
| Token newTok = mkToken("x"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_EQUAL_INT(0, p.nErr); |
| TEST_ASSERT_NULL(p.zErrMsg); |
| TEST_ASSERT_NOT_NULL(p.pVdbe); |
| |
| TEST_ASSERT_TRUE(p.pVdbe->nOp > 0); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| void test_sqlite3AlterRenameColumn_success_temp_db_quoted_newname(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_exec(db, |
| "CREATE TEMP TABLE tt(a,b);", 0, 0, 0)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| |
| SrcList *pSrc = makeSrcList(db, "temp", "tt"); |
| Token oldTok = mkToken("b"); |
| Token newTok = mkToken("\"x y\""); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_EQUAL_INT(0, p.nErr); |
| TEST_ASSERT_NULL(p.zErrMsg); |
| TEST_ASSERT_NOT_NULL(p.pVdbe); |
| TEST_ASSERT_TRUE(p.pVdbe->nOp > 0); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| void test_sqlite3AlterRenameColumn_cannot_alter_system_table(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| |
| SrcList *pSrc = makeSrcList(db, NULL, "sqlite_schema"); |
| Token oldTok = mkToken("type"); |
| Token newTok = mkToken("xtype"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| TEST_ASSERT_TRUE(p.nErr>0); |
| TEST_ASSERT_NOT_NULL(p.zErrMsg); |
| TEST_ASSERT_NOT_EQUAL(NULL, strstr(p.zErrMsg, "may not be altered")); |
|
|
| TEST_ASSERT_NULL(p.pVdbe); |
|
|
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
|
|
| #ifndef SQLITE_OMIT_AUTHORIZATION |
| static int denyAuthorizer(void *p, int op, |
| const char *z1, const char *z2, |
| const char *z3, const char *z4){ |
| UNUSED_PARAMETER(p); |
| UNUSED_PARAMETER(op); |
| UNUSED_PARAMETER(z1); |
| UNUSED_PARAMETER(z2); |
| UNUSED_PARAMETER(z3); |
| UNUSED_PARAMETER(z4); |
| return SQLITE_DENY; |
| } |
|
|
| void test_sqlite3AlterRenameColumn_authorizer_denies(void){ |
| sqlite3 *db = 0; |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_exec(db, |
| "CREATE TABLE t1(a,b);", 0, 0, 0)); |
| TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_set_authorizer(db, denyAuthorizer, 0)); |
|
|
| Parse p; parseInit(&p, db); |
|
|
| SrcList *pSrc = makeSrcList(db, NULL, "t1"); |
| Token oldTok = mkToken("a"); |
| Token newTok = mkToken("x"); |
|
|
| sqlite3AlterRenameColumn(&p, pSrc, &oldTok, &newTok); |
|
|
| |
| TEST_ASSERT_TRUE(p.nErr>0 || p.zErrMsg!=NULL); |
| TEST_ASSERT_NULL(p.pVdbe); |
|
|
| sqlite3_set_authorizer(db, 0, 0); |
| parseCleanup(&p); |
| sqlite3_close(db); |
| } |
| #endif |
|
|
| int main(void){ |
| UNITY_BEGIN(); |
| RUN_TEST(test_sqlite3AlterRenameColumn_no_such_table); |
| RUN_TEST(test_sqlite3AlterRenameColumn_view_error); |
| RUN_TEST(test_sqlite3AlterRenameColumn_column_not_found); |
| RUN_TEST(test_sqlite3AlterRenameColumn_success_main_db); |
| RUN_TEST(test_sqlite3AlterRenameColumn_success_temp_db_quoted_newname); |
| RUN_TEST(test_sqlite3AlterRenameColumn_cannot_alter_system_table); |
| #ifndef SQLITE_OMIT_AUTHORIZATION |
| RUN_TEST(test_sqlite3AlterRenameColumn_authorizer_denies); |
| #endif |
| return UNITY_END(); |
| } |