|
|
#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(); |
|
|
} |