Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3CreateForeignKey.c316 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Helpers to construct test data */7 8static Table* makeTableWithCols(sqlite3 *db, Schema *pSchema, const char **azCol, int nCol){9  Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));10  TEST_ASSERT_NOT_NULL(pTab);11  pTab->pSchema = pSchema;12  pTab->nCol = nCol;13  pTab->tabFlags = 0; /* Ordinary table */14  pTab->u.tab.pFKey = 0;15 16  pTab->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nCol);17  TEST_ASSERT_NOT_NULL(pTab->aCol);18  for(int i=0; i<nCol; i++){19    pTab->aCol[i].zCnName = sqlite3DbStrDup(db, azCol[i]);20    TEST_ASSERT_NOT_NULL(pTab->aCol[i].zCnName);21  }22  return pTab;23}24 25/* Construct a minimal ExprList with n items, setting zEName strings if names provided.26   Items' pExpr fields are left NULL since sqlite3CreateForeignKey only uses zEName and nExpr. */27static ExprList* makeExprList(sqlite3 *db, const char **azName, int n){28  if( n<=0 ) return 0;29  int nByte = sizeof(ExprList) + (n-1)*(int)sizeof(struct ExprList_item);30  ExprList *pList = (ExprList*)sqlite3DbMallocZero(db, nByte);31  TEST_ASSERT_NOT_NULL(pList);32  pList->nExpr = n;33  pList->nAlloc = n;34  for(int i=0; i<n; i++){35    if( azName && azName[i] ){36      pList->a[i].zEName = sqlite3DbStrDup(db, azName[i]);37      TEST_ASSERT_NOT_NULL(pList->a[i].zEName);38    }else{39      pList->a[i].zEName = 0;40    }41    pList->a[i].pExpr = 0;42  }43  return pList;44}45 46static void freeTableAndFKeys(sqlite3 *db, Table *pTab){47  if( !pTab ) return;48  /* Remove and free all FKeys linked to this table and from schema hash */49  sqlite3FkDelete(db, pTab);50  /* Free column name strings and array, then table itself */51  if( pTab->aCol ){52    for(int i=0; i<pTab->nCol; i++){53      if( pTab->aCol[i].zCnName ){54        sqlite3DbFree(db, pTab->aCol[i].zCnName);55      }56    }57    sqlite3DbFree(db, pTab->aCol);58  }59  sqlite3DbFree(db, pTab);60}61 62/* Unity setUp/tearDown */63void setUp(void) {64  /* Nothing global to set up */65}66void tearDown(void) {67  /* Nothing global to tear down */68}69 70/* Tests */71 72void test_sqlite3CreateForeignKey_basic_singlecol_lastcol(void){73  sqlite3 *db = 0;74  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));75  Schema *pSchema = db->aDb[0].pSchema;76 77  const char *cols[] = {"c1","c2"};78  Table *pTab = makeTableWithCols(db, pSchema, cols, 2);79 80  Parse pParse;81  memset(&pParse, 0, sizeof(pParse));82  pParse.db = db;83  pParse.pNewTable = pTab;84 85  Token tTo;86  tTo.z = "parent";87  tTo.n = (int)strlen(tTo.z);88 89  int flags = ((int)0x77 << 8) | 0x55; /* ON UPDATE=0x77, ON DELETE=0x55 */90  sqlite3CreateForeignKey(&pParse, 0, &tTo, 0, flags);91 92  FKey *pFk = pTab->u.tab.pFKey;93  TEST_ASSERT_NOT_NULL(pFk);94  TEST_ASSERT_EQUAL_PTR(pTab, pFk->pFrom);95  TEST_ASSERT_EQUAL_INT(1, pFk->nCol);96  TEST_ASSERT_EQUAL_INT(pTab->nCol - 1, pFk->aCol[0].iFrom);97  TEST_ASSERT_EQUAL_UINT8(0x55, pFk->aAction[0]);98  TEST_ASSERT_EQUAL_UINT8(0x77, pFk->aAction[1]);99  TEST_ASSERT_EQUAL_STRING("parent", pFk->zTo);100 101  /* Verify it is visible from the schema hash */102  FKey *pHead = (FKey*)sqlite3HashFind(&pSchema->fkeyHash, pFk->zTo);103  TEST_ASSERT_EQUAL_PTR(pFk, pHead);104 105  freeTableAndFKeys(db, pTab);106  sqlite3_close(db);107}108 109void test_sqlite3CreateForeignKey_mismatch_counts_error(void){110  sqlite3 *db = 0;111  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));112  Schema *pSchema = db->aDb[0].pSchema;113 114  const char *cols[] = {"a","b","c"};115  Table *pTab = makeTableWithCols(db, pSchema, cols, 3);116 117  Parse pParse;118  memset(&pParse, 0, sizeof(pParse));119  pParse.db = db;120  pParse.pNewTable = pTab;121 122  Token tTo;123  tTo.z = "parent2";124  tTo.n = (int)strlen(tTo.z);125 126  /* from-list size 2, to-list size 1 -> mismatch */127  ExprList *pFrom = makeExprList(db, 0, 2);128  ExprList *pTo = makeExprList(db, 0, 1);129 130  sqlite3CreateForeignKey(&pParse, pFrom, &tTo, pTo, 0);131 132  TEST_ASSERT_NULL(pTab->u.tab.pFKey);133  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, pParse.rc);134 135  freeTableAndFKeys(db, pTab);136  sqlite3_close(db);137}138 139void test_sqlite3CreateForeignKey_unknown_fromcol_error(void){140  sqlite3 *db = 0;141  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));142  Schema *pSchema = db->aDb[0].pSchema;143 144  const char *cols[] = {"x","y"};145  Table *pTab = makeTableWithCols(db, pSchema, cols, 2);146 147  Parse pParse;148  memset(&pParse, 0, sizeof(pParse));149  pParse.db = db;150  pParse.pNewTable = pTab;151 152  Token tTo;153  tTo.z = "p";154  tTo.n = (int)strlen(tTo.z);155 156  const char *fromNames[] = {"does_not_exist"};157  ExprList *pFrom = makeExprList(db, fromNames, 1);158 159  sqlite3CreateForeignKey(&pParse, pFrom, &tTo, 0, 0);160 161  TEST_ASSERT_NULL(pTab->u.tab.pFKey);162  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, pParse.rc);163 164  freeTableAndFKeys(db, pTab);165  sqlite3_close(db);166}167 168void test_sqlite3CreateForeignKey_pFromCol_null_pToCol_multi_error(void){169  sqlite3 *db = 0;170  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));171  Schema *pSchema = db->aDb[0].pSchema;172 173  const char *cols[] = {"id"};174  Table *pTab = makeTableWithCols(db, pSchema, cols, 1);175 176  Parse pParse;177  memset(&pParse, 0, sizeof(pParse));178  pParse.db = db;179  pParse.pNewTable = pTab;180 181  Token tTo;182  tTo.z = "parent3";183  tTo.n = (int)strlen(tTo.z);184 185  const char *toNames[] = {"pcol1","pcol2"};186  ExprList *pTo = makeExprList(db, toNames, 2);187 188  sqlite3CreateForeignKey(&pParse, 0, &tTo, pTo, 0);189 190  TEST_ASSERT_NULL(pTab->u.tab.pFKey);191  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, pParse.rc);192 193  freeTableAndFKeys(db, pTab);194  sqlite3_close(db);195}196 197void test_sqlite3CreateForeignKey_multi_col_with_to_names(void){198  sqlite3 *db = 0;199  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));200  Schema *pSchema = db->aDb[0].pSchema;201 202  const char *cols[] = {"cA","cB","cC"};203  Table *pTab = makeTableWithCols(db, pSchema, cols, 3);204 205  Parse pParse;206  memset(&pParse, 0, sizeof(pParse));207  pParse.db = db;208  pParse.pNewTable = pTab;209 210  Token tTo;211  tTo.z = "parent4";212  tTo.n = (int)strlen(tTo.z);213 214  const char *fromNames[] = {"cB","cA"};215  const char *toNames[] = {"pB","pA"};216  ExprList *pFrom = makeExprList(db, fromNames, 2);217  ExprList *pTo = makeExprList(db, toNames, 2);218 219  sqlite3CreateForeignKey(&pParse, pFrom, &tTo, pTo, 0);220 221  FKey *pFk = pTab->u.tab.pFKey;222  TEST_ASSERT_NOT_NULL(pFk);223  TEST_ASSERT_EQUAL_INT(2, pFk->nCol);224  /* cB is index 1, cA is index 0 */225  TEST_ASSERT_EQUAL_INT(1, pFk->aCol[0].iFrom);226  TEST_ASSERT_EQUAL_INT(0, pFk->aCol[1].iFrom);227  TEST_ASSERT_NOT_NULL(pFk->aCol[0].zCol);228  TEST_ASSERT_NOT_NULL(pFk->aCol[1].zCol);229  TEST_ASSERT_EQUAL_STRING("pB", pFk->aCol[0].zCol);230  TEST_ASSERT_EQUAL_STRING("pA", pFk->aCol[1].zCol);231 232  freeTableAndFKeys(db, pTab);233  sqlite3_close(db);234}235 236void test_sqlite3CreateForeignKey_multiple_chain_same_parent(void){237  sqlite3 *db = 0;238  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));239  Schema *pSchema = db->aDb[0].pSchema;240 241  const char *cols[] = {"a","b","c"};242  Table *pTab = makeTableWithCols(db, pSchema, cols, 3);243 244  Parse pParse;245  memset(&pParse, 0, sizeof(pParse));246  pParse.db = db;247  pParse.pNewTable = pTab;248 249  Token tTo;250  tTo.z = "parent_chain";251  tTo.n = (int)strlen(tTo.z);252 253  /* First FK uses last column (c) */254  sqlite3CreateForeignKey(&pParse, 0, &tTo, 0, 0x01 | (0x02<<8));255  FKey *pFirst = pTab->u.tab.pFKey;256  TEST_ASSERT_NOT_NULL(pFirst);257  TEST_ASSERT_EQUAL_STRING("parent_chain", pFirst->zTo);258 259  /* Second FK uses explicit column 'a' */260  const char *fromNames[] = {"a"};261  ExprList *pFrom = makeExprList(db, fromNames, 1);262  sqlite3CreateForeignKey(&pParse, pFrom, &tTo, 0, 0x03 | (0x04<<8));263  FKey *pSecond = pTab->u.tab.pFKey;264  TEST_ASSERT_NOT_NULL(pSecond);265  TEST_ASSERT_NOT_EQUAL(pSecond, pFirst);266  TEST_ASSERT_EQUAL_PTR(pFirst, pSecond->pNextFrom);267 268  /* Schema hash head should now be pSecond, and linkage between them maintained */269  FKey *pHead = (FKey*)sqlite3HashFind(&pSchema->fkeyHash, "parent_chain");270  TEST_ASSERT_EQUAL_PTR(pSecond, pHead);271  TEST_ASSERT_EQUAL_PTR(pFirst, pSecond->pNextTo);272  TEST_ASSERT_EQUAL_PTR(pSecond, pFirst->pPrevTo);273 274  freeTableAndFKeys(db, pTab);275  sqlite3_close(db);276}277 278void test_sqlite3CreateForeignKey_parent_name_dequote(void){279  sqlite3 *db = 0;280  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));281  Schema *pSchema = db->aDb[0].pSchema;282 283  const char *cols[] = {"onlycol"};284  Table *pTab = makeTableWithCols(db, pSchema, cols, 1);285 286  Parse pParse;287  memset(&pParse, 0, sizeof(pParse));288  pParse.db = db;289  pParse.pNewTable = pTab;290 291  Token tTo;292  tTo.z = "\"ParEnt\"";293  tTo.n = (int)strlen(tTo.z);294 295  sqlite3CreateForeignKey(&pParse, 0, &tTo, 0, 0);296 297  FKey *pFk = pTab->u.tab.pFKey;298  TEST_ASSERT_NOT_NULL(pFk);299  /* Name should be dequoted */300  TEST_ASSERT_EQUAL_STRING("ParEnt", pFk->zTo);301 302  freeTableAndFKeys(db, pTab);303  sqlite3_close(db);304}305 306int main(void){307  UNITY_BEGIN();308  RUN_TEST(test_sqlite3CreateForeignKey_basic_singlecol_lastcol);309  RUN_TEST(test_sqlite3CreateForeignKey_mismatch_counts_error);310  RUN_TEST(test_sqlite3CreateForeignKey_unknown_fromcol_error);311  RUN_TEST(test_sqlite3CreateForeignKey_pFromCol_null_pToCol_multi_error);312  RUN_TEST(test_sqlite3CreateForeignKey_multi_col_with_to_names);313  RUN_TEST(test_sqlite3CreateForeignKey_multiple_chain_same_parent);314  RUN_TEST(test_sqlite3CreateForeignKey_parent_name_dequote);315  return UNITY_END();316}