AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6extern int test_exprCompareVariable(const Parse *pParse, const Expr *pVar, const Expr *pExpr);7 8static Expr *makeVarExpr(sqlite3 *db, int iVar){9 Expr *e = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));10 TEST_ASSERT_NOT_NULL_MESSAGE(e, "Failed to allocate Expr for variable");11 e->op = TK_VARIABLE;12 e->iColumn = iVar; /* Variable index is stored in iColumn for TK_VARIABLE */13 return e;14}15 16static Expr *makeIntExpr(sqlite3 *db, const char *zNum){17 Expr *e = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));18 TEST_ASSERT_NOT_NULL_MESSAGE(e, "Failed to allocate Expr for integer");19 e->op = TK_INTEGER;20 e->u.zToken = sqlite3DbStrDup(db, zNum);21 TEST_ASSERT_NOT_NULL_MESSAGE(e->u.zToken, "Failed to allocate zToken for integer");22 return e;23}24 25static Expr *makeTextExpr(sqlite3 *db, const char *zText){26 Expr *e = (Expr*)sqlite3DbMallocZero(db, sizeof(Expr));27 TEST_ASSERT_NOT_NULL_MESSAGE(e, "Failed to allocate Expr for string");28 e->op = TK_STRING;29 e->u.zToken = sqlite3DbStrDup(db, zText);30 TEST_ASSERT_NOT_NULL_MESSAGE(e->u.zToken, "Failed to allocate zToken for string");31 return e;32}33 34static void freeExpr(sqlite3 *db, Expr *e){35 if( !e ) return;36 if( (e->op==TK_INTEGER || e->op==TK_STRING || e->op==TK_FLOAT || e->op==TK_BLOB) && e->u.zToken ){37 sqlite3DbFree(db, e->u.zToken);38 }39 sqlite3DbFree(db, e);40}41 42void setUp(void) {43 /* No global setup */44}45void tearDown(void) {46 /* No global teardown */47}48 49/* Test: early return when pExpr is the same variable as pVar */50void test_exprCompareVariable_same_variable_returns_0(void){51 Parse p;52 memset(&p, 0, sizeof(p));53 /* p.db not needed due to early return path */54 /* Create variable expressions */55 sqlite3 *db;56 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));57 Expr *pVar = makeVarExpr(db, 1);58 Expr *pExpr = makeVarExpr(db, 1);59 60 int rc = test_exprCompareVariable(&p, pVar, pExpr);61 TEST_ASSERT_EQUAL_INT(0, rc);62 63 freeExpr(db, pVar);64 freeExpr(db, pExpr);65 sqlite3_close(db);66}67 68/* Test: SQLITE_EnableQPSG flag forces return 2 regardless of expression */69void test_exprCompareVariable_qpsg_flag_forces_2(void){70 sqlite3 *db = 0;71 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));72 Parse p;73 memset(&p, 0, sizeof(p));74 p.db = db;75 76 /* Set the flag */77 db->flags |= SQLITE_EnableQPSG;78 79 Expr *pVar = makeVarExpr(db, 1);80 Expr *pExpr = makeIntExpr(db, "5"); /* simple constant */81 82 int rc = test_exprCompareVariable(&p, pVar, pExpr);83 TEST_ASSERT_EQUAL_INT(2, rc);84 85 /* Cleanup */86 db->flags &= ~SQLITE_EnableQPSG;87 freeExpr(db, pVar);88 freeExpr(db, pExpr);89 sqlite3_close(db);90}91 92/* Helper to initialize Parse with pVdbe and a pReprepare statement "SELECT ?1" */93static void initParseWithReprepare(sqlite3 **pDbOut, Parse *pOut, sqlite3_stmt **pStmtOut){94 sqlite3 *db = 0;95 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));96 memset(pOut, 0, sizeof(*pOut));97 pOut->db = db;98 99 /* Create a VDBE for pVdbe (needed for sqlite3VdbeSetVarmask) */100 Vdbe *pv = sqlite3VdbeCreate(pOut);101 TEST_ASSERT_NOT_NULL_MESSAGE(pv, "sqlite3VdbeCreate failed");102 pOut->pVdbe = pv;103 104 /* Prepare a statement with 1 parameter; this will be used as pReprepare */105 sqlite3_stmt *stmt = 0;106 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_prepare_v2(db, "SELECT ?1", -1, &stmt, 0));107 TEST_ASSERT_NOT_NULL_MESSAGE(stmt, "prepare failed");108 pOut->pReprepare = (Vdbe*)stmt;109 110 *pDbOut = db;111 *pStmtOut = stmt;112}113 114/* Test: simple integer constant equal to bound value returns 0 */115void test_exprCompareVariable_equal_integer_constant_returns_0(void){116 sqlite3 *db = 0;117 Parse p;118 sqlite3_stmt *stmt = 0;119 initParseWithReprepare(&db, &p, &stmt);120 121 /* Bind variable ?1 = 55 */122 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_bind_int(stmt, 1, 55));123 124 Expr *pVar = makeVarExpr(db, 1);125 Expr *pExpr = makeIntExpr(db, "55");126 127 int rc = test_exprCompareVariable(&p, pVar, pExpr);128 TEST_ASSERT_EQUAL_INT(0, rc);129 130 /* Cleanup */131 freeExpr(db, pVar);132 freeExpr(db, pExpr);133 sqlite3_finalize(stmt);134 sqlite3VdbeDelete(p.pVdbe);135 sqlite3_close(db);136}137 138/* Test: simple integer constant different from bound value returns 2 */139void test_exprCompareVariable_unequal_integer_constant_returns_2(void){140 sqlite3 *db = 0;141 Parse p;142 sqlite3_stmt *stmt = 0;143 initParseWithReprepare(&db, &p, &stmt);144 145 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_bind_int(stmt, 1, 99));146 147 Expr *pVar = makeVarExpr(db, 1);148 Expr *pExpr = makeIntExpr(db, "55");149 150 int rc = test_exprCompareVariable(&p, pVar, pExpr);151 TEST_ASSERT_EQUAL_INT(2, rc);152 153 /* Cleanup */154 freeExpr(db, pVar);155 freeExpr(db, pExpr);156 sqlite3_finalize(stmt);157 sqlite3VdbeDelete(p.pVdbe);158 sqlite3_close(db);159}160 161/* Test: when variable is unbound (no bind), result should be 2 */162void test_exprCompareVariable_unbound_variable_returns_2(void){163 sqlite3 *db = 0;164 Parse p;165 sqlite3_stmt *stmt = 0;166 initParseWithReprepare(&db, &p, &stmt);167 168 /* No bind for ?1 */169 170 Expr *pVar = makeVarExpr(db, 1);171 Expr *pExpr = makeIntExpr(db, "123");172 173 int rc = test_exprCompareVariable(&p, pVar, pExpr);174 TEST_ASSERT_EQUAL_INT(2, rc);175 176 /* Cleanup */177 freeExpr(db, pVar);178 freeExpr(db, pExpr);179 sqlite3_finalize(stmt);180 sqlite3VdbeDelete(p.pVdbe);181 sqlite3_close(db);182}183 184/* Test: simple text constant equal to bound text returns 0 */185void test_exprCompareVariable_equal_text_constant_returns_0(void){186 sqlite3 *db = 0;187 Parse p;188 sqlite3_stmt *stmt = 0;189 initParseWithReprepare(&db, &p, &stmt);190 191 const char *txt = "hello";192 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_bind_text(stmt, 1, txt, -1, SQLITE_TRANSIENT));193 194 Expr *pVar = makeVarExpr(db, 1);195 Expr *pExpr = makeTextExpr(db, txt);196 197 int rc = test_exprCompareVariable(&p, pVar, pExpr);198 TEST_ASSERT_EQUAL_INT(0, rc);199 200 /* Cleanup */201 freeExpr(db, pVar);202 freeExpr(db, pExpr);203 sqlite3_finalize(stmt);204 sqlite3VdbeDelete(p.pVdbe);205 sqlite3_close(db);206}207 208/* Test: pExpr is a different variable (?2) - not a simple constant, returns 2 */209void test_exprCompareVariable_expr_is_different_variable_returns_2(void){210 sqlite3 *db = 0;211 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));212 Parse p;213 memset(&p, 0, sizeof(p));214 p.db = db;215 216 Expr *pVar = makeVarExpr(db, 1); /* ?1 */217 Expr *pExpr = makeVarExpr(db, 2); /* ?2 */218 219 int rc = test_exprCompareVariable(&p, pVar, pExpr);220 TEST_ASSERT_EQUAL_INT(2, rc);221 222 freeExpr(db, pVar);223 freeExpr(db, pExpr);224 sqlite3_close(db);225}226 227int main(void){228 UNITY_BEGIN();229 RUN_TEST(test_exprCompareVariable_same_variable_returns_0);230 RUN_TEST(test_exprCompareVariable_qpsg_flag_forces_2);231 RUN_TEST(test_exprCompareVariable_equal_integer_constant_returns_0);232 RUN_TEST(test_exprCompareVariable_unequal_integer_constant_returns_2);233 RUN_TEST(test_exprCompareVariable_unbound_variable_returns_2);234 RUN_TEST(test_exprCompareVariable_equal_text_constant_returns_0);235 RUN_TEST(test_exprCompareVariable_expr_is_different_variable_returns_2);236 return UNITY_END();237}