sqlite / tests /tests_alter_renameTableFunc.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* External wrapper for the static function under test */
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) {
/* no-op */
}
void tearDown(void) {
/* no-op */
}
/* Helper to execute SQL and assert OK */
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);
}
/* Basic: rename the table name in a CREATE TABLE statement */
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"); /* zDb */
initStrValue(&argvMem[1], db, "table"); /* type */
initStrValue(&argvMem[2], db, "t2"); /* object */
initStrValue(&argvMem[3], db, "CREATE TABLE t2(a, CHECK(a>0))"); /* input SQL */
initStrValue(&argvMem[4], db, "t2"); /* old name */
initStrValue(&argvMem[5], db, "t3"); /* new name */
initIntValue(&argvMem[6], db, 0); /* bTemp */
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);
}
/* Ensure FK references to the old table are updated */
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);
}
/* Ensure table refs inside a CREATE VIEW SELECT are updated */
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);
}
/* Ensure table refs inside CREATE TRIGGER (ON <tbl> and body) are updated */
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);
}
/* Invalid SQL (not starting with CREATE) should set an error code on context */
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"); /* invalid for this function */
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);
/* Expect an error code set on context (SQLITE_CORRUPT_BKPT) */
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();
}