AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Prototypes for the wrapper we are testing */7int test_resolveOrderGroupBy(NameContext *pNC, Select *pSelect, ExprList *pOrderBy, const char *zType);8 9/* Global test context */10static sqlite3 *gDb = NULL;11static Parse gParse;12static NameContext gNC;13 14/* Helpers */15static Token makeToken(const char *z){16 Token t;17 t.z = z;18 t.n = (int)strlen(z);19 return t;20}21 22static Expr* makeId(sqlite3 *db, const char *z){23 Token t = makeToken(z);24 return sqlite3ExprAlloc(db, TK_ID, &t, 0);25}26 27static Expr* makeInt(sqlite3 *db, const char *z){28 Token t = makeToken(z);29 return sqlite3ExprAlloc(db, TK_INTEGER, &t, 0);30}31 32static Expr* makePlus(Parse *pParse, Expr *pLeft, Expr *pRight){33 return sqlite3PExpr(pParse, TK_PLUS, pLeft, pRight);34}35 36static ExprList* appendExpr(Parse *pParse, ExprList *pList, Expr *pExpr){37 return sqlite3ExprListAppend(pParse, pList, pExpr);38}39 40static ExprList* appendExprWithAlias(Parse *pParse, ExprList *pList, Expr *pExpr, const char *zAlias){41 Token t = makeToken(zAlias);42 pList = sqlite3ExprListAppend(pParse, pList, pExpr);43 sqlite3ExprListSetName(pParse, pList, &t, 0 /*dequote*/);44 return pList;45}46 47static Select* makeSelect(sqlite3 *db, ExprList *pEList){48 Select *p = (Select*)sqlite3DbMallocZero(db, sizeof(Select));49 p->pEList = pEList;50 p->pWin = 0;51 return p;52}53 54/* Unity hooks */55void setUp(void) {56 memset(&gParse, 0, sizeof(gParse));57 memset(&gNC, 0, sizeof(gNC));58 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &gDb));59 gParse.db = gDb;60 gNC.pParse = &gParse;61}62void tearDown(void) {63 if( gDb ){64 sqlite3_close(gDb);65 gDb = NULL;66 }67}68 69/* Tests */70 71/* ORDER BY alias name should resolve to the corresponding result-set column */72void test_resolveOrderGroupBy_order_by_alias(void){73 /* Result set: 10 AS a, 20 AS b */74 ExprList *eList = NULL;75 eList = appendExprWithAlias(&gParse, eList, makeInt(gDb, "10"), "a");76 eList = appendExprWithAlias(&gParse, eList, makeInt(gDb, "20"), "b");77 78 Select *pSel = makeSelect(gDb, eList);79 80 /* ORDER BY b */81 ExprList *ob = NULL;82 ob = appendExpr(&gParse, ob, makeId(gDb, "b"));83 84 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");85 TEST_ASSERT_EQUAL_INT(0, rc);86 TEST_ASSERT_EQUAL_UINT16(2, ob->a[0].u.x.iOrderByCol);87 88 sqlite3ExprListDelete(gDb, ob);89 sqlite3ExprListDelete(gDb, eList);90 sqlite3DbFree(gDb, pSel);91}92 93/* ORDER BY integer index within result-set size should succeed */94void test_resolveOrderGroupBy_order_by_integer_valid(void){95 /* Result set: three simple expressions */96 ExprList *eList = NULL;97 eList = appendExpr(&gParse, eList, makeInt(gDb, "1"));98 eList = appendExpr(&gParse, eList, makeInt(gDb, "2"));99 eList = appendExpr(&gParse, eList, makeInt(gDb, "3"));100 Select *pSel = makeSelect(gDb, eList);101 102 /* ORDER BY 2 */103 ExprList *ob = NULL;104 ob = appendExpr(&gParse, ob, makeInt(gDb, "2"));105 106 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");107 TEST_ASSERT_EQUAL_INT(0, rc);108 TEST_ASSERT_EQUAL_UINT16(2, ob->a[0].u.x.iOrderByCol);109 110 sqlite3ExprListDelete(gDb, ob);111 sqlite3ExprListDelete(gDb, eList);112 sqlite3DbFree(gDb, pSel);113}114 115/* ORDER BY 0 => out-of-range error in resolveOrderGroupBy */116void test_resolveOrderGroupBy_order_by_integer_zero_error(void){117 ExprList *eList = NULL;118 eList = appendExpr(&gParse, eList, makeInt(gDb, "11"));119 eList = appendExpr(&gParse, eList, makeInt(gDb, "22"));120 eList = appendExpr(&gParse, eList, makeInt(gDb, "33"));121 Select *pSel = makeSelect(gDb, eList);122 123 ExprList *ob = NULL;124 ob = appendExpr(&gParse, ob, makeInt(gDb, "0"));125 126 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");127 TEST_ASSERT_NOT_EQUAL(0, rc);128 129 sqlite3ExprListDelete(gDb, ob);130 sqlite3ExprListDelete(gDb, eList);131 sqlite3DbFree(gDb, pSel);132}133 134/* ORDER BY integer index within 16-bit range but greater than result-set size => error in sqlite3ResolveOrderGroupBy */135void test_resolveOrderGroupBy_order_by_integer_exceeds_result_error(void){136 ExprList *eList = NULL;137 eList = appendExpr(&gParse, eList, makeInt(gDb, "100"));138 Select *pSel = makeSelect(gDb, eList);139 140 ExprList *ob = NULL;141 ob = appendExpr(&gParse, ob, makeInt(gDb, "2"));142 143 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");144 TEST_ASSERT_NOT_EQUAL(0, rc);145 146 sqlite3ExprListDelete(gDb, ob);147 sqlite3ExprListDelete(gDb, eList);148 sqlite3DbFree(gDb, pSel);149}150 151/* ORDER BY big integer > 0xFFFF => out-of-range error in resolveOrderGroupBy */152void test_resolveOrderGroupBy_order_by_integer_too_large_error(void){153 ExprList *eList = NULL;154 eList = appendExpr(&gParse, eList, makeInt(gDb, "1"));155 eList = appendExpr(&gParse, eList, makeInt(gDb, "2"));156 Select *pSel = makeSelect(gDb, eList);157 158 ExprList *ob = NULL;159 ob = appendExpr(&gParse, ob, makeInt(gDb, "70000")); /* > 65535 */160 161 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");162 TEST_ASSERT_NOT_EQUAL(0, rc);163 164 sqlite3ExprListDelete(gDb, ob);165 sqlite3ExprListDelete(gDb, eList);166 sqlite3DbFree(gDb, pSel);167}168 169/* Structural match: ORDER BY expression identical to a result-set expression should map to that column */170void test_resolveOrderGroupBy_order_by_structural_match(void){171 /* Result-set expression: 1 + 2 */172 ExprList *eList = NULL;173 Expr *lhs1 = makeInt(gDb, "1");174 Expr *rhs1 = makeInt(gDb, "2");175 Expr *sum1 = makePlus(&gParse, lhs1, rhs1);176 eList = appendExpr(&gParse, eList, sum1);177 Select *pSel = makeSelect(gDb, eList);178 179 /* ORDER BY 1 + 2 (new tree structurally identical) */180 ExprList *ob = NULL;181 Expr *lhs2 = makeInt(gDb, "1");182 Expr *rhs2 = makeInt(gDb, "2");183 Expr *sum2 = makePlus(&gParse, lhs2, rhs2);184 ob = appendExpr(&gParse, ob, sum2);185 186 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");187 TEST_ASSERT_EQUAL_INT(0, rc);188 TEST_ASSERT_EQUAL_UINT16(1, ob->a[0].u.x.iOrderByCol);189 190 sqlite3ExprListDelete(gDb, ob);191 sqlite3ExprListDelete(gDb, eList);192 sqlite3DbFree(gDb, pSel);193}194 195/* Non-matching expression: ORDER BY expression not in result-set should leave iOrderByCol=0 and succeed */196void test_resolveOrderGroupBy_order_by_no_match_expr(void){197 /* Result-set expression: 1 + 2 */198 ExprList *eList = NULL;199 Expr *lhs1 = makeInt(gDb, "1");200 Expr *rhs1 = makeInt(gDb, "2");201 Expr *sum1 = makePlus(&gParse, lhs1, rhs1);202 eList = appendExpr(&gParse, eList, sum1);203 Select *pSel = makeSelect(gDb, eList);204 205 /* ORDER BY 3 + 4 */206 ExprList *ob = NULL;207 Expr *lhs2 = makeInt(gDb, "3");208 Expr *rhs2 = makeInt(gDb, "4");209 Expr *sum2 = makePlus(&gParse, lhs2, rhs2);210 ob = appendExpr(&gParse, ob, sum2);211 212 int rc = test_resolveOrderGroupBy(&gNC, pSel, ob, "ORDER");213 TEST_ASSERT_EQUAL_INT(0, rc);214 TEST_ASSERT_EQUAL_UINT16(0, ob->a[0].u.x.iOrderByCol);215 216 sqlite3ExprListDelete(gDb, ob);217 sqlite3ExprListDelete(gDb, eList);218 sqlite3DbFree(gDb, pSel);219}220 221/* GROUP BY should not use result-set aliases (identifier remains unresolved and triggers an error) */222void test_resolveOrderGroupBy_group_by_alias_not_used_causes_error(void){223 /* Result set: 10 AS a */224 ExprList *eList = NULL;225 eList = appendExprWithAlias(&gParse, eList, makeInt(gDb, "10"), "a");226 Select *pSel = makeSelect(gDb, eList);227 228 /* GROUP BY a (alias) -> not matched; identifier resolution fails -> error */229 ExprList *gb = NULL;230 gb = appendExpr(&gParse, gb, makeId(gDb, "a"));231 232 int rc = test_resolveOrderGroupBy(&gNC, pSel, gb, "GROUP");233 TEST_ASSERT_NOT_EQUAL(0, rc);234 235 sqlite3ExprListDelete(gDb, gb);236 sqlite3ExprListDelete(gDb, eList);237 sqlite3DbFree(gDb, pSel);238}239 240/* Main */241int main(void) {242 UNITY_BEGIN();243 RUN_TEST(test_resolveOrderGroupBy_order_by_alias);244 RUN_TEST(test_resolveOrderGroupBy_order_by_integer_valid);245 RUN_TEST(test_resolveOrderGroupBy_order_by_integer_zero_error);246 RUN_TEST(test_resolveOrderGroupBy_order_by_integer_exceeds_result_error);247 RUN_TEST(test_resolveOrderGroupBy_order_by_integer_too_large_error);248 RUN_TEST(test_resolveOrderGroupBy_order_by_structural_match);249 RUN_TEST(test_resolveOrderGroupBy_order_by_no_match_expr);250 RUN_TEST(test_resolveOrderGroupBy_group_by_alias_not_used_causes_error);251 return UNITY_END();252}