AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5 6/* Helper scalar function: double the integer argument */7static void xDouble(sqlite3_context *ctx, int argc, sqlite3_value **argv){8 int v = 0;9 if( argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){10 v = sqlite3_value_int(argv[0]);11 }12 sqlite3_result_int(ctx, v*2);13}14 15/* Helper scalar function: triple the integer argument (used to test overwrite) */16static void xTimes3(sqlite3_context *ctx, int argc, sqlite3_value **argv){17 int v = 0;18 if( argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){19 v = sqlite3_value_int(argv[0]);20 }21 sqlite3_result_int(ctx, v*3);22}23 24/* Helper zero-arg scalar function: returns constant 1234 */25static void xConst1234(sqlite3_context *ctx, int argc, sqlite3_value **argv){26 (void)argc; (void)argv;27 sqlite3_result_int(ctx, 1234);28}29 30/* Helper varargs scalar function: return number of arguments passed */31static void xVarCount(sqlite3_context *ctx, int argc, sqlite3_value **argv){32 (void)argv;33 sqlite3_result_int(ctx, argc);34}35 36/* Aggregate: sum of integer arguments */37static void xAggSumStep(sqlite3_context *ctx, int argc, sqlite3_value **argv){38 long long *pSum = (long long*)sqlite3_aggregate_context(ctx, (int)sizeof(long long));39 if( pSum && argc>=1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){40 *pSum += sqlite3_value_int64(argv[0]);41 }42}43static void xAggSumFinal(sqlite3_context *ctx){44 long long *pSum = (long long*)sqlite3_aggregate_context(ctx, 0);45 if( pSum ){46 sqlite3_result_int64(ctx, *pSum);47 }else{48 sqlite3_result_int64(ctx, 0);49 }50}51 52/* Small helper to evaluate a single-row/single-column integer result */53static int eval_int(sqlite3 *db, const char *zSql, int *pOut){54 sqlite3_stmt *pStmt = 0;55 int rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);56 if( rc!=SQLITE_OK ) return rc;57 rc = sqlite3_step(pStmt);58 if( rc==SQLITE_ROW ){59 if( pOut ) *pOut = sqlite3_column_int(pStmt, 0);60 rc = SQLITE_OK;61 }else if( rc==SQLITE_DONE ){62 rc = SQLITE_EMPTY; /* No row returned */63 }64 sqlite3_finalize(pStmt);65 return rc;66}67 68void setUp(void) {69 /* Setup code here, or leave empty */70}71 72void tearDown(void) {73 /* Cleanup code here, or leave empty */74}75 76void test_sqlite3_create_function_scalar_basic(void){77 sqlite3 *db = 0;78 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));79 80 int rc = sqlite3_create_function(81 db, "xdouble", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);82 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);83 84 /* Direct constant */85 int out = 0;86 rc = eval_int(db, "SELECT xdouble(21)", &out);87 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88 TEST_ASSERT_EQUAL_INT(42, out);89 90 /* With bound parameter */91 sqlite3_stmt *pStmt = 0;92 rc = sqlite3_prepare_v2(db, "SELECT xdouble(?1)", -1, &pStmt, 0);93 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);94 TEST_ASSERT_NOT_NULL(pStmt);95 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_bind_int(pStmt, 1, 7));96 rc = sqlite3_step(pStmt);97 TEST_ASSERT_EQUAL_INT(SQLITE_ROW, rc);98 TEST_ASSERT_EQUAL_INT(14, sqlite3_column_int(pStmt, 0));99 sqlite3_finalize(pStmt);100 101 sqlite3_close(db);102}103 104void test_sqlite3_create_function_zero_arg(void){105 sqlite3 *db = 0;106 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));107 108 int rc = sqlite3_create_function(109 db, "zerof", 0, SQLITE_UTF8, NULL, xConst1234, NULL, NULL);110 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);111 112 int out = 0;113 rc = eval_int(db, "SELECT zerof()", &out);114 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);115 TEST_ASSERT_EQUAL_INT(1234, out);116 117 sqlite3_close(db);118}119 120void test_sqlite3_create_function_aggregate_basic(void){121 sqlite3 *db = 0;122 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));123 124 int rc = sqlite3_create_function(125 db, "mysum", 1, SQLITE_UTF8, NULL, NULL, xAggSumStep, xAggSumFinal);126 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);127 128 int out = 0;129 /* Use VALUES table with alias for column name */130 rc = eval_int(db, "SELECT mysum(x) FROM (VALUES(1),(2),(3),(4)) AS t(x)", &out);131 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);132 TEST_ASSERT_EQUAL_INT(10, out);133 134 sqlite3_close(db);135}136 137void test_sqlite3_create_function_varargs(void){138 sqlite3 *db = 0;139 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));140 141 int rc = sqlite3_create_function(142 db, "varcnt", -1, SQLITE_UTF8, NULL, xVarCount, NULL, NULL);143 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);144 145 int out = 0;146 147 rc = eval_int(db, "SELECT varcnt()", &out);148 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);149 TEST_ASSERT_EQUAL_INT(0, out);150 151 rc = eval_int(db, "SELECT varcnt(10)", &out);152 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);153 TEST_ASSERT_EQUAL_INT(1, out);154 155 rc = eval_int(db, "SELECT varcnt(1,2,3,4,5)", &out);156 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);157 TEST_ASSERT_EQUAL_INT(5, out);158 159 sqlite3_close(db);160}161 162void test_sqlite3_create_function_overwrite_existing(void){163 sqlite3 *db = 0;164 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));165 166 /* Register xdouble as doubling function */167 int rc = sqlite3_create_function(168 db, "xdouble", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);169 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);170 171 int out = 0;172 rc = eval_int(db, "SELECT xdouble(5)", &out);173 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);174 TEST_ASSERT_EQUAL_INT(10, out);175 176 /* Overwrite with a tripling function under same name/arity */177 rc = sqlite3_create_function(178 db, "xdouble", 1, SQLITE_UTF8, NULL, xTimes3, NULL, NULL);179 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);180 181 rc = eval_int(db, "SELECT xdouble(5)", &out);182 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);183 TEST_ASSERT_EQUAL_INT(15, out);184 185 sqlite3_close(db);186}187 188void test_sqlite3_create_function_wrong_arity_prepare_error(void){189 sqlite3 *db = 0;190 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));191 192 int rc = sqlite3_create_function(193 db, "only1", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);194 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);195 196 /* Using wrong number of arguments should cause prepare to fail */197 sqlite3_stmt *pStmt = 0;198 rc = sqlite3_prepare_v2(db, "SELECT only1(1,2)", -1, &pStmt, 0);199 TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);200 if( pStmt ) sqlite3_finalize(pStmt);201 202 /* Correct arity should work */203 int out = 0;204 rc = eval_int(db, "SELECT only1(9)", &out);205 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);206 TEST_ASSERT_EQUAL_INT(18, out);207 208 sqlite3_close(db);209}210 211void test_sqlite3_create_function_invalid_name_fails(void){212 sqlite3 *db = 0;213 TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));214 215 /* NULL function name should fail (but must not crash) */216 int rc = sqlite3_create_function(217 db, NULL, 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);218 TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);219 220 /* Empty string name should also fail */221 rc = sqlite3_create_function(222 db, "", 1, SQLITE_UTF8, NULL, xDouble, NULL, NULL);223 TEST_ASSERT_NOT_EQUAL(INT, SQLITE_OK, rc);224 225 sqlite3_close(db);226}227 228int main(void){229 UNITY_BEGIN();230 RUN_TEST(test_sqlite3_create_function_scalar_basic);231 RUN_TEST(test_sqlite3_create_function_zero_arg);232 RUN_TEST(test_sqlite3_create_function_aggregate_basic);233 RUN_TEST(test_sqlite3_create_function_varargs);234 RUN_TEST(test_sqlite3_create_function_overwrite_existing);235 RUN_TEST(test_sqlite3_create_function_wrong_arity_prepare_error);236 RUN_TEST(test_sqlite3_create_function_invalid_name_fails);237 return UNITY_END();238}