Skip to content

Commit dc3f1ac

Browse files
committed
Add unit test for Database::createFunction()
using an example from https://stackoverflow.com/a/8283265/1163698 How can I create a user-defined function in SQLite?
1 parent 41cf3c5 commit dc3f1ac

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

include/SQLiteCpp/Database.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,9 @@ class Database
336336
bool abDeterministic,
337337
void* apApp,
338338
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
339-
void (*apStep)(sqlite3_context *, int, sqlite3_value **),
340-
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
341-
void (*apDestroy)(void *));
339+
void (*apStep)(sqlite3_context *, int, sqlite3_value **) = nullptr,
340+
void (*apFinal)(sqlite3_context *) = nullptr, // NOLINT(readability/casting)
341+
void (*apDestroy)(void *) = nullptr);
342342

343343
/**
344344
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
@@ -364,12 +364,12 @@ class Database
364364
bool abDeterministic,
365365
void* apApp,
366366
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
367-
void (*apStep)(sqlite3_context *, int, sqlite3_value **),
368-
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
369-
void (*apDestroy)(void *))
367+
void (*apStep)(sqlite3_context *, int, sqlite3_value **) = nullptr,
368+
void (*apFinal)(sqlite3_context *) = nullptr,
369+
void (*apDestroy)(void *) = nullptr)
370370
{
371-
return createFunction(aFuncName.c_str(), aNbArg, abDeterministic,
372-
apApp, apFunc, apStep, apFinal, apDestroy);
371+
createFunction(aFuncName.c_str(), aNbArg, abDeterministic,
372+
apApp, apFunc, apStep, apFinal, apDestroy);
373373
}
374374

375375
/**

src/Database.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,17 @@ void Database::createFunction(const char* apFuncName,
192192
bool abDeterministic,
193193
void* apApp,
194194
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
195-
void (*apStep)(sqlite3_context *, int, sqlite3_value **),
196-
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
197-
void (*apDestroy)(void *))
195+
void (*apStep)(sqlite3_context *, int, sqlite3_value **) /* = nullptr */,
196+
void (*apFinal)(sqlite3_context *) /* = nullptr */, // NOLINT(readability/casting)
197+
void (*apDestroy)(void *) /* = nullptr */)
198198
{
199-
int TextRep = SQLITE_UTF8;
199+
int textRep = SQLITE_UTF8;
200200
// optimization if deterministic function (e.g. of nondeterministic function random())
201201
if (abDeterministic)
202202
{
203-
TextRep = TextRep|SQLITE_DETERMINISTIC;
203+
textRep = textRep | SQLITE_DETERMINISTIC;
204204
}
205-
const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep,
205+
const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, textRep,
206206
apApp, apFunc, apStep, apFinal, apDestroy);
207207
check(ret);
208208
}

tests/Database_test.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,40 @@ TEST(Database, execException)
311311
EXPECT_STREQ("table test has 3 columns but 4 values were supplied", db.getErrorMsg());
312312
}
313313

314-
// TODO: test Database::createFunction()
314+
// From https://stackoverflow.com/a/8283265/1163698 How can I create a user-defined function in SQLite?
315+
static void firstchar(sqlite3_context *context, int argc, sqlite3_value **argv)
316+
{
317+
if (argc == 1)
318+
{
319+
const unsigned char *text = sqlite3_value_text(argv[0]);
320+
if (text && text[0])
321+
{
322+
char result[2];
323+
result[0] = text[0]; result[1] = '\0';
324+
sqlite3_result_text(context, result, -1, SQLITE_TRANSIENT);
325+
return;
326+
}
327+
}
328+
sqlite3_result_null(context);
329+
}
330+
331+
TEST(Database, createFunction)
332+
{
333+
// Create a new database
334+
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
335+
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
336+
337+
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
338+
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
339+
340+
// exception with SQL error: "no such function: firstchar"
341+
EXPECT_THROW(db.exec("SELECT firstchar(value) FROM test WHERE id=1"), SQLite::Exception);
342+
343+
db.createFunction("firstchar", 1, true, nullptr, &firstchar, nullptr, nullptr, nullptr);
344+
345+
EXPECT_EQ(1, db.exec("SELECT firstchar(value) FROM test WHERE id=1"));
346+
}
347+
315348
// TODO: test Database::loadExtension()
316349

317350
#ifdef SQLITE_HAS_CODEC

0 commit comments

Comments
 (0)