AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Unity setup/teardown */7void setUp(void) {8 /* No setup required */9}10void tearDown(void) {11 /* No teardown required */12}13 14/* Helper: Initialize a TK_COLUMN Expr that points to a minimal Table/Column15 providing the specified column affinity in cols[0].affinity. The lifetime16 of Table/Column/Expr are managed by the caller (stack variables). */17static void init_column_expr_with_affinity(Expr *pExpr, Table *pTab, Column *aCol, char aff){18 memset(pExpr, 0, sizeof(*pExpr));19 memset(pTab, 0, sizeof(*pTab));20 memset(aCol, 0, sizeof(*aCol));21 22 aCol[0].affinity = aff;23 24 pTab->nCol = 1;25 pTab->aCol = aCol;26 27 pExpr->op = TK_COLUMN;28 pExpr->y.pTab = pTab;29 pExpr->iColumn = 0;30}31 32/* Helper: Initialize a non-column Expr that returns aff via sqlite3ExprAffinity.33 We use op=TK_INTEGER (any non-special op) and set affExpr directly. */34static void init_noncolumn_expr_with_affinity(Expr *pExpr, char aff){35 memset(pExpr, 0, sizeof(*pExpr));36 pExpr->op = TK_INTEGER; /* Any non-special op so code falls through */37 pExpr->affExpr = aff; /* sqlite3ExprAffinity will return this */38}39 40/* Test: If either side is numeric and both sides have affinity, result is NUMERIC. */41void test_sqlite3CompareAffinity_numeric_affinity_wins_if_either_side_is_numeric(void){42 Expr e;43 Table tab;44 Column col;45 46 /* Case A: column=TEXT, aff2=NUMERIC -> expect NUMERIC */47 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_TEXT);48 {49 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_NUMERIC);50 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_NUMERIC, (int)got);51 }52 53 /* Case B: column=INTEGER (numeric), aff2=TEXT -> expect NUMERIC */54 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_INTEGER);55 {56 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_TEXT);57 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_NUMERIC, (int)got);58 }59 60 /* Case C: both numeric (REAL vs NUMERIC) -> expect NUMERIC */61 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_REAL);62 {63 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_NUMERIC);64 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_NUMERIC, (int)got);65 }66}67 68/* Test: If both sides have non-NONE affinity but neither is numeric, result is BLOB. */69void test_sqlite3CompareAffinity_no_numeric_results_in_blob(void){70 Expr e;71 Table tab;72 Column col;73 74 /* column=TEXT, aff2=TEXT -> neither numeric */75 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_TEXT);76 {77 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_TEXT);78 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_BLOB, (int)got);79 }80 81 /* column=BLOB, aff2=TEXT -> still no numeric, expect BLOB */82 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_BLOB);83 {84 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_TEXT);85 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_BLOB, (int)got);86 }87}88 89/* Test: One side is a column (aff1>NONE), the other is NONE -> use column's affinity (OR SQLITE_AFF_NONE). */90void test_sqlite3CompareAffinity_column_vs_none_prefers_column_affinity(void){91 Expr e;92 Table tab;93 Column col;94 95 /* column=REAL, aff2=NONE */96 init_column_expr_with_affinity(&e, &tab, &col, SQLITE_AFF_REAL);97 {98 char aff1 = sqlite3ExprAffinity(&e); /* Should be REAL */99 TEST_ASSERT_TRUE(aff1 > SQLITE_AFF_NONE);100 char aff2 = SQLITE_AFF_NONE;101 char expected = ((aff1 <= SQLITE_AFF_NONE) ? aff2 : aff1) | SQLITE_AFF_NONE;102 char got = sqlite3CompareAffinity(&e, aff2);103 TEST_ASSERT_EQUAL_INT((int)expected, (int)got);104 }105}106 107/* Test: aff1 is NONE (non-column expr), aff2 has affinity -> result is aff2 | SQLITE_AFF_NONE. */108void test_sqlite3CompareAffinity_none_vs_text_prefers_aff2(void){109 Expr e;110 111 init_noncolumn_expr_with_affinity(&e, SQLITE_AFF_NONE);112 {113 char aff1 = sqlite3ExprAffinity(&e);114 TEST_ASSERT_TRUE(aff1 <= SQLITE_AFF_NONE);115 char aff2 = SQLITE_AFF_TEXT;116 char expected = ((aff1 <= SQLITE_AFF_NONE) ? aff2 : aff1) | SQLITE_AFF_NONE;117 char got = sqlite3CompareAffinity(&e, aff2);118 TEST_ASSERT_EQUAL_INT((int)expected, (int)got);119 }120}121 122/* Test: Both sides NONE -> result is SQLITE_AFF_NONE (i.e., NONE | NONE). */123void test_sqlite3CompareAffinity_both_none_results_in_none(void){124 Expr e;125 126 init_noncolumn_expr_with_affinity(&e, SQLITE_AFF_NONE);127 {128 char aff1 = sqlite3ExprAffinity(&e);129 char aff2 = SQLITE_AFF_NONE;130 char expected = ((aff1 <= SQLITE_AFF_NONE) ? aff2 : aff1) | SQLITE_AFF_NONE;131 char got = sqlite3CompareAffinity(&e, aff2);132 TEST_ASSERT_EQUAL_INT((int)expected, (int)got);133 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_NONE, (int)got);134 }135}136 137/* Additional test: Non-column aff1 numeric and aff2 non-numeric still returns NUMERIC. */138void test_sqlite3CompareAffinity_noncolumn_numeric_wins(void){139 Expr e;140 141 init_noncolumn_expr_with_affinity(&e, SQLITE_AFF_NUMERIC);142 {143 char aff1 = sqlite3ExprAffinity(&e);144 TEST_ASSERT_TRUE(aff1 > SQLITE_AFF_NONE);145 TEST_ASSERT_TRUE(sqlite3IsNumericAffinity(aff1) != 0);146 char got = sqlite3CompareAffinity(&e, SQLITE_AFF_TEXT);147 TEST_ASSERT_EQUAL_INT((int)SQLITE_AFF_NUMERIC, (int)got);148 }149}150 151int main(void){152 UNITY_BEGIN();153 154 RUN_TEST(test_sqlite3CompareAffinity_numeric_affinity_wins_if_either_side_is_numeric);155 RUN_TEST(test_sqlite3CompareAffinity_no_numeric_results_in_blob);156 RUN_TEST(test_sqlite3CompareAffinity_column_vs_none_prefers_column_affinity);157 RUN_TEST(test_sqlite3CompareAffinity_none_vs_text_prefers_aff2);158 RUN_TEST(test_sqlite3CompareAffinity_both_none_results_in_none);159 RUN_TEST(test_sqlite3CompareAffinity_noncolumn_numeric_wins);160 161 return UNITY_END();162}