| #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(); |
| } |