/* ** 2016-08-09 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file demonstrates how to create an SQL function that is a pass-through ** for integer values (it returns a copy of its argument) but also saves the ** value that is passed through into a C-language variable. The address of ** the C-language variable is supplied as the second argument. ** ** This allows, for example, a counter to incremented and the original ** value retrieved, atomically, using a single statement: ** ** UPDATE counterTab SET cnt=remember(cnt,$PTR)+1 WHERE id=$ID ** ** Prepare the above statement once. Then to use it, bind the address ** of the output variable to $PTR using sqlite3_bind_pointer() with a ** pointer type of "carray" and bind the id of the counter to $ID and ** run the prepared statement. ** ** This implementation of the remember() function uses a "carray" ** pointer so that it can share pointers with the carray() extension. ** ** One can imagine doing similar things with floating-point values and ** strings, but this demonstration extension will stick to using just ** integers. */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> /* ** remember(V,PTR) ** ** Return the integer value V. Also save the value of V in a ** C-language variable whose address is PTR. */ static void rememberFunc( sqlite3_context *pCtx, int argc, sqlite3_value **argv ){ sqlite3_int64 v; sqlite3_int64 *ptr; assert( argc==2 ); v = sqlite3_value_int64(argv[0]); ptr = sqlite3_value_pointer(argv[1], "carray"); if( ptr ) *ptr = v; sqlite3_result_int64(pCtx, v); } #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_remember_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); rc = sqlite3_create_function(db, "remember", 2, SQLITE_UTF8, 0, rememberFunc, 0, 0); return rc; }