|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
extern void test_renameFixQuotes(Parse *pParse, const char *zDb, int bTemp); |
|
|
|
|
|
|
|
|
static void exec_sql_ok(sqlite3 *db, const char *zSql){ |
|
|
char *zErr = 0; |
|
|
int rc = sqlite3_exec(db, zSql, 0, 0, &zErr); |
|
|
if( rc!=SQLITE_OK ){ |
|
|
|
|
|
const char *msg = zErr ? zErr : "no message"; |
|
|
|
|
|
if( zErr ) sqlite3_free(zErr); |
|
|
TEST_FAIL_MESSAGE(msg); |
|
|
} |
|
|
if( zErr ) sqlite3_free(zErr); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *get_schema_sql(sqlite3 *db, const char *zDb, const char *zName){ |
|
|
char *zSql = sqlite3_mprintf( |
|
|
"SELECT sql FROM \"%w\"." LEGACY_SCHEMA_TABLE " WHERE name=%Q", |
|
|
zDb, zName |
|
|
); |
|
|
sqlite3_stmt *pStmt = 0; |
|
|
char *zOut = 0; |
|
|
int rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
|
|
sqlite3_free(zSql); |
|
|
if( rc!=SQLITE_OK ){ |
|
|
TEST_FAIL_MESSAGE("prepare failed in get_schema_sql"); |
|
|
return 0; |
|
|
} |
|
|
rc = sqlite3_step(pStmt); |
|
|
if( rc==SQLITE_ROW ){ |
|
|
const unsigned char *z = sqlite3_column_text(pStmt, 0); |
|
|
if( z ){ |
|
|
zOut = sqlite3_mprintf("%s", z); |
|
|
}else{ |
|
|
zOut = 0; |
|
|
} |
|
|
}else{ |
|
|
|
|
|
zOut = 0; |
|
|
} |
|
|
sqlite3_finalize(pStmt); |
|
|
return zOut; |
|
|
} |
|
|
|
|
|
|
|
|
static int contains(const char *hay, const char *needle){ |
|
|
if( hay==0 || needle==0 ) return 0; |
|
|
return strstr(hay, needle)!=0; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_renameFixQuotes_updates_only_main_when_bTemp_is_true(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
|
|
|
exec_sql_ok(db, "CREATE TABLE t1(x);"); |
|
|
exec_sql_ok(db, "CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t1 VALUES(\"abc\"); END;"); |
|
|
|
|
|
|
|
|
exec_sql_ok(db, "CREATE TEMP TABLE tt1(x);"); |
|
|
exec_sql_ok(db, "CREATE TEMP TRIGGER trtemp AFTER INSERT ON tt1 BEGIN INSERT INTO tt1 VALUES(\"def\"); END;"); |
|
|
|
|
|
|
|
|
char *zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
char *zTempTrig = get_schema_sql(db, "temp", "trtemp"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zTempTrig); |
|
|
TEST_ASSERT_TRUE_MESSAGE(contains(zMainTrig, "VALUES(\"abc\")"), "Main trigger SQL missing expected double-quoted literal"); |
|
|
TEST_ASSERT_TRUE_MESSAGE(contains(zTempTrig, "VALUES(\"def\")"), "Temp trigger SQL missing expected double-quoted literal"); |
|
|
|
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zTempTrig); |
|
|
|
|
|
|
|
|
Parse sParse; |
|
|
memset(&sParse, 0, sizeof(sParse)); |
|
|
sParse.db = db; |
|
|
test_renameFixQuotes(&sParse, "main", 1); |
|
|
|
|
|
|
|
|
zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
zTempTrig = get_schema_sql(db, "temp", "trtemp"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zTempTrig); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(contains(zMainTrig, "VALUES('abc')"), "Main trigger SQL was not converted to single quotes"); |
|
|
TEST_ASSERT_FALSE_MESSAGE(contains(zMainTrig, "VALUES(\"abc\")"), "Main trigger SQL still contains double-quoted literal"); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(contains(zTempTrig, "VALUES(\"def\")"), "Temp trigger SQL should remain with double-quoted literal when bTemp==1"); |
|
|
TEST_ASSERT_FALSE_MESSAGE(contains(zTempTrig, "VALUES('def')"), "Temp trigger SQL should not be converted when bTemp==1"); |
|
|
|
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zTempTrig); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db)); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameFixQuotes_updates_main_and_temp_when_bTemp_is_false(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
exec_sql_ok(db, "CREATE TABLE t1(x);"); |
|
|
exec_sql_ok(db, "CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t1 VALUES(\"abc\"); END;"); |
|
|
|
|
|
exec_sql_ok(db, "CREATE TEMP TABLE tt1(x);"); |
|
|
exec_sql_ok(db, "CREATE TEMP TRIGGER trtemp AFTER INSERT ON tt1 BEGIN INSERT INTO tt1 VALUES(\"def\"); END;"); |
|
|
|
|
|
|
|
|
char *zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
char *zTempTrig = get_schema_sql(db, "temp", "trtemp"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zTempTrig); |
|
|
TEST_ASSERT_TRUE(contains(zMainTrig, "VALUES(\"abc\")")); |
|
|
TEST_ASSERT_TRUE(contains(zTempTrig, "VALUES(\"def\")")); |
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zTempTrig); |
|
|
|
|
|
|
|
|
Parse sParse; |
|
|
memset(&sParse, 0, sizeof(sParse)); |
|
|
sParse.db = db; |
|
|
test_renameFixQuotes(&sParse, "main", 0); |
|
|
|
|
|
|
|
|
zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
zTempTrig = get_schema_sql(db, "temp", "trtemp"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zTempTrig); |
|
|
|
|
|
TEST_ASSERT_TRUE(contains(zMainTrig, "VALUES('abc')")); |
|
|
TEST_ASSERT_FALSE(contains(zMainTrig, "VALUES(\"abc\")")); |
|
|
|
|
|
TEST_ASSERT_TRUE(contains(zTempTrig, "VALUES('def')")); |
|
|
TEST_ASSERT_FALSE(contains(zTempTrig, "VALUES(\"def\")")); |
|
|
|
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zTempTrig); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db)); |
|
|
} |
|
|
|
|
|
|
|
|
void test_renameFixQuotes_does_not_affect_other_attached_db(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
|
|
|
exec_sql_ok(db, "CREATE TABLE t1(x);"); |
|
|
exec_sql_ok(db, "CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t1 VALUES(\"abc\"); END;"); |
|
|
|
|
|
|
|
|
|
|
|
exec_sql_ok(db, "ATTACH 'test_aux.db' AS aux;"); |
|
|
exec_sql_ok(db, "CREATE TABLE aux.t2(y);"); |
|
|
exec_sql_ok(db, "CREATE TRIGGER aux.tr2 AFTER INSERT ON t2 BEGIN INSERT INTO t2 VALUES(\"ghi\"); END;"); |
|
|
|
|
|
|
|
|
char *zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
char *zAuxTrig = get_schema_sql(db, "aux", "tr2"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zAuxTrig); |
|
|
TEST_ASSERT_TRUE(contains(zMainTrig, "VALUES(\"abc\")")); |
|
|
TEST_ASSERT_TRUE(contains(zAuxTrig, "VALUES(\"ghi\")")); |
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zAuxTrig); |
|
|
|
|
|
|
|
|
Parse sParse; |
|
|
memset(&sParse, 0, sizeof(sParse)); |
|
|
sParse.db = db; |
|
|
test_renameFixQuotes(&sParse, "main", 1); |
|
|
|
|
|
|
|
|
zMainTrig = get_schema_sql(db, "main", "tr1"); |
|
|
zAuxTrig = get_schema_sql(db, "aux", "tr2"); |
|
|
TEST_ASSERT_NOT_NULL(zMainTrig); |
|
|
TEST_ASSERT_NOT_NULL(zAuxTrig); |
|
|
|
|
|
TEST_ASSERT_TRUE(contains(zMainTrig, "VALUES('abc')")); |
|
|
TEST_ASSERT_FALSE(contains(zMainTrig, "VALUES(\"abc\")")); |
|
|
|
|
|
TEST_ASSERT_TRUE(contains(zAuxTrig, "VALUES(\"ghi\")")); |
|
|
TEST_ASSERT_FALSE(contains(zAuxTrig, "VALUES('ghi')")); |
|
|
|
|
|
sqlite3_free(zMainTrig); |
|
|
sqlite3_free(zAuxTrig); |
|
|
|
|
|
|
|
|
exec_sql_ok(db, "DETACH aux;"); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db)); |
|
|
} |
|
|
|
|
|
int main(void){ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_renameFixQuotes_updates_only_main_when_bTemp_is_true); |
|
|
RUN_TEST(test_renameFixQuotes_updates_main_and_temp_when_bTemp_is_false); |
|
|
RUN_TEST(test_renameFixQuotes_does_not_affect_other_attached_db); |
|
|
return UNITY_END(); |
|
|
} |