|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <string.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
extern void test_renameTableFunc(sqlite3_context *context, int NotUsed, sqlite3_value **argv); |
|
|
|
|
|
static void initStrValue(Mem *p, sqlite3 *db, const char *z){ |
|
|
sqlite3VdbeMemInit(p, db, 0); |
|
|
sqlite3VdbeMemSetStr(p, z, -1, SQLITE_UTF8, SQLITE_TRANSIENT); |
|
|
} |
|
|
|
|
|
static void initIntValue(Mem *p, sqlite3 *db, sqlite3_int64 v){ |
|
|
sqlite3VdbeMemInit(p, db, 0); |
|
|
sqlite3VdbeMemSetInt64(p, v); |
|
|
} |
|
|
|
|
|
static void releaseMemArray(Mem *a, int n){ |
|
|
for(int i=0; i<n; i++){ |
|
|
sqlite3VdbeMemRelease(&a[i]); |
|
|
} |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static void execOrFail(sqlite3 *db, const char *sql){ |
|
|
char *zErr = 0; |
|
|
int rc = sqlite3_exec(db, sql, 0, 0, &zErr); |
|
|
if( zErr ) sqlite3_free(zErr); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameTableFunc_rename_table_name_in_create_table(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execOrFail(db, "CREATE TABLE t2(a, CHECK(a>0))"); |
|
|
|
|
|
Mem argvMem[7]; |
|
|
sqlite3_context ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.s.db = db; |
|
|
|
|
|
initStrValue(&argvMem[0], db, "main"); |
|
|
initStrValue(&argvMem[1], db, "table"); |
|
|
initStrValue(&argvMem[2], db, "t2"); |
|
|
initStrValue(&argvMem[3], db, "CREATE TABLE t2(a, CHECK(a>0))"); |
|
|
initStrValue(&argvMem[4], db, "t2"); |
|
|
initStrValue(&argvMem[5], db, "t3"); |
|
|
initIntValue(&argvMem[6], db, 0); |
|
|
|
|
|
sqlite3_value *argv[7] = { |
|
|
(sqlite3_value*)&argvMem[0], (sqlite3_value*)&argvMem[1], |
|
|
(sqlite3_value*)&argvMem[2], (sqlite3_value*)&argvMem[3], |
|
|
(sqlite3_value*)&argvMem[4], (sqlite3_value*)&argvMem[5], |
|
|
(sqlite3_value*)&argvMem[6] |
|
|
}; |
|
|
|
|
|
test_renameTableFunc(&ctx, 0, argv); |
|
|
|
|
|
const unsigned char *zRes = sqlite3_value_text((sqlite3_value*)&ctx.s); |
|
|
TEST_ASSERT_NOT_NULL(zRes); |
|
|
TEST_ASSERT_EQUAL_STRING("CREATE TABLE \"t3\"(a, CHECK(a>0))", (const char*)zRes); |
|
|
|
|
|
sqlite3VdbeMemRelease(&ctx.s); |
|
|
releaseMemArray(argvMem, 7); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameTableFunc_updates_fk_references(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execOrFail(db, "CREATE TABLE t2(x PRIMARY KEY)"); |
|
|
execOrFail(db, "CREATE TABLE t1(a REFERENCES t2)"); |
|
|
|
|
|
Mem argvMem[7]; |
|
|
sqlite3_context ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.s.db = db; |
|
|
|
|
|
initStrValue(&argvMem[0], db, "main"); |
|
|
initStrValue(&argvMem[1], db, "table"); |
|
|
initStrValue(&argvMem[2], db, "t1"); |
|
|
initStrValue(&argvMem[3], db, "CREATE TABLE t1(a REFERENCES t2)"); |
|
|
initStrValue(&argvMem[4], db, "t2"); |
|
|
initStrValue(&argvMem[5], db, "t3"); |
|
|
initIntValue(&argvMem[6], db, 0); |
|
|
|
|
|
sqlite3_value *argv[7] = { |
|
|
(sqlite3_value*)&argvMem[0], (sqlite3_value*)&argvMem[1], |
|
|
(sqlite3_value*)&argvMem[2], (sqlite3_value*)&argvMem[3], |
|
|
(sqlite3_value*)&argvMem[4], (sqlite3_value*)&argvMem[5], |
|
|
(sqlite3_value*)&argvMem[6] |
|
|
}; |
|
|
|
|
|
test_renameTableFunc(&ctx, 0, argv); |
|
|
|
|
|
const unsigned char *zRes = sqlite3_value_text((sqlite3_value*)&ctx.s); |
|
|
TEST_ASSERT_NOT_NULL(zRes); |
|
|
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t1(a REFERENCES \"t3\")", (const char*)zRes); |
|
|
|
|
|
sqlite3VdbeMemRelease(&ctx.s); |
|
|
releaseMemArray(argvMem, 7); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameTableFunc_updates_view_select_references(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execOrFail(db, "CREATE TABLE t2(x)"); |
|
|
|
|
|
Mem argvMem[7]; |
|
|
sqlite3_context ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.s.db = db; |
|
|
|
|
|
initStrValue(&argvMem[0], db, "main"); |
|
|
initStrValue(&argvMem[1], db, "view"); |
|
|
initStrValue(&argvMem[2], db, "v"); |
|
|
initStrValue(&argvMem[3], db, "CREATE VIEW v AS SELECT x FROM t2"); |
|
|
initStrValue(&argvMem[4], db, "t2"); |
|
|
initStrValue(&argvMem[5], db, "t3"); |
|
|
initIntValue(&argvMem[6], db, 0); |
|
|
|
|
|
sqlite3_value *argv[7] = { |
|
|
(sqlite3_value*)&argvMem[0], (sqlite3_value*)&argvMem[1], |
|
|
(sqlite3_value*)&argvMem[2], (sqlite3_value*)&argvMem[3], |
|
|
(sqlite3_value*)&argvMem[4], (sqlite3_value*)&argvMem[5], |
|
|
(sqlite3_value*)&argvMem[6] |
|
|
}; |
|
|
|
|
|
test_renameTableFunc(&ctx, 0, argv); |
|
|
|
|
|
const char *zRes = (const char*)sqlite3_value_text((sqlite3_value*)&ctx.s); |
|
|
TEST_ASSERT_NOT_NULL(zRes); |
|
|
TEST_ASSERT_NOT_NULL(strstr(zRes, "FROM \"t3\"")); |
|
|
TEST_ASSERT_NULL(strstr(zRes, "t2")); |
|
|
|
|
|
sqlite3VdbeMemRelease(&ctx.s); |
|
|
releaseMemArray(argvMem, 7); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameTableFunc_updates_trigger_on_and_body_references(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execOrFail(db, "CREATE TABLE t2(x)"); |
|
|
execOrFail(db, "CREATE TABLE log(y)"); |
|
|
|
|
|
const char *zTrig = |
|
|
"CREATE TRIGGER tr AFTER INSERT ON t2 " |
|
|
"BEGIN " |
|
|
" INSERT INTO log SELECT x FROM t2; " |
|
|
"END"; |
|
|
|
|
|
Mem argvMem[7]; |
|
|
sqlite3_context ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.s.db = db; |
|
|
|
|
|
initStrValue(&argvMem[0], db, "main"); |
|
|
initStrValue(&argvMem[1], db, "trigger"); |
|
|
initStrValue(&argvMem[2], db, "tr"); |
|
|
initStrValue(&argvMem[3], db, zTrig); |
|
|
initStrValue(&argvMem[4], db, "t2"); |
|
|
initStrValue(&argvMem[5], db, "t3"); |
|
|
initIntValue(&argvMem[6], db, 0); |
|
|
|
|
|
sqlite3_value *argv[7] = { |
|
|
(sqlite3_value*)&argvMem[0], (sqlite3_value*)&argvMem[1], |
|
|
(sqlite3_value*)&argvMem[2], (sqlite3_value*)&argvMem[3], |
|
|
(sqlite3_value*)&argvMem[4], (sqlite3_value*)&argvMem[5], |
|
|
(sqlite3_value*)&argvMem[6] |
|
|
}; |
|
|
|
|
|
test_renameTableFunc(&ctx, 0, argv); |
|
|
|
|
|
const char *zRes = (const char*)sqlite3_value_text((sqlite3_value*)&ctx.s); |
|
|
TEST_ASSERT_NOT_NULL(zRes); |
|
|
TEST_ASSERT_NOT_NULL(strstr(zRes, " ON \"t3\"")); |
|
|
TEST_ASSERT_NOT_NULL(strstr(zRes, " FROM \"t3\"")); |
|
|
TEST_ASSERT_NULL(strstr(zRes, "t2")); |
|
|
|
|
|
sqlite3VdbeMemRelease(&ctx.s); |
|
|
releaseMemArray(argvMem, 7); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameTableFunc_invalid_sql_sets_error(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execOrFail(db, "CREATE TABLE t2(x)"); |
|
|
|
|
|
Mem argvMem[7]; |
|
|
sqlite3_context ctx; |
|
|
memset(&ctx, 0, sizeof(ctx)); |
|
|
ctx.s.db = db; |
|
|
|
|
|
initStrValue(&argvMem[0], db, "main"); |
|
|
initStrValue(&argvMem[1], db, "table"); |
|
|
initStrValue(&argvMem[2], db, "t2"); |
|
|
initStrValue(&argvMem[3], db, "SELECT 1"); |
|
|
initStrValue(&argvMem[4], db, "t2"); |
|
|
initStrValue(&argvMem[5], db, "t3"); |
|
|
initIntValue(&argvMem[6], db, 0); |
|
|
|
|
|
sqlite3_value *argv[7] = { |
|
|
(sqlite3_value*)&argvMem[0], (sqlite3_value*)&argvMem[1], |
|
|
(sqlite3_value*)&argvMem[2], (sqlite3_value*)&argvMem[3], |
|
|
(sqlite3_value*)&argvMem[4], (sqlite3_value*)&argvMem[5], |
|
|
(sqlite3_value*)&argvMem[6] |
|
|
}; |
|
|
|
|
|
test_renameTableFunc(&ctx, 0, argv); |
|
|
|
|
|
|
|
|
TEST_ASSERT_NOT_EQUAL(0, ctx.isError); |
|
|
|
|
|
sqlite3VdbeMemRelease(&ctx.s); |
|
|
releaseMemArray(argvMem, 7); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
int main(void){ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_renameTableFunc_rename_table_name_in_create_table); |
|
|
RUN_TEST(test_renameTableFunc_updates_fk_references); |
|
|
RUN_TEST(test_renameTableFunc_updates_view_select_references); |
|
|
RUN_TEST(test_renameTableFunc_updates_trigger_on_and_body_references); |
|
|
RUN_TEST(test_renameTableFunc_invalid_sql_sets_error); |
|
|
return UNITY_END(); |
|
|
} |