|
|
#include "sqliteInt.h" |
|
|
#include "unity.h" |
|
|
#include <string.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static SrcList *makeSrcListOne(sqlite3 *db, const char *zDb, const char *zTab){ |
|
|
|
|
|
SrcList *p = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList)); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p, "sqlite3DbMallocZero failed creating SrcList"); |
|
|
p->nAlloc = 1; |
|
|
p->nSrc = 1; |
|
|
p->a[0].zName = sqlite3DbStrDup(db, zTab); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zName, "sqlite3DbStrDup failed for table name"); |
|
|
if( zDb ){ |
|
|
p->a[0].zDatabase = sqlite3DbStrDup(db, zDb); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p->a[0].zDatabase, "sqlite3DbStrDup failed for database name"); |
|
|
} |
|
|
return p; |
|
|
} |
|
|
|
|
|
|
|
|
static Token makeToken(const char *z){ |
|
|
Token t; |
|
|
t.z = z; |
|
|
t.n = (int)strlen(z); |
|
|
return t; |
|
|
} |
|
|
|
|
|
|
|
|
static void initParse(Parse *pParse, sqlite3 *db){ |
|
|
memset(pParse, 0, sizeof(*pParse)); |
|
|
pParse->db = db; |
|
|
} |
|
|
|
|
|
|
|
|
static void execSqlOk(sqlite3 *db, const char *zSql){ |
|
|
int rc = sqlite3_exec(db, zSql, 0, 0, 0); |
|
|
if( rc!=SQLITE_OK ){ |
|
|
const char *err = sqlite3_errmsg(db); |
|
|
char msg[512]; |
|
|
sqlite3_snprintf(sizeof(msg), msg, "SQL exec failed (%d): %s; SQL: %s", rc, err ? err : "(null)", zSql); |
|
|
TEST_FAIL_MESSAGE(msg); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropConstraint_nonexistent_table(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
Parse p; |
|
|
initParse(&p, db); |
|
|
|
|
|
SrcList *pSrc = makeSrcListOne(db, NULL, "nosuchtable"); |
|
|
Token cons = makeToken("c1"); |
|
|
|
|
|
sqlite3AlterDropConstraint(&p, pSrc, &cons, 0); |
|
|
|
|
|
TEST_ASSERT_NULL_MESSAGE(p.pVdbe, "VDBE should not be created for nonexistent table"); |
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "An error should be recorded for nonexistent table"); |
|
|
|
|
|
sqlite3SrcListDelete(db, pSrc); |
|
|
if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropConstraint_drop_not_null_on_existing_col_generates_code(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execSqlOk(db, "CREATE TABLE t1(a INTEGER NOT NULL, b TEXT);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(&p, db); |
|
|
|
|
|
SrcList *pSrc = makeSrcListOne(db, NULL, "t1"); |
|
|
Token col = makeToken("a"); |
|
|
|
|
|
sqlite3AlterDropConstraint(&p, pSrc, 0, &col); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "VDBE should be created for valid DROP NOT NULL operation"); |
|
|
|
|
|
|
|
|
sqlite3SrcListDelete(db, pSrc); |
|
|
if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropConstraint_nonexistent_column_reports_error(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
execSqlOk(db, "CREATE TABLE t2(a INTEGER NOT NULL, b TEXT);"); |
|
|
|
|
|
Parse p; |
|
|
initParse(&p, db); |
|
|
|
|
|
SrcList *pSrc = makeSrcListOne(db, NULL, "t2"); |
|
|
Token col = makeToken("no_such_col"); |
|
|
|
|
|
sqlite3AlterDropConstraint(&p, pSrc, 0, &col); |
|
|
|
|
|
TEST_ASSERT_NULL_MESSAGE(p.pVdbe, "VDBE should not be created when column does not exist"); |
|
|
TEST_ASSERT_TRUE_MESSAGE(p.nErr>0, "An error should be recorded for nonexistent column"); |
|
|
|
|
|
sqlite3SrcListDelete(db, pSrc); |
|
|
if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
|
|
|
void test_sqlite3AlterDropConstraint_drop_named_constraint_generates_code(void){ |
|
|
sqlite3 *db = 0; |
|
|
TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db)); |
|
|
|
|
|
execSqlOk(db, "CREATE TABLE t3(x INT, y INT, CONSTRAINT c1 CHECK(x>0));"); |
|
|
|
|
|
Parse p; |
|
|
initParse(&p, db); |
|
|
|
|
|
SrcList *pSrc = makeSrcListOne(db, NULL, "t3"); |
|
|
Token cons = makeToken("c1"); |
|
|
|
|
|
sqlite3AlterDropConstraint(&p, pSrc, &cons, 0); |
|
|
|
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(p.pVdbe, "VDBE should be created for valid DROP CONSTRAINT operation"); |
|
|
|
|
|
sqlite3SrcListDelete(db, pSrc); |
|
|
if( p.pVdbe ) sqlite3VdbeDelete(p.pVdbe); |
|
|
sqlite3_close(db); |
|
|
} |
|
|
|
|
|
int main(void){ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_sqlite3AlterDropConstraint_nonexistent_table); |
|
|
RUN_TEST(test_sqlite3AlterDropConstraint_drop_not_null_on_existing_col_generates_code); |
|
|
RUN_TEST(test_sqlite3AlterDropConstraint_nonexistent_column_reports_error); |
|
|
RUN_TEST(test_sqlite3AlterDropConstraint_drop_named_constraint_generates_code); |
|
|
return UNITY_END(); |
|
|
} |