|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
extern void test_addConstraintFunc(sqlite3_context*, int, sqlite3_value**); |
|
|
|
|
|
static sqlite3 *gDb = NULL; |
|
|
static const char *gFuncName = "test_addc"; |
|
|
|
|
|
|
|
|
static void register_add_constraint_func(void){ |
|
|
int rc = sqlite3_create_function(gDb, gFuncName, 3, SQLITE_UTF8, 0, |
|
|
test_addConstraintFunc, 0, 0); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_create_function failed"); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char* call_add_constraint(const char *zCreate, const char *zCons, int iCol, |
|
|
int *out_step_rc, int *out_errcode){ |
|
|
char *zSql = sqlite3_mprintf("SELECT %s(%Q,%Q,%d)", gFuncName, zCreate, zCons, iCol); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(zSql, "sqlite3_mprintf returned NULL"); |
|
|
sqlite3_stmt *pStmt = NULL; |
|
|
int rc = sqlite3_prepare_v2(gDb, zSql, -1, &pStmt, 0); |
|
|
sqlite3_free(zSql); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_prepare_v2 failed"); |
|
|
rc = sqlite3_step(pStmt); |
|
|
if( out_step_rc ) *out_step_rc = rc; |
|
|
if( out_errcode ) *out_errcode = sqlite3_errcode(gDb); |
|
|
char *res = NULL; |
|
|
if( rc==SQLITE_ROW ){ |
|
|
const unsigned char *txt = sqlite3_column_text(pStmt, 0); |
|
|
if( txt ){ |
|
|
res = (char*)sqlite3_mprintf("%s", txt); |
|
|
} |
|
|
} |
|
|
sqlite3_finalize(pStmt); |
|
|
return res; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
int rc = sqlite3_open(":memory:", &gDb); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed"); |
|
|
register_add_constraint_func(); |
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
if( gDb ){ |
|
|
sqlite3_close(gDb); |
|
|
gDb = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_adds_to_first_column_simple(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
const char *inSql = "CREATE TABLE t(a, b)"; |
|
|
const char *cons = "CHECK(a>0)"; |
|
|
char *out = call_add_constraint(inSql, cons, 0, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(a CHECK(a>0), b)", out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_adds_to_second_column_simple(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
const char *inSql = "CREATE TABLE t(a, b)"; |
|
|
const char *cons = "DEFAULT 5"; |
|
|
char *out = call_add_constraint(inSql, cons, 1, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(a, b DEFAULT 5)", out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_appends_table_constraint_neg1(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
const char *inSql = "CREATE TABLE t(a INTEGER, b TEXT)"; |
|
|
const char *cons = "UNIQUE(a,b)"; |
|
|
char *out = call_add_constraint(inSql, cons, -1, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_STRING("CREATE TABLE t(a INTEGER, b TEXT, UNIQUE(a,b))", out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void test_addConstraintFunc_handles_comments_and_parens(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
const char *inSql = |
|
|
"CREATE TABLE t( /*c*/ a DECIMAL(10, 5) /*x*/, b TEXT )"; |
|
|
const char *cons = "NOT NULL"; |
|
|
char *out = call_add_constraint(inSql, cons, 0, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_STRING( |
|
|
"CREATE TABLE t( /*c*/ a DECIMAL(10, 5) /*x*/ NOT NULL, b TEXT )", out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_handles_nested_parens_in_defaults(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
const char *inSql = |
|
|
"CREATE TABLE t(a TEXT DEFAULT (printf('x(%d)', 1)), b INT)"; |
|
|
const char *cons = "CHECK(length(a)>0)"; |
|
|
char *out = call_add_constraint(inSql, cons, 0, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NOT_NULL(out); |
|
|
TEST_ASSERT_EQUAL_STRING( |
|
|
"CREATE TABLE t(a TEXT DEFAULT (printf('x(%d)', 1)) CHECK(length(a)>0), b INT)", out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_null_sql_returns_null(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
char *out = call_add_constraint(NULL, "ANY", 0, &stepRc, &err); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ROW, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, err); |
|
|
TEST_ASSERT_NULL(out); |
|
|
sqlite3_free(out); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_out_of_range_column_reports_corrupt(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
|
|
|
const char *inSql = "CREATE TABLE t(a)"; |
|
|
char *out = call_add_constraint(inSql, "ZZZ", 5, &stepRc, &err); |
|
|
TEST_ASSERT(out == NULL); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT, err); |
|
|
} |
|
|
|
|
|
|
|
|
void test_addConstraintFunc_malformed_sql_reports_corrupt(void){ |
|
|
int stepRc = 0, err = 0; |
|
|
|
|
|
const char *inSql = "CREATE TABLE t(a DEFAULT 'unterminated, b INT)"; |
|
|
char *out = call_add_constraint(inSql, "NOT NULL", 0, &stepRc, &err); |
|
|
TEST_ASSERT(out == NULL); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, stepRc); |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_CORRUPT, err); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_addConstraintFunc_adds_to_first_column_simple); |
|
|
RUN_TEST(test_addConstraintFunc_adds_to_second_column_simple); |
|
|
RUN_TEST(test_addConstraintFunc_appends_table_constraint_neg1); |
|
|
RUN_TEST(test_addConstraintFunc_handles_comments_and_parens); |
|
|
RUN_TEST(test_addConstraintFunc_handles_nested_parens_in_defaults); |
|
|
RUN_TEST(test_addConstraintFunc_null_sql_returns_null); |
|
|
RUN_TEST(test_addConstraintFunc_out_of_range_column_reports_corrupt); |
|
|
RUN_TEST(test_addConstraintFunc_malformed_sql_reports_corrupt); |
|
|
return UNITY_END(); |
|
|
} |