File size: 7,092 Bytes
7510827 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* Wrapper for the static function (provided by build system as per instructions) */
extern void test_renameColumnFunc(sqlite3_context *context, int NotUsed, sqlite3_value **argv);
/* Unity setup/teardown */
void setUp(void) {
/* no-op */
}
void tearDown(void) {
/* no-op */
}
/* Helpers to build sqlite3_value* arguments */
static sqlite3_value *make_text_value(sqlite3 *db, const char *z){
Mem *p = sqlite3ValueNew(db);
if( z ){
sqlite3VdbeMemSetStr(p, z, (int)strlen(z), SQLITE_UTF8, SQLITE_TRANSIENT);
}else{
sqlite3VdbeMemSetNull(p);
}
return (sqlite3_value*)p;
}
static sqlite3_value *make_int_value(sqlite3 *db, int v){
Mem *p = sqlite3ValueNew(db);
sqlite3VdbeMemSetInt64(p, (i64)v);
return (sqlite3_value*)p;
}
static void free_value(sqlite3 *db, sqlite3_value *v){
if( v ){
sqlite3ValueFree((Mem*)v);
}
}
/* Execute SQL and assert success */
static void exec_ok(sqlite3 *db, const char *zSql){
char *zErr = 0;
int rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
/* Provide diagnostic if fails */
fprintf(stderr, "exec error: rc=%d sql=[%s] err=[%s]\n", rc, zSql, zErr ? zErr : "(null)");
}
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_exec failed");
sqlite3_free(zErr);
}
/* Call the wrapper and return heap copy of result text, or NULL if no text result */
static char *call_rename(
sqlite3 *db,
const char *zSql, /* argv[0] */
const char *zType, /* argv[1] */
const char *zObject, /* argv[2] */
const char *zDb, /* argv[3] */
const char *zTable, /* argv[4] */
int iCol, /* argv[5] */
const char *zNew, /* argv[6] */
int bQuote, /* argv[7] */
int bTemp /* argv[8] */
){
sqlite3_value *argv[9];
sqlite3_context ctx;
Mem out;
char *zRet = NULL;
/* Prepare argv[] */
argv[0] = make_text_value(db, zSql);
argv[1] = make_text_value(db, zType);
argv[2] = make_text_value(db, zObject);
argv[3] = make_text_value(db, zDb);
argv[4] = make_text_value(db, zTable);
argv[5] = make_int_value(db, iCol);
argv[6] = make_text_value(db, zNew);
argv[7] = make_int_value(db, bQuote);
argv[8] = make_int_value(db, bTemp);
/* Prepare context and result container */
memset(&ctx, 0, sizeof(ctx));
memset(&out, 0, sizeof(out));
out.db = db;
sqlite3VdbeMemZero(&out);
ctx.db = db;
ctx.pOut = &out;
/* Invoke the function */
test_renameColumnFunc(&ctx, 9, argv);
/* Collect result text if any */
if( (out.flags & MEM_Str)!=0 && out.z!=0 ){
zRet = sqlite3_mprintf("%s", out.z);
}else{
zRet = NULL;
}
/* Cleanup */
sqlite3VdbeMemRelease(&out);
for(int i=0;i<9;i++) free_value(db, argv[i]);
return zRet;
}
/* Test: Basic table column rename, unquoted original, no forced quoting */
void test_renameColumnFunc_table_basic_unquoted_noquote(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b, c)");
const char *zSql = "CREATE TABLE t(a, b, c)";
char *zOut = call_rename(db, zSql, "table", "t", "main", "t", 1, "d", 0, 0);
TEST_ASSERT_NOT_NULL(zOut);
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(a, d, c)", zOut);
sqlite3_free(zOut);
sqlite3_close(db);
}
/* Test: Basic table column rename, unquoted original, forced quoting of new name */
void test_renameColumnFunc_table_basic_unquoted_forcequote(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b, c)");
const char *zSql = "CREATE TABLE t(a, b, c)";
char *zOut = call_rename(db, zSql, "table", "t", "main", "t", 1, "d", 1, 0);
TEST_ASSERT_NOT_NULL(zOut);
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(a, \"d\", c)", zOut);
sqlite3_free(zOut);
sqlite3_close(db);
}
/* Test: Table column rename when original identifier is quoted; bQuote=0 should still quote */
void test_renameColumnFunc_table_original_quoted(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(\"a\", \"b\", c)");
const char *zSql = "CREATE TABLE t(\"a\", \"b\", c)";
char *zOut = call_rename(db, zSql, "table", "t", "main", "t", 1, "x", 0, 0);
TEST_ASSERT_NOT_NULL(zOut);
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(\"a\", \"x\", c)", zOut);
sqlite3_free(zOut);
sqlite3_close(db);
}
/* Test: View rewrite - rename column referenced by view select list */
void test_renameColumnFunc_view_rewrite_select_list(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b)");
const char *zSql = "CREATE VIEW v AS SELECT a, b FROM t";
char *zOut = call_rename(db, zSql, "view", "v", "main", "t", 1, "d", 0, 0);
TEST_ASSERT_NOT_NULL(zOut);
TEST_ASSERT_EQUAL_STRING("CREATE VIEW v AS SELECT a, d FROM t", zOut);
sqlite3_free(zOut);
sqlite3_close(db);
}
/* Test: Trigger rewrite - rename in UPDATE OF clause */
void test_renameColumnFunc_trigger_update_of_clause(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b)");
const char *zSql =
"CREATE TRIGGER tr AFTER UPDATE OF b ON t BEGIN SELECT 1; END";
char *zOut = call_rename(db, zSql, "trigger", "tr", "main", "t", 1, "d", 0, 0);
TEST_ASSERT_NOT_NULL(zOut);
TEST_ASSERT_EQUAL_STRING(
"CREATE TRIGGER tr AFTER UPDATE OF d ON t BEGIN SELECT 1; END", zOut
);
sqlite3_free(zOut);
sqlite3_close(db);
}
/* Test: Invalid column index (out of range) - expect no result (NULL) */
void test_renameColumnFunc_invalid_col_index_no_result(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b)");
const char *zSql = "CREATE TABLE t(a, b)";
/* iCol==2 is out of range for 2-column table (0,1 valid) */
char *zOut = call_rename(db, zSql, "table", "t", "main", "t", 2, "d", 0, 0);
TEST_ASSERT_NULL(zOut);
sqlite3_free(zOut); /* safe even if NULL */
sqlite3_close(db);
}
/* Test: Non-existent table name - expect no result (NULL) */
void test_renameColumnFunc_wrong_table_no_result(void){
sqlite3 *db = 0;
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));
exec_ok(db, "CREATE TABLE t(a, b)");
const char *zSql = "CREATE TABLE t(a, b)";
char *zOut = call_rename(db, zSql, "table", "t", "main", "nope", 1, "d", 0, 0);
TEST_ASSERT_NULL(zOut);
sqlite3_free(zOut);
sqlite3_close(db);
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameColumnFunc_table_basic_unquoted_noquote);
RUN_TEST(test_renameColumnFunc_table_basic_unquoted_forcequote);
RUN_TEST(test_renameColumnFunc_table_original_quoted);
RUN_TEST(test_renameColumnFunc_view_rewrite_select_list);
RUN_TEST(test_renameColumnFunc_trigger_update_of_clause);
RUN_TEST(test_renameColumnFunc_invalid_col_index_no_result);
RUN_TEST(test_renameColumnFunc_wrong_table_no_result);
return UNITY_END();
} |