File size: 5,746 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 |
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>
/* Some builds may not expose the prototype in headers, so declare here. */
extern void sqlite3AlterFunctions(sqlite3*);
static char* call_rename_quotefix(sqlite3 *db, const char *zDb, const char *zInput, int *pRc){
char *zSQL = sqlite3_mprintf("SELECT sqlite_rename_quotefix(%Q,%Q)", zDb, zInput);
sqlite3_stmt *pStmt = 0;
int rc = sqlite3_prepare_v2(db, zSQL, -1, &pStmt, 0);
sqlite3_free(zSQL);
if( rc!=SQLITE_OK ){
if(pRc) *pRc = rc;
return NULL;
}
rc = sqlite3_step(pStmt);
char *zRes = NULL;
if( rc==SQLITE_ROW ){
const unsigned char *z = sqlite3_column_text(pStmt, 0);
if( z ){
zRes = sqlite3_mprintf("%s", z);
}
rc = SQLITE_OK;
}
int rc2 = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK && rc2!=SQLITE_OK ) rc = rc2;
if( pRc ) *pRc = rc;
return zRes;
}
static void execSQL(sqlite3 *db, const char *zSql){
char *zErr = 0;
int rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
TEST_ASSERT_EQUAL_MESSAGE(SQLITE_OK, rc, zErr ? zErr : "execSQL failed");
if( zErr ) sqlite3_free(zErr);
}
void setUp(void) {
/* no-op */
}
void tearDown(void) {
/* no-op */
}
void test_renameQuotefixFunc_view_basic(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
execSQL(db, "CREATE TABLE t1(a, b, c);");
const char *inSql = "CREATE VIEW v1 AS SELECT \"a\", \"string\" FROM t1";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("CREATE VIEW v1 AS SELECT \"a\", 'string' FROM t1", out);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_table_check_expr(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
const char *inSql = "CREATE TABLE t2(a CHECK(\"ok\" IN (\"ok\",\"bad\")))";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t2(a CHECK('ok' IN ('ok','bad')))", out);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_index_partial_where(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
execSQL(db, "CREATE TABLE t1(a, b);");
const char *inSql = "CREATE INDEX i1 ON t1(a) WHERE b=\"str\"";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("CREATE INDEX i1 ON t1(a) WHERE b='str'", out);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_trigger_when_and_step(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
execSQL(db, "CREATE TABLE t1(a, b);");
const char *inSql =
"CREATE TRIGGER tr1 AFTER INSERT ON t1 "
"WHEN \"string\"='x' BEGIN UPDATE t1 SET a=1 WHERE b=\"y\"; END";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(
"CREATE TRIGGER tr1 AFTER INSERT ON t1 "
"WHEN 'string'='x' BEGIN UPDATE t1 SET a=1 WHERE b='y'; END",
out
);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_adjacent_single_quote_alias_spacing(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
execSQL(db, "CREATE TABLE t1(a);");
/* Ensure that a space is inserted to avoid adjacent literal concatenation */
const char *inSql = "CREATE VIEW v2 AS SELECT \"string\"'alias' FROM t1";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("CREATE VIEW v2 AS SELECT 'string' 'alias' FROM t1", out);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_writable_schema_returns_input_on_error(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
execSQL(db, "PRAGMA writable_schema=ON;");
const char *inSql = "CREATE VIEW v_bad AS SELECT \"x\" FROM nosuchtable";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
/* With writable_schema=ON and an error during processing, the original input is returned */
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(inSql, out);
sqlite3_free(out);
sqlite3_close(db);
}
void test_renameQuotefixFunc_error_without_writable_schema(void){
sqlite3 *db = 0; int rc;
TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));
sqlite3AlterFunctions(db);
const char *inSql = "CREATE VIEW v_bad AS SELECT \"x\" FROM nosuchtable";
char *out = call_rename_quotefix(db, "main", inSql, &rc);
/* Expect an error (no row) because name resolution fails and writable_schema is OFF */
TEST_ASSERT_NULL(out);
TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);
sqlite3_close(db);
}
int main(void){
UNITY_BEGIN();
RUN_TEST(test_renameQuotefixFunc_view_basic);
RUN_TEST(test_renameQuotefixFunc_table_check_expr);
RUN_TEST(test_renameQuotefixFunc_index_partial_where);
RUN_TEST(test_renameQuotefixFunc_trigger_when_and_step);
RUN_TEST(test_renameQuotefixFunc_adjacent_single_quote_alias_spacing);
RUN_TEST(test_renameQuotefixFunc_writable_schema_returns_input_on_error);
RUN_TEST(test_renameQuotefixFunc_error_without_writable_schema);
return UNITY_END();
} |