Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_resolve_resolveCompoundOrderBy.c269 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5/* Forward declaration of the test wrapper provided in the module */6int test_resolveCompoundOrderBy(Parse *pParse, Select *pSelect);7 8/* Global DB for each test */9static sqlite3 *gDb = NULL;10 11/* Helpers */12static Token mkToken(const char *z){13  Token t;14  t.z = (char*)z;15  t.n = (int)strlen(z);16  return t;17}18 19static Expr* makeIdExpr(sqlite3 *db, const char *z){20  Token t = mkToken(z);21  return sqlite3ExprAlloc(db, TK_ID, &t, 0);22}23 24static Expr* makeIntExpr(sqlite3 *db, int v){25  return sqlite3ExprInt32(db, v);26}27 28static ExprList* appendExpr(Parse *pParse, ExprList *pList, Expr *pExpr){29  return sqlite3ExprListAppend(pParse, pList, pExpr);30}31 32static ExprList* makeOrderBy1(Parse *pParse, Expr *p1){33  ExprList *p = NULL;34  p = appendExpr(pParse, p, p1);35  return p;36}37 38static ExprList* makeOrderBy2(Parse *pParse, Expr *p1, Expr *p2){39  ExprList *p = NULL;40  p = appendExpr(pParse, p, p1);41  p = appendExpr(pParse, p, p2);42  return p;43}44 45static ExprList* makeEListWithAliases(Parse *pParse, const char **aliases, int nAlias){46  ExprList *p = NULL;47  for(int i=0; i<nAlias; i++){48    /* The actual expression does not matter for alias matching. Use integer constants. */49    p = appendExpr(pParse, p, makeIntExpr(pParse->db, i+100));50    if( aliases && aliases[i] ){51      Token t = mkToken(aliases[i]);52      /* Set alias on the most recently appended item */53      sqlite3ExprListSetName(pParse, p, &t, 1);54    }55  }56  return p;57}58 59static Select* makeSelect(Parse *pParse, ExprList *pEList, ExprList *pOrderBy){60  Select *pSel = (Select*)sqlite3DbMallocZero(pParse->db, sizeof(Select));61  TEST_ASSERT_NOT_NULL(pSel);62  pSel->pEList = pEList;63  pSel->pOrderBy = pOrderBy;64  return pSel;65}66 67void setUp(void) {68  int rc = sqlite3_open(":memory:", &gDb);69  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);70}71 72void tearDown(void) {73  if( gDb ){74    sqlite3_close(gDb);75    gDb = NULL;76  }77}78 79/* Test: No ORDER BY clause should return 0 (no errors) */80void test_resolveCompoundOrderBy_no_order_by_returns0(void){81  Parse s = {0};82  s.db = gDb;83 84  const char *aliases[] = { "c1" };85  ExprList *pEList = makeEListWithAliases(&s, aliases, 1);86  Select *pSel = makeSelect(&s, pEList, NULL);87 88  int rc = test_resolveCompoundOrderBy(&s, pSel);89  TEST_ASSERT_EQUAL_INT(0, rc);90 91  sqlite3SelectDelete(gDb, pSel);92}93 94/* Test: ORDER BY integer within range is accepted and transformed */95void test_resolveCompoundOrderBy_integer_within_range(void){96  Parse s = (Parse){0};97  s.db = gDb;98 99  const char *aliases[] = { "a", "b", "c" };100  ExprList *pEList = makeEListWithAliases(&s, aliases, 3);101  ExprList *pOrderBy = makeOrderBy1(&s, makeIntExpr(gDb, 2));102  Select *pSel = makeSelect(&s, pEList, pOrderBy);103 104  int rc = test_resolveCompoundOrderBy(&s, pSel);105  TEST_ASSERT_EQUAL_INT(0, rc);106 107  TEST_ASSERT_EQUAL_INT(1, pOrderBy->a[0].fg.done);108  TEST_ASSERT_EQUAL_UINT16(2, pOrderBy->a[0].u.x.iOrderByCol);109  TEST_ASSERT_NOT_NULL(pOrderBy->a[0].pExpr);110  TEST_ASSERT_EQUAL_INT(TK_INTEGER, pOrderBy->a[0].pExpr->op);111 112  sqlite3SelectDelete(gDb, pSel);113}114 115/* Test: ORDER BY integer out of range should raise an error */116void test_resolveCompoundOrderBy_integer_out_of_range(void){117  Parse s = (Parse){0};118  s.db = gDb;119 120  const char *aliases[] = { "a" };121  ExprList *pEList = makeEListWithAliases(&s, aliases, 1);122  /* ORDER BY 2 while only 1 column available */123  ExprList *pOrderBy = makeOrderBy1(&s, makeIntExpr(gDb, 2));124  Select *pSel = makeSelect(&s, pEList, pOrderBy);125 126  int rc = test_resolveCompoundOrderBy(&s, pSel);127  TEST_ASSERT_EQUAL_INT(1, rc);128  TEST_ASSERT_NOT_NULL(s.zErrMsg);129  TEST_ASSERT_NOT_EQUAL(NULL, strstr(s.zErrMsg, "out of range"));130 131  sqlite3SelectDelete(gDb, pSel);132}133 134/* Test: ORDER BY alias name resolves to correct column index */135void test_resolveCompoundOrderBy_alias_match(void){136  Parse s = (Parse){0};137  s.db = gDb;138 139  const char *aliases[] = { "c1", "c2" };140  ExprList *pEList = makeEListWithAliases(&s, aliases, 2);141 142  Expr *pId = makeIdExpr(gDb, "c1");143  ExprList *pOrderBy = makeOrderBy1(&s, pId);144 145  Select *pSel = makeSelect(&s, pEList, pOrderBy);146 147  int rc = test_resolveCompoundOrderBy(&s, pSel);148  TEST_ASSERT_EQUAL_INT(0, rc);149 150  TEST_ASSERT_EQUAL_INT(1, pOrderBy->a[0].fg.done);151  TEST_ASSERT_EQUAL_UINT16(1, pOrderBy->a[0].u.x.iOrderByCol);152  TEST_ASSERT_NOT_NULL(pOrderBy->a[0].pExpr);153  TEST_ASSERT_EQUAL_INT(TK_INTEGER, pOrderBy->a[0].pExpr->op);154 155  sqlite3SelectDelete(gDb, pSel);156}157 158/* Test: ORDER BY identifier that does not match any result column generates error */159void test_resolveCompoundOrderBy_identifier_no_match_errors(void){160  Parse s = (Parse){0};161  s.db = gDb;162 163  const char *aliases[] = { "a" };164  ExprList *pEList = makeEListWithAliases(&s, aliases, 1);165  ExprList *pOrderBy = makeOrderBy1(&s, makeIdExpr(gDb, "b")); /* Does not match */166  Select *pSel = makeSelect(&s, pEList, pOrderBy);167 168  int rc = test_resolveCompoundOrderBy(&s, pSel);169  TEST_ASSERT_EQUAL_INT(1, rc);170  TEST_ASSERT_NOT_NULL(s.zErrMsg);171  TEST_ASSERT_NOT_EQUAL(NULL, strstr(s.zErrMsg, "does not match any column"));172 173  sqlite3SelectDelete(gDb, pSel);174}175 176/* Test: ORDER BY with COLLATE wrapper preserves COLLATE and replaces inner expr */177void test_resolveCompoundOrderBy_collate_wrapped_expr(void){178  Parse s = (Parse){0};179  s.db = gDb;180 181  const char *aliases[] = { "x" };182  ExprList *pEList = makeEListWithAliases(&s, aliases, 1);183 184  Expr *pInner = makeIdExpr(gDb, "x");185  Expr *pCollated = sqlite3ExprAddCollateString(gDb, pInner, "BINARY");186  ExprList *pOrderBy = makeOrderBy1(&s, pCollated);187 188  Select *pSel = makeSelect(&s, pEList, pOrderBy);189 190  int rc = test_resolveCompoundOrderBy(&s, pSel);191  TEST_ASSERT_EQUAL_INT(0, rc);192 193  TEST_ASSERT_EQUAL_INT(1, pOrderBy->a[0].fg.done);194  TEST_ASSERT_EQUAL_UINT16(1, pOrderBy->a[0].u.x.iOrderByCol);195  /* The outer expression should remain TK_COLLATE with integer left child */196  TEST_ASSERT_NOT_NULL(pOrderBy->a[0].pExpr);197  TEST_ASSERT_EQUAL_INT(TK_COLLATE, pOrderBy->a[0].pExpr->op);198  TEST_ASSERT_NOT_NULL(pOrderBy->a[0].pExpr->pLeft);199  TEST_ASSERT_EQUAL_INT(TK_INTEGER, pOrderBy->a[0].pExpr->pLeft->op);200 201  sqlite3SelectDelete(gDb, pSel);202}203 204/* Test: Too many ORDER BY terms compared to SQLITE_LIMIT_COLUMN should error */205void test_resolveCompoundOrderBy_too_many_terms_limit_error(void){206  Parse s = (Parse){0};207  s.db = gDb;208 209  /* Set a very low column limit for ORDER BY term count check */210  int prior = sqlite3_limit(gDb, SQLITE_LIMIT_COLUMN, 1);211  (void)prior; /* unused */212 213  const char *aliases[] = { "a", "b" };214  ExprList *pEList = makeEListWithAliases(&s, aliases, 2);215  ExprList *pOrderBy = makeOrderBy2(&s, makeIntExpr(gDb, 1), makeIntExpr(gDb, 2));216  Select *pSel = makeSelect(&s, pEList, pOrderBy);217 218  int rc = test_resolveCompoundOrderBy(&s, pSel);219  TEST_ASSERT_EQUAL_INT(1, rc);220  TEST_ASSERT_NOT_NULL(s.zErrMsg);221  TEST_ASSERT_NOT_EQUAL(NULL, strstr(s.zErrMsg, "too many terms"));222 223  sqlite3SelectDelete(gDb, pSel);224 225  /* Restore a reasonable limit for other tests just in case */226  sqlite3_limit(gDb, SQLITE_LIMIT_COLUMN, 2000);227}228 229/* Test: Compound SELECT chain; ORDER BY alias resolved in a later SELECT */230void test_resolveCompoundOrderBy_compound_chain_resolution(void){231  Parse s = (Parse){0};232  s.db = gDb;233 234  /* Left-most SELECT: aliases do not include "x" */235  const char *leftAliases[] = { "a1", "a2" };236  ExprList *pLeftEList = makeEListWithAliases(&s, leftAliases, 2);237  Select *pLeft = makeSelect(&s, pLeftEList, NULL);238 239  /* Right-most SELECT: alias contains "x" */240  const char *rightAliases[] = { "x", "y" };241  ExprList *pRightEList = makeEListWithAliases(&s, rightAliases, 2);242  ExprList *pOrderBy = makeOrderBy1(&s, makeIdExpr(gDb, "x"));243  Select *pRight = makeSelect(&s, pRightEList, pOrderBy);244 245  /* Link as a compound: right->pPrior = left, ORDER BY belongs to right-most */246  pRight->pPrior = pLeft;247 248  int rc = test_resolveCompoundOrderBy(&s, pRight); /* Pass the SELECT containing ORDER BY */249  TEST_ASSERT_EQUAL_INT(0, rc);250  TEST_ASSERT_EQUAL_INT(1, pOrderBy->a[0].fg.done);251  TEST_ASSERT_EQUAL_UINT16(1, pOrderBy->a[0].u.x.iOrderByCol);252 253  /* Free starting from left-most is fine after function linked pNext pointers */254  /* resolveCompoundOrderBy built pNext chain; delete from left-most cleans all */255  sqlite3SelectDelete(gDb, pLeft);256}257 258int main(void) {259  UNITY_BEGIN();260  RUN_TEST(test_resolveCompoundOrderBy_no_order_by_returns0);261  RUN_TEST(test_resolveCompoundOrderBy_integer_within_range);262  RUN_TEST(test_resolveCompoundOrderBy_integer_out_of_range);263  RUN_TEST(test_resolveCompoundOrderBy_alias_match);264  RUN_TEST(test_resolveCompoundOrderBy_identifier_no_match_errors);265  RUN_TEST(test_resolveCompoundOrderBy_collate_wrapped_expr);266  RUN_TEST(test_resolveCompoundOrderBy_too_many_terms_limit_error);267  RUN_TEST(test_resolveCompoundOrderBy_compound_chain_resolution);268  return UNITY_END();269}