sqlite / tests /tests_alter_sqlite3AlterBeginAddColumn.c
AryaWu's picture
Upload folder using huggingface_hub
7510827 verified
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>
/* Globals for tests */
static sqlite3 *gDb = NULL;
/* Unity setup/teardown */
void setUp(void) {
int rc = sqlite3_open(":memory:", &gDb);
TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
TEST_ASSERT_NOT_NULL(gDb);
}
void tearDown(void) {
if (gDb) {
sqlite3_close(gDb);
gDb = NULL;
}
}
/* Helper: create a SrcList with a single table name */
static SrcList* makeSrcList(const char *zName){
Token t;
memset(&t, 0, sizeof(t));
t.z = zName;
t.n = (int)strlen(zName);
return sqlite3SrcListAppend(gDb, 0, &t, 0);
}
/* Helper: initialize a Parse object for our db */
static void initParse(Parse *p){
memset(p, 0, sizeof(*p));
p->db = gDb;
}
/* Test: successful copy for an ordinary table */
void test_sqlite3AlterBeginAddColumn_success_creates_partial_copy(void) {
char *err = 0;
int rc;
/* Create a normal table with multiple columns and defaults */
rc = sqlite3_exec(gDb,
"CREATE TABLE t(a INTEGER DEFAULT 1, b TEXT, c REAL DEFAULT 3.14);",
0, 0, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create failed");
if (err) sqlite3_free(err), err = 0;
/* Find original table metadata */
Table *pOrig = sqlite3FindTable(gDb, "t", "main");
TEST_ASSERT_NOT_NULL(pOrig);
TEST_ASSERT_TRUE(pOrig->nCol > 0);
/* Prepare SrcList and Parse */
SrcList *pSrc = makeSrcList("t");
TEST_ASSERT_NOT_NULL(pSrc);
Parse parse;
initParse(&parse);
TEST_ASSERT_NULL(parse.pNewTable);
/* Call the target function while holding btree mutexes */
sqlite3BtreeEnterAll(gDb);
sqlite3AlterBeginAddColumn(&parse, pSrc);
sqlite3BtreeLeaveAll(gDb);
/* Verify success: no error and pNewTable populated */
TEST_ASSERT_EQUAL_INT(0, parse.nErr);
TEST_ASSERT_NOT_NULL(parse.pNewTable);
Table *pNew = parse.pNewTable;
/* Name must be prefixed as "sqlite_altertab_t" */
TEST_ASSERT_NOT_NULL(pNew->zName);
TEST_ASSERT_EQUAL_STRING("sqlite_altertab_t", pNew->zName);
/* Column count should match */
TEST_ASSERT_EQUAL_INT(pOrig->nCol, pNew->nCol);
/* Column names duplicated and hashes computed */
for(int i=0; i<pNew->nCol; i++){
Column *cOrig = &pOrig->aCol[i];
Column *cNew = &pNew->aCol[i];
TEST_ASSERT_NOT_NULL(cNew->zCnName);
TEST_ASSERT_NOT_NULL(cOrig->zCnName);
/* Ensure duplicated pointer (not aliasing original) and same content */
TEST_ASSERT(cNew->zCnName != cOrig->zCnName);
TEST_ASSERT_EQUAL_STRING(cOrig->zCnName, cNew->zCnName);
/* Ensure hash is set to case-insensitive hash of the name */
TEST_ASSERT_EQUAL_INT(sqlite3StrIHash(cNew->zCnName), cNew->hName);
}
/* Schema and addColOffset should match original */
TEST_ASSERT(pNew->pSchema == pOrig->pSchema);
TEST_ASSERT_TRUE(pNew->u.tab.addColOffset > 0);
TEST_ASSERT_EQUAL_INT(pOrig->u.tab.addColOffset, pNew->u.tab.addColOffset);
/* Default expression list should be duplicated if present on original */
if( pOrig->u.tab.pDfltList ){
TEST_ASSERT_NOT_NULL(pNew->u.tab.pDfltList);
TEST_ASSERT_NOT_NULL(pOrig->u.tab.pDfltList);
TEST_ASSERT(pNew->u.tab.pDfltList != pOrig->u.tab.pDfltList);
TEST_ASSERT_EQUAL_INT(pOrig->u.tab.pDfltList->nExpr,
pNew->u.tab.pDfltList->nExpr);
}
/* New table refcount should be 1 */
TEST_ASSERT_EQUAL_INT(1, pNew->nTabRef);
/* Cleanup: delete the allocated table copy */
sqlite3DeleteTable(gDb, pNew);
parse.pNewTable = 0;
}
/* Test: attempting to alter a view should raise an error */
void test_sqlite3AlterBeginAddColumn_on_view_sets_error(void) {
char *err = 0;
int rc;
rc = sqlite3_exec(gDb, "CREATE VIEW v AS SELECT 1 AS x;", 0, 0, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create view failed");
if (err) sqlite3_free(err), err = 0;
SrcList *pSrc = makeSrcList("v");
TEST_ASSERT_NOT_NULL(pSrc);
Parse parse;
initParse(&parse);
sqlite3BtreeEnterAll(gDb);
sqlite3AlterBeginAddColumn(&parse, pSrc);
sqlite3BtreeLeaveAll(gDb);
TEST_ASSERT_TRUE(parse.nErr > 0);
TEST_ASSERT_NULL(parse.pNewTable);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "Cannot add a column to a view"));
sqlite3DbFree(gDb, parse.zErrMsg);
parse.zErrMsg = 0;
}
/* Test: attempting to alter a system table (sqlite_sequence) should raise an error */
void test_sqlite3AlterBeginAddColumn_on_system_table_sets_error(void) {
char *err = 0;
int rc;
/* Create an AUTOINCREMENT table to ensure sqlite_sequence exists */
rc = sqlite3_exec(gDb,
"CREATE TABLE at(id INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);",
0, 0, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "create autoinc failed");
if (err) sqlite3_free(err), err = 0;
/* Ensure sqlite_sequence exists by inserting a row (usually created at table create, but this is safe) */
rc = sqlite3_exec(gDb, "INSERT INTO at(b) VALUES('x');", 0, 0, &err);
TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, err ? err : "insert failed");
if (err) sqlite3_free(err), err = 0;
/* Now attempt to alter sqlite_sequence */
SrcList *pSrc = makeSrcList("sqlite_sequence");
TEST_ASSERT_NOT_NULL(pSrc);
Parse parse;
initParse(&parse);
sqlite3BtreeEnterAll(gDb);
sqlite3AlterBeginAddColumn(&parse, pSrc);
sqlite3BtreeLeaveAll(gDb);
TEST_ASSERT_TRUE(parse.nErr > 0);
TEST_ASSERT_NULL(parse.pNewTable);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "table sqlite_sequence may not be altered"));
sqlite3DbFree(gDb, parse.zErrMsg);
parse.zErrMsg = 0;
}
/* Test: table not found should set an error and no pNewTable */
void test_sqlite3AlterBeginAddColumn_table_not_found_sets_error(void) {
SrcList *pSrc = makeSrcList("no_such_table_123");
TEST_ASSERT_NOT_NULL(pSrc);
Parse parse;
initParse(&parse);
sqlite3BtreeEnterAll(gDb);
sqlite3AlterBeginAddColumn(&parse, pSrc);
sqlite3BtreeLeaveAll(gDb);
TEST_ASSERT_TRUE(parse.nErr > 0);
TEST_ASSERT_NULL(parse.pNewTable);
TEST_ASSERT_NOT_NULL(parse.zErrMsg);
TEST_ASSERT_NOT_NULL(strstr(parse.zErrMsg, "no such table"));
sqlite3DbFree(gDb, parse.zErrMsg);
parse.zErrMsg = 0;
}
/* Main runner */
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_sqlite3AlterBeginAddColumn_success_creates_partial_copy);
RUN_TEST(test_sqlite3AlterBeginAddColumn_on_view_sets_error);
RUN_TEST(test_sqlite3AlterBeginAddColumn_on_system_table_sets_error);
RUN_TEST(test_sqlite3AlterBeginAddColumn_table_not_found_sets_error);
return UNITY_END();
}