sqlite / tests /tests_alter_dropConstraintFunc.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#include "sqliteInt.h"
#include "unity.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static sqlite3 *gDb = NULL;
/* The wrapper for the static function under test is assumed to be provided. */
extern void test_dropConstraintFunc(sqlite3_context*, int, sqlite3_value**);
/* Register the test function as an SQL scalar function "dropc". */
static void register_dropc(sqlite3 *db){
int rc = sqlite3_create_function(db, "dropc", 2, SQLITE_UTF8, NULL,
test_dropConstraintFunc, NULL, NULL);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_create_function(dropc) failed");
}
/* Helper: call dropc(SQL, TEXT) and capture result or error.
On success, returns 0 and *pzOut is sqlite3_malloc()'d string (caller must sqlite3_free()).
On error, returns 1 and *pzErr is sqlite3_malloc()'d string (caller must sqlite3_free()).
*/
static int call_dropc_text(sqlite3 *db, const char *zSql, const char *zName,
char **pzOut, char **pzErr){
int rc;
sqlite3_stmt *pStmt = NULL;
*pzOut = NULL;
*pzErr = NULL;
rc = sqlite3_prepare_v2(db, "SELECT dropc(?1, ?2)", -1, &pStmt, NULL);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_bind_text(pStmt, 1, zSql, -1, SQLITE_TRANSIENT);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_text(pStmt, 2, zName, -1, SQLITE_TRANSIENT);
}
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
const unsigned char *z = sqlite3_column_text(pStmt, 0);
if( z ){
*pzOut = sqlite3_mprintf("%s", (const char*)z);
}else{
*pzOut = NULL; /* explicit NULL result */
}
sqlite3_finalize(pStmt);
return 0;
}else{
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
return 1;
}
}
/* Helper: call dropc(SQL, INTEGER) and capture result or error. */
static int call_dropc_int(sqlite3 *db, const char *zSql, int iCol,
char **pzOut, char **pzErr){
int rc;
sqlite3_stmt *pStmt = NULL;
*pzOut = NULL;
*pzErr = NULL;
rc = sqlite3_prepare_v2(db, "SELECT dropc(?1, ?2)", -1, &pStmt, NULL);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_bind_text(pStmt, 1, zSql, -1, SQLITE_TRANSIENT);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_int(pStmt, 2, iCol);
}
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
const unsigned char *z = sqlite3_column_text(pStmt, 0);
if( z ){
*pzOut = sqlite3_mprintf("%s", (const char*)z);
}else{
*pzOut = NULL;
}
sqlite3_finalize(pStmt);
return 0;
}else{
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
return 1;
}
}
void setUp(void) {
int rc = sqlite3_open(":memory:", &gDb);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");
register_dropc(gDb);
}
void tearDown(void) {
if( gDb ){
sqlite3_close(gDb);
gDb = NULL;
}
}
/* Drop NOT NULL on first column */
void test_dropConstraintFunc_drop_not_null_first_column(void){
const char *inSql = "CREATE TABLE t1(a NOT NULL,b)";
const char *expect = "CREATE TABLE t1(a ,b)";
char *out = NULL, *err = NULL;
int rc = call_dropc_int(gDb, inSql, 0, &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(expect, out);
sqlite3_free(out);
}
/* Drop NOT NULL on column that is not NOT NULL -> should return original SQL unchanged */
void test_dropConstraintFunc_drop_not_null_noop_when_absent(void){
const char *inSql = "CREATE TABLE t1(a,b)";
char *out = NULL, *err = NULL;
int rc = call_dropc_int(gDb, inSql, 1, &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(inSql, out);
sqlite3_free(out);
}
/* Drop named CHECK table constraint and verify comma handling */
void test_dropConstraintFunc_drop_named_check_table_constraint(void){
const char *inSql = "CREATE TABLE t1(a,CONSTRAINT ck CHECK(a))";
const char *expect = "CREATE TABLE t1(a)";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "ck", &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(expect, out);
sqlite3_free(out);
}
/* Attempt to drop disallowed constraint (PRIMARY KEY) -> error */
void test_dropConstraintFunc_error_on_primary_key(void){
const char *inSql = "CREATE TABLE t1(a,CONSTRAINT pk PRIMARY KEY(a))";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "pk", &out, &err);
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NULL(out);
TEST_ASSERT_NOT_NULL(err);
TEST_ASSERT_EQUAL_STRING("constraint may not be dropped: pk", err);
sqlite3_free(err);
}
/* Named constraint not found -> error */
void test_dropConstraintFunc_error_on_no_such_constraint(void){
const char *inSql = "CREATE TABLE t1(a,CONSTRAINT ck CHECK(a))";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "nosuch", &out, &err);
TEST_ASSERT_EQUAL_INT(1, rc);
TEST_ASSERT_NULL(out);
TEST_ASSERT_NOT_NULL(err);
TEST_ASSERT_EQUAL_STRING("no such constraint: nosuch", err);
sqlite3_free(err);
}
/* Drop named NOT NULL column constraint */
void test_dropConstraintFunc_drop_named_not_null_column_constraint(void){
const char *inSql = "CREATE TABLE t1(a CONSTRAINT nn NOT NULL,b)";
const char *expect = "CREATE TABLE t1(a ,b)";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "nn", &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(expect, out);
sqlite3_free(out);
}
/* Case-insensitive and quoted constraint name matching */
void test_dropConstraintFunc_case_insensitive_and_quoted_name(void){
const char *inSql = "CREATE TABLE t1(a,CONSTRAINT \"MiX\" CHECK(a>0))";
const char *expect = "CREATE TABLE t1(a)";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "mix", &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(expect, out);
sqlite3_free(out);
}
/* Drop only the first of two consecutive CONSTRAINT names */
void test_dropConstraintFunc_drop_first_of_two_constraint_names(void){
const char *inSql = "CREATE TABLE t1(x CONSTRAINT one CONSTRAINT two NOT NULL)";
const char *expect = "CREATE TABLE t1(x CONSTRAINT two NOT NULL)";
char *out = NULL, *err = NULL;
int rc = call_dropc_text(gDb, inSql, "one", &out, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, err ? err : "Unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING(expect, out);
sqlite3_free(out);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_dropConstraintFunc_drop_not_null_first_column);
RUN_TEST(test_dropConstraintFunc_drop_not_null_noop_when_absent);
RUN_TEST(test_dropConstraintFunc_drop_named_check_table_constraint);
RUN_TEST(test_dropConstraintFunc_error_on_primary_key);
RUN_TEST(test_dropConstraintFunc_error_on_no_such_constraint);
RUN_TEST(test_dropConstraintFunc_drop_named_not_null_column_constraint);
RUN_TEST(test_dropConstraintFunc_case_insensitive_and_quoted_name);
RUN_TEST(test_dropConstraintFunc_drop_first_of_two_constraint_names);
return UNITY_END();
}