Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_expr_codeVectorCompare.c196 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Helper: Create a TK_VECTOR expression with N NULL elements */7static Expr* makeVectorOfNulls(Parse *pParse, int n){8  ExprList *pList = 0;9  for(int i=0; i<n; i++){10    Expr *pNull = sqlite3PExpr(pParse, TK_NULL, 0, 0);11    TEST_ASSERT_NOT_NULL_MESSAGE(pNull, "Failed to allocate TK_NULL expression");12    pList = sqlite3ExprListAppend(pParse, pList, pNull);13    TEST_ASSERT_NOT_NULL_MESSAGE(pList, "Failed to append to ExprList");14  }15  Expr *pVec = sqlite3ExprAlloc(pParse->db, TK_VECTOR, 0, 0);16  TEST_ASSERT_NOT_NULL_MESSAGE(pVec, "Failed to allocate TK_VECTOR expression");17  pVec->x.pList = pList; /* Vector uses x.pList */18  return pVec;19}20 21/* Helper: Build a comparison expression pLeft <op> pRight */22static Expr* makeCompareExpr(Parse *pParse, int tkOp, Expr *pLeft, Expr *pRight){23  Expr *pExpr = sqlite3PExpr(pParse, tkOp, pLeft, pRight);24  TEST_ASSERT_NOT_NULL_MESSAGE(pExpr, "Failed to allocate comparison Expr");25  return pExpr;26}27 28/* Helper: Count number of VDBE ops with specific opcode in [start, end) */29static int countOpcode(Vdbe *v, int start, int end, int opcode){30  int n = 0;31  for(int i=start; i<end; i++){32    VdbeOp *op = sqlite3VdbeGetOp(v, i);33    if( op && op->opcode==opcode ) n++;34  }35  return n;36}37 38/* Helper: Find first op with opcode and (optional) p1/p2 match in [start,end). 39   Pass p1Match/p2Match as -1 to ignore. Returns index or -1 if not found. */40static int findOpcodeP1P2(Vdbe *v, int start, int end, int opcode, int p1Match, int p2Match){41  for(int i=start; i<end; i++){42    VdbeOp *op = sqlite3VdbeGetOp(v, i);43    if( op && op->opcode==opcode ){44      if( (p1Match<0 || op->p1==p1Match) && (p2Match<0 || op->p2==p2Match) ){45        return i;46      }47    }48  }49  return -1;50}51 52void setUp(void) {53  /* empty */54}55void tearDown(void) {56  /* empty */57}58 59/* Test: (NULL) = (NULL) with SQLITE_NULLEQ on singleton vector60   Expect: First op OP_Integer 1,dest; and an OP_Integer 0,dest later (due to NULLEQ branch). */61void test_codeVectorCompare_eq_nulleq_singleton(void){62  sqlite3 *db = 0;63  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));64  Parse parse;65  memset(&parse, 0, sizeof(parse));66  parse.db = db;67  parse.pVdbe = sqlite3VdbeCreate(db);68  TEST_ASSERT_NOT_NULL(parse.pVdbe);69  Vdbe *v = parse.pVdbe;70 71  int dest = 10;72 73  Expr *pLeft = makeVectorOfNulls(&parse, 1);74  Expr *pRight = makeVectorOfNulls(&parse, 1);75  Expr *pCmp = makeCompareExpr(&parse, TK_EQ, pLeft, pRight);76 77  int start = sqlite3VdbeCurrentAddr(v);78  test_codeVectorCompare(&parse, pCmp, dest, TK_EQ, SQLITE_NULLEQ);79  int end = sqlite3VdbeCurrentAddr(v);80 81  /* First new op should be OP_Integer 1 -> dest */82  VdbeOp *op0 = sqlite3VdbeGetOp(v, start);83  TEST_ASSERT_NOT_NULL(op0);84  TEST_ASSERT_EQUAL_INT(OP_Integer, op0->opcode);85  TEST_ASSERT_EQUAL_INT(1, op0->p1);86  TEST_ASSERT_EQUAL_INT(dest, op0->p2);87 88  /* Ensure an OP_Integer 0 -> dest exists later (from NULLEQ branch) */89  int idxZero = findOpcodeP1P2(v, start+1, end, OP_Integer, 0, dest);90  TEST_ASSERT_TRUE_MESSAGE(idxZero >= 0, "Did not find OP_Integer 0,dest emitted for NULLEQ");91 92  sqlite3_close(db);93}94 95/* Test: (NULL) <> (NULL) on singleton vector96   Expect the last emitted op is OP_Not dest,dest (the NE invert). */97void test_codeVectorCompare_ne_singleton_has_final_not(void){98  sqlite3 *db = 0;99  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));100  Parse parse;101  memset(&parse, 0, sizeof(parse));102  parse.db = db;103  parse.pVdbe = sqlite3VdbeCreate(db);104  TEST_ASSERT_NOT_NULL(parse.pVdbe);105  Vdbe *v = parse.pVdbe;106 107  int dest = 7;108 109  Expr *pLeft = makeVectorOfNulls(&parse, 1);110  Expr *pRight = makeVectorOfNulls(&parse, 1);111  Expr *pCmp = makeCompareExpr(&parse, TK_NE, pLeft, pRight);112 113  int start = sqlite3VdbeCurrentAddr(v);114  test_codeVectorCompare(&parse, pCmp, dest, TK_NE, 0);115  int end = sqlite3VdbeCurrentAddr(v);116 117  TEST_ASSERT_TRUE_MESSAGE(end > start, "No ops emitted");118  VdbeOp *last = sqlite3VdbeGetOp(v, end-1);119  TEST_ASSERT_NOT_NULL(last);120  TEST_ASSERT_EQUAL_INT(OP_Not, last->opcode);121  TEST_ASSERT_EQUAL_INT(dest, last->p1);122  TEST_ASSERT_EQUAL_INT(dest, last->p2);123 124  sqlite3_close(db);125}126 127/* Test: (NULL,NULL) < (NULL,NULL)128   Expect at least one OP_ElseEq emitted (tie-breaker for vector LT/GT) */129void test_codeVectorCompare_lt_two_elements_has_ElseEq(void){130  sqlite3 *db = 0;131  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));132  Parse parse;133  memset(&parse, 0, sizeof(parse));134  parse.db = db;135  parse.pVdbe = sqlite3VdbeCreate(db);136  TEST_ASSERT_NOT_NULL(parse.pVdbe);137  Vdbe *v = parse.pVdbe;138 139  int dest = 3;140 141  Expr *pLeft = makeVectorOfNulls(&parse, 2);142  Expr *pRight = makeVectorOfNulls(&parse, 2);143  Expr *pCmp = makeCompareExpr(&parse, TK_LT, pLeft, pRight);144 145  int start = sqlite3VdbeCurrentAddr(v);146  test_codeVectorCompare(&parse, pCmp, dest, TK_LT, 0);147  int end = sqlite3VdbeCurrentAddr(v);148 149  int nElseEq = countOpcode(v, start, end, OP_ElseEq);150  TEST_ASSERT_TRUE_MESSAGE(nElseEq >= 1, "Expected OP_ElseEq for vector LT with multiple elements");151 152  /* Sanity: first emitted op is OP_Integer 1->dest */153  VdbeOp *op0 = sqlite3VdbeGetOp(v, start);154  TEST_ASSERT_NOT_NULL(op0);155  TEST_ASSERT_EQUAL_INT(OP_Integer, op0->opcode);156  TEST_ASSERT_EQUAL_INT(1, op0->p1);157  TEST_ASSERT_EQUAL_INT(dest, op0->p2);158 159  sqlite3_close(db);160}161 162/* Test: Mismatched vector sizes -> error and no ops emitted */163void test_codeVectorCompare_mismatched_sizes_sets_error_and_no_ops(void){164  sqlite3 *db = 0;165  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));166  Parse parse;167  memset(&parse, 0, sizeof(parse));168  parse.db = db;169  parse.pVdbe = sqlite3VdbeCreate(db);170  TEST_ASSERT_NOT_NULL(parse.pVdbe);171  Vdbe *v = parse.pVdbe;172 173  int dest = 5;174 175  Expr *pLeft = makeVectorOfNulls(&parse, 1);176  Expr *pRight = makeVectorOfNulls(&parse, 2);177  Expr *pCmp = makeCompareExpr(&parse, TK_EQ, pLeft, pRight);178 179  int start = sqlite3VdbeCurrentAddr(v);180  test_codeVectorCompare(&parse, pCmp, dest, TK_EQ, 0);181  int end = sqlite3VdbeCurrentAddr(v);182 183  TEST_ASSERT_EQUAL_INT_MESSAGE(start, end, "No VDBE ops should be emitted on error");184  TEST_ASSERT_TRUE_MESSAGE(parse.nErr>0, "Expected parse error (row value misused)");185 186  sqlite3_close(db);187}188 189int main(void){190  UNITY_BEGIN();191  RUN_TEST(test_codeVectorCompare_eq_nulleq_singleton);192  RUN_TEST(test_codeVectorCompare_ne_singleton_has_final_not);193  RUN_TEST(test_codeVectorCompare_lt_two_elements_has_ElseEq);194  RUN_TEST(test_codeVectorCompare_mismatched_sizes_sets_error_and_no_ops);195  return UNITY_END();196}