Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3UniqueConstraint.c245 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Helpers to build minimal Table and Index objects for testing */8 9static void init_parse_and_vdbe(sqlite3 **ppDb, Parse *pParse){10  sqlite3 *db = 0;11  int rc = sqlite3_open(":memory:", &db);12  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13  memset(pParse, 0, sizeof(*pParse));14  pParse->db = db;15  /* Create a Vdbe and attach to Parse to satisfy sqlite3HaltConstraint assert */16  Vdbe *v = sqlite3VdbeCreate(db);17  TEST_ASSERT_NOT_NULL(v);18  pParse->pVdbe = v;19  *ppDb = db;20}21 22static void free_vdbe_and_close(Parse *pParse){23  if( pParse && pParse->pVdbe ){24    sqlite3VdbeDelete(pParse->pVdbe);25    pParse->pVdbe = 0;26  }27  if( pParse && pParse->db ){28    sqlite3_close(pParse->db);29    pParse->db = 0;30  }31}32 33static void make_table(sqlite3 *db, Table *pTab,34                       const char *zTabName,35                       int nCol, const char **azColNames){36  memset(pTab, 0, sizeof(*pTab));37  pTab->zName = sqlite3_mprintf("%s", zTabName);38  TEST_ASSERT_NOT_NULL(pTab->zName);39  pTab->nCol = (i16)nCol;40  pTab->aCol = (Column*)sqlite3_malloc64(sizeof(Column)*nCol);41  TEST_ASSERT_NOT_NULL(pTab->aCol);42  memset(pTab->aCol, 0, sizeof(Column)*nCol);43  for(int i=0; i<nCol; i++){44    pTab->aCol[i].zCnName = sqlite3_mprintf("%s", azColNames[i]);45    TEST_ASSERT_NOT_NULL(pTab->aCol[i].zCnName);46  }47  (void)db; /* db not used here, but kept for symmetry if needed */48}49 50static void free_table(Table *pTab){51  if( pTab->aCol ){52    for(int i=0; i<pTab->nCol; i++){53      if( pTab->aCol[i].zCnName ){54        sqlite3_free(pTab->aCol[i].zCnName);55        pTab->aCol[i].zCnName = 0;56      }57    }58    sqlite3_free(pTab->aCol);59    pTab->aCol = 0;60  }61  if( pTab->zName ){62    sqlite3_free(pTab->zName);63    pTab->zName = 0;64  }65}66 67static void make_index(Index *pIdx, Table *pTab,68                       const char *zName,69                       int nKeyCol, const i16 *aiCols,70                       int idxType, int hasColExpr){71  memset(pIdx, 0, sizeof(*pIdx));72  pIdx->pTable = pTab;73  pIdx->zName = sqlite3_mprintf("%s", zName);74  TEST_ASSERT_NOT_NULL(pIdx->zName);75  pIdx->nKeyCol = (i16)nKeyCol;76  /* For tests, we can point aiColumn to a provided array with static/storage duration.77     We cast away const because struct expects non-const; we do not modify it. */78  pIdx->aiColumn = (i16*)aiCols;79  pIdx->idxType = (u8)idxType;80  pIdx->aColExpr = hasColExpr ? (ExprList*)pTab /* any non-NULL sentinel */ : 0;81}82 83static void free_index(Index *pIdx){84  if( pIdx->zName ){85    sqlite3_free(pIdx->zName);86    pIdx->zName = 0;87  }88  /* aiColumn points to caller-owned memory; not freed here */89}90 91/* Unity hooks */92void setUp(void) {93  /* No global setup */94}95void tearDown(void) {96  /* No global teardown */97}98 99/* Tests */100 101void test_sqlite3UniqueConstraint_nonpk_multi_column_message_and_op_fields(void){102  sqlite3 *db = 0;103  Parse parse;104  init_parse_and_vdbe(&db, &parse);105 106  /* Build table t(a,b) */107  const char *cols[] = {"a","b"};108  Table t;109  make_table(db, &t, "t", 2, cols);110 111  /* Non-PK index on (a,b) */112  static i16 aiCols[2] = {0,1};113  Index idx;114  make_index(&idx, &t, "idx_t_ab", 2, aiCols, SQLITE_IDXTYPE_APPDEF, 0);115 116  int onError = OE_Abort;117  int addr = sqlite3VdbeCurrentAddr(parse.pVdbe);118  sqlite3UniqueConstraint(&parse, onError, &idx);119 120  VdbeOp *op = sqlite3VdbeGetOp(parse.pVdbe, addr);121  TEST_ASSERT_NOT_NULL(op);122  TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);123  TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_UNIQUE, op->p1);124  TEST_ASSERT_EQUAL_INT(onError, op->p2);125  TEST_ASSERT_EQUAL_INT(P5_ConstraintUnique, op->p5);126  TEST_ASSERT_NOT_NULL(op->p4.z);127  TEST_ASSERT_EQUAL_STRING("t.a, t.b", op->p4.z);128 129  free_index(&idx);130  free_table(&t);131  free_vdbe_and_close(&parse);132}133 134void test_sqlite3UniqueConstraint_index_with_expr_uses_index_name(void){135  sqlite3 *db = 0;136  Parse parse;137  init_parse_and_vdbe(&db, &parse);138 139  /* Build table t(a) */140  const char *cols[] = {"a"};141  Table t;142  make_table(db, &t, "t", 1, cols);143 144  /* Index with expressions: force aColExpr non-NULL */145  static i16 aiCols[1] = {0};146  Index idx;147  make_index(&idx, &t, "u1", 1, aiCols, SQLITE_IDXTYPE_APPDEF, 1 /* hasColExpr */);148 149  int onError = OE_Fail;150  int addr = sqlite3VdbeCurrentAddr(parse.pVdbe);151  sqlite3UniqueConstraint(&parse, onError, &idx);152 153  VdbeOp *op = sqlite3VdbeGetOp(parse.pVdbe, addr);154  TEST_ASSERT_NOT_NULL(op);155  TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);156  TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_UNIQUE, op->p1);157  TEST_ASSERT_EQUAL_INT(onError, op->p2);158  TEST_ASSERT_EQUAL_INT(P5_ConstraintUnique, op->p5);159  TEST_ASSERT_NOT_NULL(op->p4.z);160  TEST_ASSERT_EQUAL_STRING("index 'u1'", op->p4.z);161 162  free_index(&idx);163  free_table(&t);164  free_vdbe_and_close(&parse);165}166 167void test_sqlite3UniqueConstraint_primary_key_uses_pk_extended_code(void){168  sqlite3 *db = 0;169  Parse parse;170  init_parse_and_vdbe(&db, &parse);171 172  /* Build table t(id) */173  const char *cols[] = {"id"};174  Table t;175  make_table(db, &t, "t", 1, cols);176 177  /* Primary key index on (id) */178  static i16 aiCols[1] = {0};179  Index idx;180  make_index(&idx, &t, "pk_t", 1, aiCols, SQLITE_IDXTYPE_PRIMARYKEY, 0 /* no expr */);181 182  int onError = OE_Ignore;183  int addr = sqlite3VdbeCurrentAddr(parse.pVdbe);184  sqlite3UniqueConstraint(&parse, onError, &idx);185 186  VdbeOp *op = sqlite3VdbeGetOp(parse.pVdbe, addr);187  TEST_ASSERT_NOT_NULL(op);188  TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);189  TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_PRIMARYKEY, op->p1);190  TEST_ASSERT_EQUAL_INT(onError, op->p2);191  TEST_ASSERT_EQUAL_INT(P5_ConstraintUnique, op->p5);192  TEST_ASSERT_NOT_NULL(op->p4.z);193  TEST_ASSERT_EQUAL_STRING("t.id", op->p4.z);194 195  free_index(&idx);196  free_table(&t);197  free_vdbe_and_close(&parse);198}199 200void test_sqlite3UniqueConstraint_onError_value_is_propagated(void){201  sqlite3 *db = 0;202  Parse parse;203  init_parse_and_vdbe(&db, &parse);204 205  /* Build table t(x) */206  const char *cols[] = {"x"};207  Table t;208  make_table(db, &t, "t", 1, cols);209 210  /* Simple unique index on (x) */211  static i16 aiCols[1] = {0};212  Index idx;213  make_index(&idx, &t, "u_x", 1, aiCols, SQLITE_IDXTYPE_APPDEF, 0);214 215  /* Try several onError values */216  int onErrors[] = {OE_None, OE_Rollback, OE_Abort, OE_Fail, OE_Ignore, OE_Replace};217  const int nErr = (int)(sizeof(onErrors)/sizeof(onErrors[0]));218 219  for(int i=0; i<nErr; i++){220    int addr = sqlite3VdbeCurrentAddr(parse.pVdbe);221    sqlite3UniqueConstraint(&parse, onErrors[i], &idx);222    VdbeOp *op = sqlite3VdbeGetOp(parse.pVdbe, addr);223    TEST_ASSERT_NOT_NULL(op);224    TEST_ASSERT_EQUAL_INT(OP_Halt, op->opcode);225    TEST_ASSERT_EQUAL_INT(SQLITE_CONSTRAINT_UNIQUE, op->p1);226    TEST_ASSERT_EQUAL_INT(onErrors[i], op->p2);227    TEST_ASSERT_EQUAL_INT(P5_ConstraintUnique, op->p5);228    TEST_ASSERT_NOT_NULL(op->p4.z);229    /* For non-expr index, message uses "t.x" */230    TEST_ASSERT_EQUAL_STRING("t.x", op->p4.z);231  }232 233  free_index(&idx);234  free_table(&t);235  free_vdbe_and_close(&parse);236}237 238int main(void) {239  UNITY_BEGIN();240  RUN_TEST(test_sqlite3UniqueConstraint_nonpk_multi_column_message_and_op_fields);241  RUN_TEST(test_sqlite3UniqueConstraint_index_with_expr_uses_index_name);242  RUN_TEST(test_sqlite3UniqueConstraint_primary_key_uses_pk_extended_code);243  RUN_TEST(test_sqlite3UniqueConstraint_onError_value_is_propagated);244  return UNITY_END();245}