Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_resolve_sqlite3ResolveSelectNames.c252 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 tests */7static sqlite3 *gDb = NULL;8 9/* Unity setup/teardown */10void setUp(void) {11  int rc = sqlite3_open(":memory:", &gDb);12  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13  /* Create simple schema used by tests */14  rc = sqlite3_exec(gDb, "CREATE TABLE t1(a INTEGER, b TEXT);", 0, 0, 0);15  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);16}17 18void tearDown(void) {19  if (gDb) {20    sqlite3_close(gDb);21    gDb = NULL;22  }23}24 25/* Helpers to build tokens safely */26static Token makeToken(const char *z){27  Token t;28  t.z = z;29  t.n = (int)strlen(z);30  return t;31}32 33/* Helper: build SELECT <col> FROM <table> */34static Select* buildSelect_Col_From_Table(Parse *pParse, const char *zCol, const char *zTable){35  Token tCol = makeToken(zCol);36  Token tTable = makeToken(zTable);37 38  SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0, &tTable, 0);39  TEST_ASSERT_NOT_NULL(pSrc);40 41  Expr *pE = sqlite3ExprAlloc(pParse->db, TK_ID, &tCol, 0);42  TEST_ASSERT_NOT_NULL(pE);43 44  ExprList *pEList = sqlite3ExprListAppend(pParse, 0, pE);45  TEST_ASSERT_NOT_NULL(pEList);46 47  Select *pSel = sqlite3SelectNew(pParse, pEList, pSrc, 0, 0, 0, 0, 0, 0, 0);48  TEST_ASSERT_NOT_NULL(pSel);49  return pSel;50}51 52/* Helper: build SELECT <const> (no FROM) */53static Select* buildSelect_Const(Parse *pParse, const char *zConst){54  Token tConst = makeToken(zConst);55  Expr *pE = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &tConst, 0);56  TEST_ASSERT_NOT_NULL(pE);57  ExprList *pEList = sqlite3ExprListAppend(pParse, 0, pE);58  TEST_ASSERT_NOT_NULL(pEList);59  Select *pSel = sqlite3SelectNew(pParse, pEList, 0, 0, 0, 0, 0, 0, 0, 0);60  TEST_ASSERT_NOT_NULL(pSel);61  return pSel;62}63 64/* Helper: free Select safely */65static void freeSelect(Select *pSel){66  if( pSel ){67    sqlite3SelectDelete(gDb, pSel);68  }69}70 71/* Test 1: Basic resolution of columns in a simple SELECT ... FROM ... */72void test_sqlite3ResolveSelectNames_basic_select_from_table(void){73  Parse parse;74  memset(&parse, 0, sizeof(parse));75  parse.db = gDb;76 77  Select *pSel = buildSelect_Col_From_Table(&parse, "a", "t1");78 79  /* Expand then resolve */80  sqlite3SelectExpand(&parse, pSel);81  sqlite3ResolveSelectNames(&parse, pSel, NULL);82 83  /* No errors */84  TEST_ASSERT_EQUAL_INT(0, parse.nErr);85 86  /* SF_Resolved should be set */87  TEST_ASSERT_TRUE((pSel->selFlags & SF_Resolved)!=0);88 89  /* The result expression should have been resolved to TK_COLUMN */90  TEST_ASSERT_NOT_NULL(pSel->pEList);91  TEST_ASSERT_EQUAL_INT(1, pSel->pEList->nExpr);92  Expr *pExpr = pSel->pEList->a[0].pExpr;93  TEST_ASSERT_NOT_NULL(pExpr);94  TEST_ASSERT_EQUAL_INT(TK_COLUMN, pExpr->op);95 96  freeSelect(pSel);97}98 99/* Test 2: Unresolved column should yield an error */100void test_sqlite3ResolveSelectNames_unresolved_column_error(void){101  Parse parse;102  memset(&parse, 0, sizeof(parse));103  parse.db = gDb;104 105  /* Column "c" does not exist in t1 */106  Select *pSel = buildSelect_Col_From_Table(&parse, "c", "t1");107 108  sqlite3SelectExpand(&parse, pSel);109  sqlite3ResolveSelectNames(&parse, pSel, NULL);110 111  TEST_ASSERT_TRUE(parse.nErr > 0);112 113  freeSelect(pSel);114}115 116/* Test 3: Subquery in FROM should be resolved by the walker */117void test_sqlite3ResolveSelectNames_subquery_in_from_is_resolved(void){118  Parse parse;119  memset(&parse, 0, sizeof(parse));120  parse.db = gDb;121 122  /* Build subquery: SELECT 1 AS x */123  Select *pSub = buildSelect_Const(&parse, "1");124  /* Optionally name the column as "x" */125  Token tX = makeToken("x");126  sqlite3ExprListSetName(&parse, pSub->pEList, &tX, 1);127 128  /* Build outer SELECT: SELECT 1 FROM (subquery) */129  Expr *pOne = sqlite3ExprAlloc(gDb, TK_INTEGER, &tX /* reuse token len 1? No, set correct */, 0);130  /* Recreate correct const token "1" */131  Token tOne = makeToken("1");132  if( pOne==0 ){ /* allocate if NULL, but should not happen */133    pOne = sqlite3ExprAlloc(gDb, TK_INTEGER, &tOne, 0);134  }else{135    /* Replace token to "1" in case previous was "x" */136    sqlite3ExprDelete(gDb, pOne);137    pOne = sqlite3ExprAlloc(gDb, TK_INTEGER, &tOne, 0);138  }139  TEST_ASSERT_NOT_NULL(pOne);140 141  ExprList *pOuterEList = sqlite3ExprListAppend(&parse, 0, pOne);142  TEST_ASSERT_NOT_NULL(pOuterEList);143 144  SrcList *pSrc = sqlite3SrcListAppend(gDb, 0, 0, 0);145  TEST_ASSERT_NOT_NULL(pSrc);146  SrcItem *pItem = &pSrc->a[pSrc->nSrc-1];147  pItem->pSelect = pSub; /* Attach the subquery as a FROM-term */148 149  Select *pOuter = sqlite3SelectNew(&parse, pOuterEList, pSrc, 0, 0, 0, 0, 0, 0, 0);150  TEST_ASSERT_NOT_NULL(pOuter);151 152  sqlite3SelectExpand(&parse, pOuter);153  sqlite3ResolveSelectNames(&parse, pOuter, NULL);154 155  /* No errors overall */156  TEST_ASSERT_EQUAL_INT(0, parse.nErr);157 158  /* Both outer and subquery should be marked resolved */159  TEST_ASSERT_TRUE((pOuter->selFlags & SF_Resolved)!=0);160  TEST_ASSERT_TRUE((pSub->selFlags & SF_Resolved)!=0);161 162  freeSelect(pOuter); /* frees subquery as well */163}164 165/* Test 4: Compound SELECT (pPrior) should resolve all arms */166void test_sqlite3ResolveSelectNames_compound_select_resolves_both_arms(void){167  Parse parse;168  memset(&parse, 0, sizeof(parse));169  parse.db = gDb;170 171  /* First arm: SELECT a FROM t1 */172  Select *pA = buildSelect_Col_From_Table(&parse, "a", "t1");173  /* Second arm: SELECT b FROM t1 */174  Select *pB = buildSelect_Col_From_Table(&parse, "b", "t1");175 176  /* Link as a compound select */177  pA->pPrior = pB;178  /* The operator kind is not strictly necessary for the walker,179     but set to TK_ALL for clarity if available */180  pA->op = TK_ALL;181 182  /* Expand both arms before resolving */183  sqlite3SelectExpand(&parse, pA);184  sqlite3SelectExpand(&parse, pB);185 186  sqlite3ResolveSelectNames(&parse, pA, NULL);187 188  TEST_ASSERT_EQUAL_INT(0, parse.nErr);189  TEST_ASSERT_TRUE((pA->selFlags & SF_Resolved)!=0);190  TEST_ASSERT_TRUE((pB->selFlags & SF_Resolved)!=0);191 192  freeSelect(pA); /* frees pB via pPrior chain */193}194 195/* Test 5: Outer NameContext allows correlated reference to resolve */196void test_sqlite3ResolveSelectNames_outer_name_context_resolves_correlated(void){197  Parse parse;198  memset(&parse, 0, sizeof(parse));199  parse.db = gDb;200 201  /* Build inner select: SELECT a (no FROM clause) */202  Token tA = makeToken("a");203  Expr *pAexpr = sqlite3ExprAlloc(gDb, TK_ID, &tA, 0);204  TEST_ASSERT_NOT_NULL(pAexpr);205  ExprList *pEList = sqlite3ExprListAppend(&parse, 0, pAexpr);206  TEST_ASSERT_NOT_NULL(pEList);207  Select *pInner = sqlite3SelectNew(&parse, pEList, 0, 0, 0, 0, 0, 0, 0, 0);208  TEST_ASSERT_NOT_NULL(pInner);209 210  /* Construct an outer NameContext that exposes table t1 */211  SrcList *pOuterSrc = sqlite3SrcListAppend(gDb, 0, &makeToken("t1"), 0);212  TEST_ASSERT_NOT_NULL(pOuterSrc);213  /* Ensure pTab is populated so resolver can find columns */214  Table *pTab = sqlite3FindTable(gDb, "t1", 0);215  TEST_ASSERT_NOT_NULL(pTab);216  pOuterSrc->a[pOuterSrc->nSrc-1].pTab = pTab;217 218  NameContext outerNC;219  memset(&outerNC, 0, sizeof(outerNC));220  outerNC.pParse = &parse;221  outerNC.pSrcList = pOuterSrc;222 223  /* Expand then resolve using the outer name context */224  sqlite3SelectExpand(&parse, pInner);225  sqlite3ResolveSelectNames(&parse, pInner, &outerNC);226 227  /* No errors; inner should be marked resolved */228  TEST_ASSERT_EQUAL_INT(0, parse.nErr);229  TEST_ASSERT_TRUE((pInner->selFlags & SF_Resolved)!=0);230 231  /* The single result expression should have been resolved to TK_COLUMN */232  TEST_ASSERT_NOT_NULL(pInner->pEList);233  TEST_ASSERT_EQUAL_INT(1, pInner->pEList->nExpr);234  Expr *pExpr = pInner->pEList->a[0].pExpr;235  TEST_ASSERT_NOT_NULL(pExpr);236  TEST_ASSERT_EQUAL_INT(TK_COLUMN, pExpr->op);237 238  /* Cleanup */239  sqlite3SrcListDelete(gDb, pOuterSrc);240  freeSelect(pInner);241}242 243/* Unity main */244int main(void){245  UNITY_BEGIN();246  RUN_TEST(test_sqlite3ResolveSelectNames_basic_select_from_table);247  RUN_TEST(test_sqlite3ResolveSelectNames_unresolved_column_error);248  RUN_TEST(test_sqlite3ResolveSelectNames_subquery_in_from_is_resolved);249  RUN_TEST(test_sqlite3ResolveSelectNames_compound_select_resolves_both_arms);250  RUN_TEST(test_sqlite3ResolveSelectNames_outer_name_context_resolves_correlated);251  return UNITY_END();252}