|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
extern void test_findConstraintFunc(sqlite3_context *ctx, int NotUsed, sqlite3_value **argv); |
|
|
|
|
|
|
|
|
static void udf_findc(sqlite3_context *ctx, int argc, sqlite3_value **argv){ |
|
|
|
|
|
(void)argc; |
|
|
test_findConstraintFunc(ctx, 0, argv); |
|
|
} |
|
|
|
|
|
static void register_findc(sqlite3 *db){ |
|
|
int rc = sqlite3_create_function(db, "findc", 2, SQLITE_UTF8, 0, udf_findc, 0, 0); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_create_function(findc) failed"); |
|
|
} |
|
|
|
|
|
static void assert_findc_result(sqlite3 *db, |
|
|
const char *sqlDef, |
|
|
const char *consName, |
|
|
int expectType, |
|
|
int expectInt){ |
|
|
sqlite3_stmt *stmt = 0; |
|
|
int rc = sqlite3_prepare_v2(db, "SELECT findc(?,?)", -1, &stmt, 0); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "prepare SELECT findc failed"); |
|
|
if( sqlDef ){ |
|
|
rc = sqlite3_bind_text(stmt, 1, sqlDef, -1, SQLITE_TRANSIENT); |
|
|
}else{ |
|
|
rc = sqlite3_bind_null(stmt, 1); |
|
|
} |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "bind #1 failed"); |
|
|
|
|
|
if( consName ){ |
|
|
rc = sqlite3_bind_text(stmt, 2, consName, -1, SQLITE_TRANSIENT); |
|
|
}else{ |
|
|
rc = sqlite3_bind_null(stmt, 2); |
|
|
} |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "bind #2 failed"); |
|
|
|
|
|
rc = sqlite3_step(stmt); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_ROW, rc, "step did not return row"); |
|
|
int gotType = sqlite3_column_type(stmt, 0); |
|
|
TEST_ASSERT_EQUAL_INT(expectType, gotType); |
|
|
if( expectType==SQLITE_INTEGER ){ |
|
|
int got = sqlite3_column_int(stmt, 0); |
|
|
TEST_ASSERT_EQUAL_INT(expectInt, got); |
|
|
} |
|
|
|
|
|
rc = sqlite3_step(stmt); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_DONE, rc, "expected single row"); |
|
|
|
|
|
rc = sqlite3_finalize(stmt); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "finalize failed"); |
|
|
} |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void test_findConstraintFunc_basic_match(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
const char *sql = |
|
|
"CREATE TABLE t (" |
|
|
" a INT," |
|
|
" CONSTRAINT c1 CHECK(a > 0)," |
|
|
" b TEXT" |
|
|
");"; |
|
|
|
|
|
|
|
|
assert_findc_result(db, sql, "c1", SQLITE_INTEGER, 1); |
|
|
|
|
|
assert_findc_result(db, sql, "c2", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_case_insensitive_and_quoted(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
|
|
|
const char *sql = |
|
|
"CREATE TABLE t (" |
|
|
" a INT," |
|
|
" CONSTRAINT \"My Constr\" UNIQUE(a)" |
|
|
");"; |
|
|
|
|
|
assert_findc_result(db, sql, "My Constr", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "my constr", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "MY CONSTR", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "Other", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_bracket_and_backtick_quoted(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
const char *sql1 = |
|
|
"CREATE TABLE t1 (" |
|
|
" a INT," |
|
|
" CONSTRAINT [C-Name] CHECK(a IS NOT NULL)" |
|
|
");"; |
|
|
assert_findc_result(db, sql1, "c-name", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql1, "C-Name", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql1, "other", SQLITE_INTEGER, 0); |
|
|
|
|
|
const char *sql2 = |
|
|
"CREATE TABLE t2 (" |
|
|
" a INT," |
|
|
" CONSTRAINT `bk` CHECK(a > 0)" |
|
|
");"; |
|
|
assert_findc_result(db, sql2, "bk", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql2, "BK", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql2, "xx", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_with_comments_and_nested_parens(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
const char *sql = |
|
|
"/* heading comment */ CREATE /* mid */ TABLE t (\n" |
|
|
" a INT, -- column a\n" |
|
|
" CONSTRAINT /*name*/ \"C 1\" CHECK( (a > 0) AND (a < 10) )\n" |
|
|
"); -- trailer\n"; |
|
|
|
|
|
assert_findc_result(db, sql, "C 1", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "c 1", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "not-there", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_no_named_constraints_returns_0(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
|
|
|
const char *sql = |
|
|
"CREATE TABLE t (" |
|
|
" a INT," |
|
|
" UNIQUE(a)," |
|
|
" PRIMARY KEY(a)" |
|
|
");"; |
|
|
|
|
|
assert_findc_result(db, sql, "anything", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_no_left_paren_in_sql_returns_0(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
|
|
|
const char *sql = "DROP TABLE t;"; |
|
|
assert_findc_result(db, sql, "c1", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_null_arguments_return_null(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
|
|
|
assert_findc_result(db, NULL, "c1", SQLITE_NULL, 0); |
|
|
|
|
|
|
|
|
const char *sql = |
|
|
"CREATE TABLE t ( a INT, CONSTRAINT c1 CHECK(a>0) );"; |
|
|
assert_findc_result(db, sql, NULL, SQLITE_NULL, 0); |
|
|
|
|
|
|
|
|
assert_findc_result(db, NULL, NULL, SQLITE_NULL, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
static void test_findConstraintFunc_multiple_constraints_both_detected(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
register_findc(db); |
|
|
|
|
|
const char *sql = |
|
|
"CREATE TABLE t (" |
|
|
" a INT, b INT," |
|
|
" CONSTRAINT cA CHECK(a>0)," |
|
|
" CONSTRAINT cB UNIQUE(b)" |
|
|
");"; |
|
|
|
|
|
assert_findc_result(db, sql, "cA", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "ca", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "cB", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "cb", SQLITE_INTEGER, 1); |
|
|
assert_findc_result(db, sql, "nope", SQLITE_INTEGER, 0); |
|
|
|
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
int main(void){ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_findConstraintFunc_basic_match); |
|
|
RUN_TEST(test_findConstraintFunc_case_insensitive_and_quoted); |
|
|
RUN_TEST(test_findConstraintFunc_bracket_and_backtick_quoted); |
|
|
RUN_TEST(test_findConstraintFunc_with_comments_and_nested_parens); |
|
|
RUN_TEST(test_findConstraintFunc_no_named_constraints_returns_0); |
|
|
RUN_TEST(test_findConstraintFunc_no_left_paren_in_sql_returns_0); |
|
|
RUN_TEST(test_findConstraintFunc_null_arguments_return_null); |
|
|
RUN_TEST(test_findConstraintFunc_multiple_constraints_both_detected); |
|
|
return UNITY_END(); |
|
|
} |