# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1588888925 -7200
# Node ID 1b21c78d87066f9f65438a378b0ce42066a1988c
# Parent  813b44590d070c25d3fd79eddfa00dbbd594a2cf
SQLite: demo modul – rozšíření přidávající pár funkcí do SQL
Vzniklo v rámci práce na článku: https://blog.frantovo.cz/c/383/Komplexita%3A%20%C5%99e%C5%A1en%C3%AD%20a%C2%A0prevence

diff -r 813b44590d07 -r 1b21c78d8706 c++/sqlite-demo-modul/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/sqlite-demo-modul/Makefile	Fri May 08 00:02:05 2020 +0200
@@ -0,0 +1,20 @@
+all: libdemo.so
+
+libdemo.so: demo.cpp
+	g++ -g -shared -fPIC demo.cpp -o libdemo.so
+
+clean:
+	rm -f libdemo.so
+
+run: libdemo.so
+	echo "\
+	    SELECT 'load_extension',   load_extension('./libdemo.so'); \
+	    SELECT 'get_pid',          get_pid(); \
+	    SELECT 'value_count',      value_count(), value_count('a'), value_count('a', 'b'), value_count(1,2,3); \
+	    SELECT 'multiply',         multiply(2, 4); \
+	" | sqlite3
+
+info: libdemo.so
+	nm libdemo.so
+	ldd libdemo.so
+	file libdemo.so
diff -r 813b44590d07 -r 1b21c78d8706 c++/sqlite-demo-modul/demo.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c++/sqlite-demo-modul/demo.cpp	Fri May 08 00:02:05 2020 +0200
@@ -0,0 +1,50 @@
+#include <cstdio>
+#include <sqlite3ext.h>
+#include <unistd.h>
+
+/**
+ * This is just an example – use official documentation: https://www.sqlite.org/loadext.html
+ */
+
+#define C_API extern "C"
+#define SQL_FN(functionName) C_API void functionName (sqlite3_context* ctx, int valueCount, sqlite3_value** values)
+
+SQLITE_EXTENSION_INIT1
+
+/**
+ * Returns number of values passed to the SQL function.
+ */
+SQL_FN(valueCount) {
+	sqlite3_result_int(ctx, valueCount);
+}
+
+/**
+ * Returns current PID (process id).
+ */
+SQL_FN(getPID) {
+	sqlite3_result_int(ctx, getpid());
+}
+
+/**
+ * Returns multiplication of all arguments or zero, if there are no arguments.
+ */
+SQL_FN(multiply) {
+	sqlite3_int64 result = valueCount == 0 ? 0 : 1;
+	for (int i = 0; i < valueCount; i++) result *= sqlite3_value_int64(values[i]);
+	sqlite3_result_int64(ctx, result);
+}
+
+/**
+ * Function name should match the library file name: libdemo.so → sqlite3_demo_init.
+ * Or we can specify different entry point when loading the module.
+ */
+C_API int sqlite3_demo_init(sqlite3* db, char** error, const sqlite3_api_routines* api) {
+	SQLITE_EXTENSION_INIT2(api);
+
+	sqlite3_create_function(db, "value_count", -1, SQLITE_UTF8, nullptr, valueCount, nullptr, nullptr);
+	sqlite3_create_function(db, "get_pid", 0, SQLITE_UTF8, nullptr, getPID, nullptr, nullptr);
+	sqlite3_create_function(db, "multiply", -1, SQLITE_UTF8, nullptr, multiply, nullptr, nullptr);
+	// -1 = function accepts arbitrary number of arguments
+
+	return SQLITE_OK;
+}