AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include "vdbeInt.h"4#include <string.h>5 6/* Globals for each test */7static sqlite3 *gDb = NULL;8static Parse gParse;9static Vdbe *gVdbe = NULL;10 11/* Helper: get last opcode, or NULL if none */12static Op* getLastOp(void){13 int n = sqlite3VdbeCurrentAddr(gVdbe);14 if( n<=0 ) return NULL;15 return sqlite3VdbeGetOp(gVdbe, n-1);16}17 18void setUp(void) {19 int rc = sqlite3_open(":memory:", &gDb);20 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21 memset(&gParse, 0, sizeof(gParse));22 gParse.db = gDb;23 gVdbe = sqlite3VdbeCreate(gDb);24 TEST_ASSERT_NOT_NULL(gVdbe);25 gParse.pVdbe = gVdbe;26 gParse.nMem = 100; /* plenty of registers for tests */27 gParse.iSelfTab = 0; /* default, overridden in specific tests as needed */28}29 30void tearDown(void) {31 if( gVdbe ){32 sqlite3VdbeDelete(gVdbe);33 gVdbe = NULL;34 }35 if( gDb ){36 sqlite3_close(gDb);37 gDb = NULL;38 }39}40 41/* Test: pExpr==NULL results in OP_Null to target */42void test_sqlite3ExprCode_null_expr_emits_OP_Null(void){43 int target = 5;44 sqlite3ExprCode(&gParse, NULL, target);45 46 int nOp = sqlite3VdbeCurrentAddr(gVdbe);47 TEST_ASSERT_EQUAL_INT(1, nOp);48 49 Op *pOp = getLastOp();50 TEST_ASSERT_NOT_NULL(pOp);51 TEST_ASSERT_EQUAL_INT(OP_Null, pOp->opcode);52 /* sqlite3VdbeAddOp2(OP_Null, 0, target) -> p2 is the target */53 TEST_ASSERT_EQUAL_INT(target, pOp->p2);54}55 56/* Test: TK_INTEGER emits OP_Integer directly to target and no copy */57void test_sqlite3ExprCode_TK_INTEGER_no_copy(void){58 int target = 10;59 Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));60 TEST_ASSERT_NOT_NULL(p);61 p->op = TK_INTEGER;62 /* Use an inline integer value */63 p->flags = EP_IntValue | EP_TokenOnly;64 p->u.iValue = 12345;65 66 sqlite3ExprCode(&gParse, p, target);67 68 int nOp = sqlite3VdbeCurrentAddr(gVdbe);69 TEST_ASSERT_EQUAL_INT(1, nOp);70 71 Op *pOp = getLastOp();72 TEST_ASSERT_NOT_NULL(pOp);73 TEST_ASSERT_EQUAL_INT(OP_Integer, pOp->opcode);74 TEST_ASSERT_EQUAL_INT(12345, pOp->p1);75 TEST_ASSERT_EQUAL_INT(target, pOp->p2);76 77 sqlite3DbFree(gDb, p);78}79 80/* Test: TK_REGISTER causes OP_Copy from source register to target */81void test_sqlite3ExprCode_TK_REGISTER_emits_OP_Copy(void){82 int sourceReg = 8;83 int target = 3;84 Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));85 TEST_ASSERT_NOT_NULL(p);86 p->op = TK_REGISTER;87 p->iTable = sourceReg;88 89 sqlite3ExprCode(&gParse, p, target);90 91 int nOp = sqlite3VdbeCurrentAddr(gVdbe);92 TEST_ASSERT_EQUAL_INT(1, nOp);93 94 Op *pOp = getLastOp();95 TEST_ASSERT_NOT_NULL(pOp);96 TEST_ASSERT_EQUAL_INT(OP_Copy, pOp->opcode);97 TEST_ASSERT_EQUAL_INT(sourceReg, pOp->p1);98 TEST_ASSERT_EQUAL_INT(target, pOp->p2);99 100 sqlite3DbFree(gDb, p);101}102 103/* Test: TK_COLUMN in self-row context (iTable<0, iSelfTab<0) returns a non-target104 register, so sqlite3ExprCode must emit OP_SCopy to move to target. */105void test_sqlite3ExprCode_TK_COLUMN_selftab_negative_emits_OP_SCopy(void){106 int target = 2;107 108 /* Set up self-row context */109 gParse.iSelfTab = -10; /* registers for unpacked row start at 0 - iSelfTab */110 111 /* Minimal table with 1 column */112 Table *pTab = (Table*)sqlite3DbMallocZero(gDb, sizeof(Table));113 TEST_ASSERT_NOT_NULL(pTab);114 pTab->nCol = 1;115 pTab->aCol = (Column*)sqlite3DbMallocZero(gDb, sizeof(Column)*pTab->nCol);116 TEST_ASSERT_NOT_NULL(pTab->aCol);117 pTab->aCol[0].affinity = SQLITE_AFF_BLOB; /* ensure branch does not add RealAffinity */118 119 /* Build the expression: TK_COLUMN referencing column 0 of self-row (iTable<0) */120 Expr *p = (Expr*)sqlite3DbMallocZero(gDb, sizeof(Expr));121 TEST_ASSERT_NOT_NULL(p);122 p->op = TK_COLUMN;123 p->iTable = -1; /* indicates self-row */124 p->iColumn = 0; /* first column */125 p->y.pTab = pTab; /* table metadata needed by the code path */126 127 /* Expected source register computed as:128 sqlite3TableColumnToStorage(pTab,0) - gParse.iSelfTab129 Normally storage index for first column is 0, so src = 0 - (-10) = 10. */130 int expectedSrc = 0 - gParse.iSelfTab;131 132 sqlite3ExprCode(&gParse, p, target);133 134 int nOp = sqlite3VdbeCurrentAddr(gVdbe);135 TEST_ASSERT_EQUAL_INT(1, nOp);136 137 Op *pOp = getLastOp();138 TEST_ASSERT_NOT_NULL(pOp);139 TEST_ASSERT_EQUAL_INT(OP_SCopy, pOp->opcode);140 TEST_ASSERT_EQUAL_INT(expectedSrc, pOp->p1);141 TEST_ASSERT_EQUAL_INT(target, pOp->p2);142 143 /* Cleanup */144 sqlite3DbFree(gDb, p);145 sqlite3DbFree(gDb, pTab->aCol);146 sqlite3DbFree(gDb, pTab);147}148 149int main(void) {150 UNITY_BEGIN();151 RUN_TEST(test_sqlite3ExprCode_null_expr_emits_OP_Null);152 RUN_TEST(test_sqlite3ExprCode_TK_INTEGER_no_copy);153 RUN_TEST(test_sqlite3ExprCode_TK_REGISTER_emits_OP_Copy);154 RUN_TEST(test_sqlite3ExprCode_TK_COLUMN_selftab_negative_emits_OP_SCopy);155 return UNITY_END();156}