| /* | 
 | ** 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; | 
 | } |