AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Helpers to construct minimal structures needed by sqlite3ExprAffinity() */7 8static Table* makeTableWithAffinities(const char *affs, int n){9 Table *pTab = (Table*)sqlite3_malloc(sizeof(Table));10 TEST_ASSERT_NOT_NULL(pTab);11 memset(pTab, 0, sizeof(Table));12 pTab->nCol = n;13 pTab->aCol = (Column*)sqlite3_malloc(sizeof(Column)*n);14 TEST_ASSERT_NOT_NULL(pTab->aCol);15 memset(pTab->aCol, 0, sizeof(Column)*n);16 for(int i=0;i<n;i++){17 pTab->aCol[i].affinity = affs[i];18 }19 return pTab;20}21 22static Expr* makeCastExpr(const char *zType){23 Expr *p = (Expr*)sqlite3_malloc(sizeof(Expr));24 TEST_ASSERT_NOT_NULL(p);25 memset(p, 0, sizeof(Expr));26 p->op = TK_CAST;27 /* EP_IntValue must not be set for TK_CAST */28 p->u.zToken = (char*)zType;29 return p;30}31 32static ExprList* makeExprList(Expr **apExpr, int n){33 ExprList *pList = (ExprList*)sqlite3_malloc(sizeof(ExprList));34 TEST_ASSERT_NOT_NULL(pList);35 memset(pList, 0, sizeof(ExprList));36 pList->nExpr = n;37 pList->a = (struct ExprList_item*)sqlite3_malloc(sizeof(struct ExprList_item)*n);38 TEST_ASSERT_NOT_NULL(pList->a);39 memset(pList->a, 0, sizeof(struct ExprList_item)*n);40 for(int i=0;i<n;i++){41 pList->a[i].pExpr = apExpr[i];42 }43 return pList;44}45 46static Select* makeSelectFromExprs(Expr **apExpr, int n){47 Select *pSel = (Select*)sqlite3_malloc(sizeof(Select));48 TEST_ASSERT_NOT_NULL(pSel);49 memset(pSel, 0, sizeof(Select));50 pSel->pEList = makeExprList(apExpr, n);51 return pSel;52}53 54static Expr* makeSelectExprHolding(Select *pSel){55 Expr *p = (Expr*)sqlite3_malloc(sizeof(Expr));56 TEST_ASSERT_NOT_NULL(p);57 memset(p, 0, sizeof(Expr));58 p->op = TK_SELECT;59 p->flags |= EP_xIsSelect; /* Satisfy ExprUseXSelect() assertions */60 p->x.pSelect = pSel;61 return p;62}63 64void setUp(void) {65 /* Setup code here, or leave empty */66}67void tearDown(void) {68 /* Cleanup code here, or leave empty */69}70 71/* Tests */72 73void test_sqlite3ExprAffinity_column_returns_table_col_affinity(void){74 char affs[2] = { SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER };75 Table *pTab = makeTableWithAffinities(affs, 2);76 77 Expr e; memset(&e, 0, sizeof(e));78 e.op = TK_COLUMN;79 e.y.pTab = pTab;80 e.iColumn = 1;81 82 char a = sqlite3ExprAffinity(&e);83 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_INTEGER, a);84}85 86void test_sqlite3ExprAffinity_column_negative_index_rowid_affinity(void){87 char affs[1] = { SQLITE_AFF_TEXT };88 Table *pTab = makeTableWithAffinities(affs, 1);89 90 Expr e; memset(&e, 0, sizeof(e));91 e.op = TK_COLUMN;92 e.y.pTab = pTab;93 e.iColumn = -1; /* rowid pseudo-column */94 95 char a = sqlite3ExprAffinity(&e);96 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_INTEGER, a);97}98 99void test_sqlite3ExprAffinity_agg_column_with_pTab_returns_affinity(void){100 char affs[1] = { SQLITE_AFF_REAL };101 Table *pTab = makeTableWithAffinities(affs, 1);102 103 Expr e; memset(&e, 0, sizeof(e));104 e.op = TK_AGG_COLUMN;105 e.y.pTab = pTab;106 e.iColumn = 0;107 108 char a = sqlite3ExprAffinity(&e);109 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_REAL, a);110}111 112void test_sqlite3ExprAffinity_agg_column_without_pTab_falls_back_to_affExpr(void){113 Expr e; memset(&e, 0, sizeof(e));114 e.op = TK_AGG_COLUMN;115 e.y.pTab = 0; /* Not set */116 e.affExpr = SQLITE_AFF_NUMERIC;117 118 char a = sqlite3ExprAffinity(&e);119 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_NUMERIC, a);120}121 122void test_sqlite3ExprAffinity_select_returns_first_result_affinity(void){123 /* SELECT CAST('x' AS TEXT) */124 Expr *pCastText = makeCastExpr("TEXT");125 Expr *aExprs[1] = { pCastText };126 Select *pSel = makeSelectFromExprs(aExprs, 1);127 Expr *pSelectExpr = makeSelectExprHolding(pSel);128 129 char a = sqlite3ExprAffinity(pSelectExpr);130 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_TEXT, a);131}132 133void test_sqlite3ExprAffinity_cast_type_mapped_affinities(void){134 struct {135 const char *zType;136 char aff;137 } cases[] = {138 { "INTEGER", SQLITE_AFF_INTEGER },139 { "TEXT", SQLITE_AFF_TEXT },140 { "NUMERIC", SQLITE_AFF_NUMERIC },141 { "BLOB", SQLITE_AFF_BLOB },142 { "REAL", SQLITE_AFF_REAL }143 };144 for(unsigned i=0; i<sizeof(cases)/sizeof(cases[0]); i++){145 Expr *pCast = makeCastExpr(cases[i].zType);146 char a = sqlite3ExprAffinity(pCast);147 TEST_ASSERT_EQUAL_CHAR(cases[i].aff, a);148 }149}150 151void test_sqlite3ExprAffinity_select_column_picks_correct_output_affinity(void){152 /* Build a SELECT with two result columns:153 0: CAST(... AS INTEGER)154 1: CAST(... AS TEXT)155 */156 Expr *pInt = makeCastExpr("INTEGER");157 Expr *pTxt = makeCastExpr("TEXT");158 Expr *aExprs[2] = { pInt, pTxt };159 Select *pSel = makeSelectFromExprs(aExprs, 2);160 Expr *pSelectExpr = makeSelectExprHolding(pSel);161 162 Expr eSC; memset(&eSC, 0, sizeof(eSC));163 eSC.op = TK_SELECT_COLUMN;164 eSC.pLeft = pSelectExpr;165 eSC.iTable = pSel->pEList->nExpr; /* must equal nExpr */166 eSC.iColumn = 1; /* pick 2nd expression (TEXT) */167 168 char a = sqlite3ExprAffinity(&eSC);169 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_TEXT, a);170}171 172void test_sqlite3ExprAffinity_vector_uses_first_element_affinity(void){173 Expr *pNum = makeCastExpr("NUMERIC");174 Expr *aExprs[1] = { pNum };175 ExprList *pList = makeExprList(aExprs, 1);176 177 Expr eVec; memset(&eVec, 0, sizeof(eVec));178 eVec.op = TK_VECTOR;179 eVec.x.pList = pList;180 181 char a = sqlite3ExprAffinity(&eVec);182 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_NUMERIC, a);183}184 185void test_sqlite3ExprAffinity_function_defer_uses_first_arg_affinity(void){186 Expr *pReal = makeCastExpr("REAL");187 Expr *aExprs[1] = { pReal };188 ExprList *pList = makeExprList(aExprs, 1);189 190 Expr eFn; memset(&eFn, 0, sizeof(eFn));191 eFn.op = TK_FUNCTION;192 eFn.affExpr = SQLITE_AFF_DEFER; /* Trigger the defer path */193 eFn.x.pList = pList;194 195 char a = sqlite3ExprAffinity(&eFn);196 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_REAL, a);197}198 199void test_sqlite3ExprAffinity_collate_skip_follows_left_child(void){200 /* Make child: CAST(... AS REAL) */201 Expr *pChild = makeCastExpr("REAL");202 203 /* Parent COLLATE with EP_Skip, should forward to left child */204 Expr e; memset(&e, 0, sizeof(e));205 e.op = TK_COLLATE;206 e.flags |= EP_Skip;207 e.pLeft = pChild;208 209 char a = sqlite3ExprAffinity(&e);210 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_REAL, a);211}212 213void test_sqlite3ExprAffinity_register_op2_is_used(void){214 /* A TK_REGISTER that wraps a CAST to INTEGER */215 Expr e; memset(&e, 0, sizeof(e));216 e.op = TK_REGISTER;217 e.op2 = TK_CAST;218 e.u.zToken = (char*)"INTEGER"; /* used when op2==TK_CAST */219 220 char a = sqlite3ExprAffinity(&e);221 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_INTEGER, a);222}223 224void test_sqlite3ExprAffinity_fallback_returns_affExpr_field(void){225 Expr e; memset(&e, 0, sizeof(e));226 e.op = TK_STRING; /* any op not handled specially */227 e.affExpr = SQLITE_AFF_TEXT;228 229 char a = sqlite3ExprAffinity(&e);230 TEST_ASSERT_EQUAL_CHAR(SQLITE_AFF_TEXT, a);231}232 233int main(void) {234 UNITY_BEGIN();235 236 RUN_TEST(test_sqlite3ExprAffinity_column_returns_table_col_affinity);237 RUN_TEST(test_sqlite3ExprAffinity_column_negative_index_rowid_affinity);238 RUN_TEST(test_sqlite3ExprAffinity_agg_column_with_pTab_returns_affinity);239 RUN_TEST(test_sqlite3ExprAffinity_agg_column_without_pTab_falls_back_to_affExpr);240 RUN_TEST(test_sqlite3ExprAffinity_select_returns_first_result_affinity);241 RUN_TEST(test_sqlite3ExprAffinity_cast_type_mapped_affinities);242 RUN_TEST(test_sqlite3ExprAffinity_select_column_picks_correct_output_affinity);243 RUN_TEST(test_sqlite3ExprAffinity_vector_uses_first_element_affinity);244 RUN_TEST(test_sqlite3ExprAffinity_function_defer_uses_first_arg_affinity);245 RUN_TEST(test_sqlite3ExprAffinity_collate_skip_follows_left_child);246 RUN_TEST(test_sqlite3ExprAffinity_register_op2_is_used);247 RUN_TEST(test_sqlite3ExprAffinity_fallback_returns_affExpr_field);248 249 return UNITY_END();250}