Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_build_sqlite3CreateIndex.c266 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Globals for each test */7static sqlite3 *gDb = NULL;8static Parse gParse;9 10/* Helpers */11static void enterDbMutex(sqlite3 *db){ sqlite3_mutex_enter(sqlite3_db_mutex(db)); }12static void leaveDbMutex(sqlite3 *db){ sqlite3_mutex_leave(sqlite3_db_mutex(db)); }13 14static void resetParse(void){15  memset(&gParse, 0, sizeof(gParse));16  gParse.db = gDb;17  gDb->pParse = &gParse;18}19 20static Table* makeTestTable(21  sqlite3 *db,22  const char *zTab,23  const char *const *azCol,24  const u8 *aNotNull,25  int nCol26){27  Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));28  TEST_ASSERT_NOT_NULL(pTab);29  pTab->zName = sqlite3DbStrDup(db, zTab);30  pTab->pSchema = db->aDb[0].pSchema;31  pTab->nCol = nCol;32  pTab->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nCol);33  TEST_ASSERT_NOT_NULL(pTab->aCol);34  pTab->iPKey = -1;35  for(int i=0;i<nCol;i++){36    /* Column name and minimal properties */37    pTab->aCol[i].zCnName = sqlite3DbStrDup(db, azCol[i]);38    pTab->aCol[i].notNull = aNotNull ? aNotNull[i] : 0;39    pTab->aCol[i].szEst = 1; /* keep estimateIndexWidth happy */40    pTab->aCol[i].colFlags = 0;41  }42  return pTab;43}44 45static ExprList* makeExprListOfColumn(Parse *pParse, const char *zCol, const char *zCollate, int desc){46  Token tCol; sqlite3TokenInit(&tCol, zCol);47  Expr *pCol = sqlite3ExprAlloc(pParse->db, TK_ID, &tCol, 0);48  TEST_ASSERT_NOT_NULL(pCol);49  Expr *pExpr = pCol;50  if( zCollate ){51    Token tColl; sqlite3TokenInit(&tColl, zCollate);52    Expr *pColl = sqlite3ExprAlloc(pParse->db, TK_COLLATE, &tColl, 0);53    TEST_ASSERT_NOT_NULL(pColl);54    pColl->pLeft = pCol;55    pExpr = pColl;56  }57  ExprList *pList = sqlite3ExprListAppend(pParse, 0, pExpr);58  TEST_ASSERT_NOT_NULL(pList);59  /* Manually set sort flag: 1 means DESC in requestedSortOrder */60  if( desc ){61    pList->a[0].fg.sortFlags = 1;62  }63  return pList;64}65 66static ExprList* makeExprListWithNulls(Parse *pParse, const char *zCol, int nullsFirst){67  ExprList *pList = makeExprListOfColumn(pParse, zCol, NULL, 0);68  /* Flag explicit NULLS; sortFlags used to determine FIRST or LAST in error */69  pList->a[0].fg.bNulls = 1;70  pList->a[0].fg.sortFlags = nullsFirst ? 0 : 1;71  return pList;72}73 74static ExprList* makeExprListOfExpression(Parse *pParse, const char *zCol){75  Token tCol; sqlite3TokenInit(&tCol, zCol);76  Token tOne; sqlite3TokenInit(&tOne, "1");77  Expr *pL = sqlite3ExprAlloc(pParse->db, TK_ID, &tCol, 0);78  Expr *pR = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &tOne, 0);79  TEST_ASSERT_NOT_NULL(pL);80  TEST_ASSERT_NOT_NULL(pR);81  Expr *pPlus = sqlite3ExprAlloc(pParse->db, TK_PLUS, 0, 0);82  TEST_ASSERT_NOT_NULL(pPlus);83  pPlus->pLeft = pL;84  pPlus->pRight = pR;85  ExprList *pList = sqlite3ExprListAppend(pParse, 0, pPlus);86  TEST_ASSERT_NOT_NULL(pList);87  return pList;88}89 90static int countIndexes(Index *p){ int n=0; while(p){ n++; p=p->pNext; } return n; }91 92void setUp(void){93  int rc = sqlite3_open(":memory:", &gDb);94  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);95  resetParse();96}97 98void tearDown(void){99  if( gParse.zErrMsg ){100    sqlite3DbFree(gDb, gParse.zErrMsg);101    gParse.zErrMsg = 0;102  }103  if( gParse.pNewTable ){104    enterDbMutex(gDb);105    sqlite3DeleteTable(gDb, gParse.pNewTable);106    leaveDbMutex(gDb);107    gParse.pNewTable = 0;108  }109  if( gDb ){110    sqlite3_close(gDb);111    gDb = NULL;112  }113  memset(&gParse, 0, sizeof(gParse));114}115 116/* Tests */117 118void test_sqlite3CreateIndex_early_exit_on_parse_error(void){119  gParse.nErr = 1; /* force early exit */120  /* Satisfy assertion db->pParse==pParse */121  TEST_ASSERT_EQUAL_PTR(&gParse, gDb->pParse);122 123  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, NULL,124                     OE_None, NULL, NULL, 0, 0, SQLITE_IDXTYPE_APPDEF);125 126  TEST_ASSERT_EQUAL_INT(1, gParse.nErr);127  /* No index or table mutations expected */128  TEST_ASSERT_NULL(gParse.pNewTable);129}130 131void test_sqlite3CreateIndex_in_declare_vtab_skips_non_pk(void){132  gParse.declareVtab = 1; /* IN_DECLARE_VTAB */133  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, NULL,134                     OE_None, NULL, NULL, 0, 0, SQLITE_IDXTYPE_APPDEF);135  /* No error and no side-effects */136  TEST_ASSERT_EQUAL_INT(0, gParse.nErr);137  TEST_ASSERT_NULL(gParse.pNewTable);138}139 140void test_sqlite3CreateIndex_explicit_nulls_first_error(void){141  ExprList *pList = makeExprListWithNulls(&gParse, "a", 1 /* FIRST */);142  /* Call; expect error due to explicit NULLS FIRST */143  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList,144                     OE_None, NULL, NULL, 0, 0, SQLITE_IDXTYPE_APPDEF);145  TEST_ASSERT_NOT_EQUAL(0, gParse.nErr);146  TEST_ASSERT_NOT_NULL(gParse.zErrMsg);147  TEST_ASSERT_NOT_NULL(strstr(gParse.zErrMsg, "NULLS FIRST"));148}149 150void test_sqlite3CreateIndex_autoindex_on_last_column_and_desc(void){151  const char *cols[] = {"a","b"};152  u8 nn[] = {0,1};153  Table *pTab = makeTestTable(gDb, "t1", cols, nn, 2);154  gParse.pNewTable = pTab;155  /* Ensure DESC sort is honored (file_format>=4) */156  enterDbMutex(gDb);157  gDb->aDb[0].pSchema->file_format = 4;158  /* Call with pList==NULL to make index on last column 'b' */159  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, NULL,160                     OE_Abort, NULL, NULL, 1 /* sort DESC for last-col pk/unique */, 0,161                     SQLITE_IDXTYPE_UNIQUE);162  leaveDbMutex(gDb);163 164  TEST_ASSERT_NOT_NULL(pTab->pIndex);165  Index *pIdx = pTab->pIndex;166  TEST_ASSERT_EQUAL_INT(SQLITE_IDXTYPE_UNIQUE, pIdx->idxType);167  TEST_ASSERT_EQUAL_PTR(pTab, pIdx->pTable);168  TEST_ASSERT_EQUAL_INT(1, pIdx->nKeyCol);169  TEST_ASSERT_EQUAL_INT(1, pIdx->aiColumn[0]); /* column 'b' index 1 */170  TEST_ASSERT_EQUAL_UINT8(1, pIdx->aSortOrder[0]); /* DESC honored */171  TEST_ASSERT_TRUE(pIdx->uniqNotNull); /* 'b' was NOT NULL */172  /* Ensure rowid appended */173  TEST_ASSERT_EQUAL_INT(XN_ROWID, pIdx->aiColumn[pIdx->nKeyCol]);174}175 176void test_sqlite3CreateIndex_collate_nocase_on_column(void){177  const char *cols[] = {"a"};178  u8 nn[] = {1};179  Table *pTab = makeTestTable(gDb, "t2", cols, nn, 1);180  gParse.pNewTable = pTab;181  ExprList *pList = makeExprListOfColumn(&gParse, "a", "nocase", 0);182 183  enterDbMutex(gDb);184  gDb->aDb[0].pSchema->file_format = 4;185  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList,186                     OE_Abort, NULL, NULL, 0, 0, SQLITE_IDXTYPE_UNIQUE);187  leaveDbMutex(gDb);188 189  TEST_ASSERT_EQUAL_INT(0, gParse.nErr);190  TEST_ASSERT_NOT_NULL(pTab->pIndex);191  Index *pIdx = pTab->pIndex;192  TEST_ASSERT_EQUAL_INT(1, pIdx->nKeyCol);193  TEST_ASSERT_EQUAL_INT(0, pIdx->aiColumn[0]);194  TEST_ASSERT_NOT_NULL(pIdx->azColl[0]);195  TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(pIdx->azColl[0], "nocase"));196}197 198void test_sqlite3CreateIndex_unique_nullable_column_uniqNotNull_cleared(void){199  const char *cols[] = {"x"};200  u8 nn[] = {0}; /* nullable */201  Table *pTab = makeTestTable(gDb, "t3", cols, nn, 1);202  gParse.pNewTable = pTab;203  ExprList *pList = makeExprListOfColumn(&gParse, "x", NULL, 0);204 205  enterDbMutex(gDb);206  gDb->aDb[0].pSchema->file_format = 4;207  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList,208                     OE_Abort, NULL, NULL, 0, 0, SQLITE_IDXTYPE_UNIQUE);209  leaveDbMutex(gDb);210 211  TEST_ASSERT_NOT_NULL(pTab->pIndex);212  TEST_ASSERT_FALSE(pTab->pIndex->uniqNotNull); /* cleared due to nullable column */213}214 215void test_sqlite3CreateIndex_sort_order_ignored_in_old_file_format(void){216  const char *cols[] = {"a"};217  u8 nn[] = {1};218  Table *pTab = makeTestTable(gDb, "t4", cols, nn, 1);219  gParse.pNewTable = pTab;220  ExprList *pList = makeExprListOfColumn(&gParse, "a", NULL, 1 /* DESC requested */);221 222  enterDbMutex(gDb);223  gDb->aDb[0].pSchema->file_format = 3; /* old format: ignore DESC */224  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList,225                     OE_None, NULL, NULL, 0, 0, SQLITE_IDXTYPE_APPDEF);226  leaveDbMutex(gDb);227 228  TEST_ASSERT_NOT_NULL(pTab->pIndex);229  TEST_ASSERT_EQUAL_UINT8(0, pTab->pIndex->aSortOrder[0]); /* DESC ignored */230}231 232void test_sqlite3CreateIndex_duplicate_constraint_suppresses_second_index(void){233  const char *cols[] = {"a","b"};234  u8 nn[] = {1,1};235  Table *pTab = makeTestTable(gDb, "t5", cols, nn, 2);236  gParse.pNewTable = pTab;237 238  enterDbMutex(gDb);239  gDb->aDb[0].pSchema->file_format = 4;240  ExprList *pList1 = makeExprListOfColumn(&gParse, "a", NULL, 0);241  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList1,242                     OE_Abort, NULL, NULL, 0, 0, SQLITE_IDXTYPE_UNIQUE);243  int n1 = countIndexes(pTab->pIndex);244  TEST_ASSERT_EQUAL_INT(1, n1);245 246  ExprList *pList2 = makeExprListOfColumn(&gParse, "a", NULL, 0);247  sqlite3CreateIndex(&gParse, NULL, NULL, NULL, pList2,248                     OE_Abort, NULL, NULL, 0, 0, SQLITE_IDXTYPE_UNIQUE);249  int n2 = countIndexes(pTab->pIndex);250  leaveDbMutex(gDb);251 252  TEST_ASSERT_EQUAL_INT(1, n2); /* still one index after duplicate constraint */253}254 255int main(void){256  UNITY_BEGIN();257  RUN_TEST(test_sqlite3CreateIndex_early_exit_on_parse_error);258  RUN_TEST(test_sqlite3CreateIndex_in_declare_vtab_skips_non_pk);259  RUN_TEST(test_sqlite3CreateIndex_explicit_nulls_first_error);260  RUN_TEST(test_sqlite3CreateIndex_autoindex_on_last_column_and_desc);261  RUN_TEST(test_sqlite3CreateIndex_collate_nocase_on_column);262  RUN_TEST(test_sqlite3CreateIndex_unique_nullable_column_uniqNotNull_cleared);263  RUN_TEST(test_sqlite3CreateIndex_sort_order_ignored_in_old_file_format);264  RUN_TEST(test_sqlite3CreateIndex_duplicate_constraint_suppresses_second_index);265  return UNITY_END();266}