diff options
Diffstat (limited to 'Plugins/DbSqliteWx/extensionfunctions.c')
| -rw-r--r-- | Plugins/DbSqliteWx/extensionfunctions.c | 3952 |
1 files changed, 1975 insertions, 1977 deletions
diff --git a/Plugins/DbSqliteWx/extensionfunctions.c b/Plugins/DbSqliteWx/extensionfunctions.c index 18d1d7d..bac8449 100644 --- a/Plugins/DbSqliteWx/extensionfunctions.c +++ b/Plugins/DbSqliteWx/extensionfunctions.c @@ -1,1977 +1,1975 @@ -/*
-This library will provide common mathematical and string functions in
-SQL queries using the operating system libraries or provided
-definitions. It includes the following functions:
-
-Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference,
-degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp,
-log, log10, power, sign, sqrt, square, ceil, floor, pi.
-
-String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim,
-replace, reverse, proper, padl, padr, padc, strfilter.
-
-Aggregate: stdev, variance, mode, median, lower_quartile,
-upper_quartile.
-
-The string functions ltrim, rtrim, trim, replace are included in
-recent versions of SQLite and so by default do not build.
-
-Compilation instructions:
- Compile this C source file into a dynamic library as follows:
- * Linux:
- gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so
- * Mac OS X:
- gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib
- (You may need to add flags
- -I /opt/local/include/ -L/opt/local/lib -lwx_sqlite3
- if your wx_sqlite3 is installed from Mac ports, or
- -I /sw/include/ -L/sw/lib -lwx_sqlite3
- if installed with Fink.)
- * Windows:
- 1. Install MinGW (http://www.mingw.org/) and you will get the gcc
- (gnu compiler collection)
- 2. add the path to your path variable (isn't done during the
- installation!)
- 3. compile:
- gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c
- (path = path of wx_sqlite3ext.h; i.e. C:\programs\sqlite)
-
-Usage instructions for applications calling the wx_sqlite3 API functions:
- In your application, call wx_sqlite3_enable_load_extension(db,1) to
- allow loading external libraries. Then load the library libsqlitefunctions
- using wx_sqlite3_load_extension; the third argument should be 0.
- See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions.
- Select statements may now use these functions, as in
- SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544;
-
-Usage instructions for the wx_sqlite3 program:
- If the program is built so that loading extensions is permitted,
- the following will work:
- sqlite> SELECT load_extension('./libsqlitefunctions.so');
- sqlite> select cos(radians(45));
- 0.707106781186548
- Note: Loading extensions is by default prohibited as a
- security measure; see "Security Considerations" in
- http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions.
- If the wx_sqlite3 program and library are built this
- way, you cannot use these functions from the program, you
- must write your own program using the wx_sqlite3 API, and call
- wx_sqlite3_enable_load_extension as described above, or else
- rebuilt the wx_sqlite3 program to allow loadable extensions.
-
-Alterations:
-The instructions are for Linux, Mac OS X, and Windows; users of other
-OSes may need to modify this procedure. In particular, if your math
-library lacks one or more of the needed trig or log functions, comment
-out the appropriate HAVE_ #define at the top of file. If you do not
-wish to make a loadable module, comment out the define for
-COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. If you are using a
-version of SQLite without the trim functions and replace, comment out
-the HAVE_TRIM #define.
-
-Liam Healy
-
-History:
-2010-01-06 Correct check for argc in squareFunc, and add Windows
-compilation instructions.
-2009-06-24 Correct check for argc in properFunc.
-2008-09-14 Add check that memory was actually allocated after
-wx_sqlite3_malloc or wx_sqlite3StrDup, call wx_sqlite3_result_error_nomem if
-not. Thanks to Robert Simpson.
-2008-06-13 Change to instructions to indicate use of the math library
-and that program might work.
-2007-10-01 Minor clarification to instructions.
-2007-09-29 Compilation as loadable module is optional with
-COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE.
-2007-09-28 Use wx_sqlite3_extension_init and macros
-SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with
-wx_sqlite3_load_extension. Thanks to Eric Higashino and Joe Wilson.
-New instructions for Mac compilation.
-2007-09-17 With help from Joe Wilson and Nuno Luca, made use of
-external interfaces so that compilation is no longer dependent on
-SQLite source code. Merged source, header, and README into a single
-file. Added casts so that Mac will compile without warnings (unsigned
-and signed char).
-2007-09-05 Included some definitions from sqlite 3.3.13 so that this
-will continue to work in newer versions of sqlite. Completed
-description of functions available.
-2007-03-27 Revised description.
-2007-03-23 Small cleanup and a bug fix on the code. This was mainly
-letting errno flag errors encountered in the math library and checking
-the result, rather than pre-checking. This fixes a bug in power that
-would cause an error if any non-positive number was raised to any
-power.
-2007-02-07 posted by Mikey C to sqlite mailing list.
-Original code 2006 June 05 by relicoder.
-
-*/
-
-//#include "config.h"
-
-//#define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1
-#if defined(_MSC_VER) && _MSC_VER <= 1700
-#else
-#define HAVE_ACOSH 1
-#define HAVE_ASINH 1
-#define HAVE_ATANH 1
-#endif
-#define HAVE_SINH 1
-#define HAVE_COSH 1
-#define HAVE_TANH 1
-#define HAVE_LOG10 1
-#if defined(_MSC_VER) && _MSC_VER <= 1700
-#else
-#define HAVE_ISBLANK 1
-#endif
-#define SQLITE_SOUNDEX 1
-#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */
-
-#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
-#include "wx_sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-#else
-#include "wxwx_sqlite3.h"
-#endif
-
-#include <ctype.h>
-/* relicoder */
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h> /* LMH 2007-03-25 */
-
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef _MAP_H_
-#define _MAP_H_
-
-#if 0
-#if !defined(SQLITE_OS_WIN) || !defined(_MSC_VER)
-#include <stdint.h>
-#else
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef signed int int16_t;
-typedef unsigned int uint16_t;
-typedef signed long int int32_t;
-typedef unsigned long int uint32_t;
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#endif
-#endif
-
-/*
-** Simple binary tree implementation to use in median, mode and quartile calculations
-** Tree is not necessarily balanced. That would require something like red&black trees of AVL
-*/
-
-typedef int(*cmp_func)(const void *, const void *);
-typedef void(*map_iterator)(void*, i64, void*);
-
-typedef struct node{
- struct node *l;
- struct node *r;
- void* data;
- i64 count;
-} node;
-
-typedef struct map{
- node *base;
- cmp_func cmp;
- short free;
-} map;
-
-/*
-** creates a map given a comparison function
-*/
-map map_make(cmp_func cmp);
-
-/*
-** inserts the element e into map m
-*/
-void map_insert(map *m, void *e);
-
-/*
-** executes function iter over all elements in the map, in key increasing order
-*/
-void map_iterate(map *m, map_iterator iter, void* p);
-
-/*
-** frees all memory used by a map
-*/
-void map_destroy(map *m);
-
-/*
-** compares 2 integers
-** to use with map_make
-*/
-int int_cmp(const void *a, const void *b);
-
-/*
-** compares 2 doubles
-** to use with map_make
-*/
-int double_cmp(const void *a, const void *b);
-
-#endif /* _MAP_H_ */
-
-//typedef uint8_t u8;
-//typedef uint16_t u16;
-//typedef int64_t i64;
-
-static char *wx_sqlite3StrDup( const char *z ) {
- char *res = wx_sqlite3_malloc( strlen(z)+1 );
- return strcpy( res, z );
-}
-
-/*
-** These are copied verbatim from fun.c so as to not have the names exported
-*/
-
-/* LMH from wx_sqlite3 3.3.13 */
-/*
-** This table maps from the first byte of a UTF-8 character to the number
-** of trailing bytes expected. A value '4' indicates that the table key
-** is not a legal first byte for a UTF-8 character.
-*/
-static const u8 xtra_utf8_bytes[256] = {
-/* 0xxxxxxx */
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-/* 10wwwwww */
-4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-
-/* 110yyyyy */
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-/* 1110zzzz */
-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-/* 11110yyy */
-3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
-};
-
-
-/*
-** This table maps from the number of trailing bytes in a UTF-8 character
-** to an integer constant that is effectively calculated for each character
-** read by a naive implementation of a UTF-8 character reader. The code
-** in the READ_UTF8 macro explains things best.
-*/
-static const int xtra_utf8_bits[] = {
- 0,
- 12416, /* (0xC0 << 6) + (0x80) */
- 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */
- 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */
-};
-
-/*
-** If a UTF-8 character contains N bytes extra bytes (N bytes follow
-** the initial byte so that the total character length is N+1) then
-** masking the character with utf8_mask[N] must produce a non-zero
-** result. Otherwise, we have an (illegal) overlong encoding.
-*/
-static const int utf_mask[] = {
- 0x00000000,
- 0xffffff80,
- 0xfffff800,
- 0xffff0000,
-};
-
-/* LMH salvaged from wx_sqlite3 3.3.13 source code src/utf.c */
-#define EXTFUNC_READ_UTF8(zIn, c) { \
- int xtra; \
- c = *(zIn)++; \
- xtra = xtra_utf8_bytes[c]; \
- switch( xtra ){ \
- case 4: c = (int)0xFFFD; break; \
- case 3: c = (c<<6) + *(zIn)++; \
- case 2: c = (c<<6) + *(zIn)++; \
- case 1: c = (c<<6) + *(zIn)++; \
- c -= xtra_utf8_bits[xtra]; \
- if( (utf_mask[xtra]&c)==0 \
- || (c&0xFFFFF800)==0xD800 \
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
- } \
-}
-
-static int wx_sqlite3ReadUtf8(const unsigned char *z){
- int c;
- EXTFUNC_READ_UTF8(z, c);
- return c;
-}
-
-#define SKIP_UTF8(zIn) { \
- zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \
-}
-
-#if 0
-/*
-** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
-** return the number of unicode characters in pZ up to (but not including)
-** the first 0x00 byte. If nByte is not less than zero, return the
-** number of unicode characters in the first nByte of pZ (or up to
-** the first 0x00, whichever comes first).
-*/
-static int wx_sqlite3Utf8CharLen(const char *z, int nByte){
- int r = 0;
- const char *zTerm;
- if( nByte>=0 ){
- zTerm = &z[nByte];
- }else{
- zTerm = (const char *)(-1);
- }
- assert( z<=zTerm );
- while( *z!=0 && z<zTerm ){
- SKIP_UTF8(z);
- r++;
- }
- return r;
-}
-#endif
-
-/*
-** X is a pointer to the first byte of a UTF-8 character. Increment
-** X so that it points to the next character. This only works right
-** if X points to a well-formed UTF-8 string.
-*/
-#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
-#define sqliteCharVal(X) wx_sqlite3ReadUtf8(X)
-
-/*
-** This is a macro that facilitates writting wrappers for math.h functions
-** it creates code for a function to use in SQlite that gets one numeric input
-** and returns a floating point value.
-**
-** Could have been implemented using pointers to functions but this way it's inline
-** and thus more efficient. Lower * ranking though...
-**
-** Parameters:
-** name: function name to de defined (eg: sinFunc)
-** function: function defined in math.h to wrap (eg: sin)
-** domain: boolean condition that CAN'T happen in terms of the input parameter rVal
-** (eg: rval<0 for sqrt)
-*/
-/* LMH 2007-03-25 Changed to use errno and remove domain; no pre-checking for errors. */
-#define GEN_MATH_WRAP_DOUBLE_1(name, function) \
-static void name(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){\
- double rVal = 0.0, val;\
- assert( argc==1 );\
- switch( wx_sqlite3_value_type(argv[0]) ){\
- case SQLITE_NULL: {\
- wx_sqlite3_result_null(context);\
- break;\
- }\
- default: {\
- rVal = wx_sqlite3_value_double(argv[0]);\
- errno = 0;\
- val = function(rVal);\
- if (errno == 0) {\
- wx_sqlite3_result_double(context, val);\
- } else {\
- wx_sqlite3_result_error(context, strerror(errno), errno);\
- }\
- break;\
- }\
- }\
-}\
-
-
-/*
-** Example of GEN_MATH_WRAP_DOUBLE_1 usage
-** this creates function sqrtFunc to wrap the math.h standard function sqrt(x)=x^0.5
-*/
-GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt)
-
-/* trignometric functions */
-GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos)
-GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin)
-GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan)
-
-/*
-** Many of systems don't have inverse hyperbolic trig functions so this will emulate
-** them on those systems in terms of log and sqrt (formulas are too trivial to demand
-** written proof here)
-*/
-
-#ifndef HAVE_ACOSH
-static double acosh(double x){
- return log(x + sqrt(x*x - 1.0));
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh)
-
-#ifndef HAVE_ASINH
-static double asinh(double x){
- return log(x + sqrt(x*x + 1.0));
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh)
-
-#ifndef HAVE_ATANH
-static double atanh(double x){
- return (1.0/2.0)*log((1+x)/(1-x)) ;
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh)
-
-/*
-** math.h doesn't require cot (cotangent) so it's defined here
-*/
-static double cot(double x){
- return 1.0/tan(x);
-}
-
-GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin)
-GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos)
-GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan)
-GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot)
-
-static double coth(double x){
- return 1.0/tanh(x);
-}
-
-/*
-** Many systems don't have hyperbolic trigonometric functions so this will emulate
-** them on those systems directly from the definition in terms of exp
-*/
-#ifndef HAVE_SINH
-static double sinh(double x){
- return (exp(x)-exp(-x))/2.0;
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh)
-
-#ifndef HAVE_COSH
-static double cosh(double x){
- return (exp(x)+exp(-x))/2.0;
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh)
-
-#ifndef HAVE_TANH
-static double tanh(double x){
- return sinh(x)/cosh(x);
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh)
-
-GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth)
-
-/*
-** Some systems lack log in base 10. This will emulate it
-*/
-
-#ifndef HAVE_LOG10
-static double log10(double x){
- static double l10 = -1.0;
- if( l10<0.0 ){
- l10 = log(10.0);
- }
- return log(x)/l10;
-}
-#endif
-
-GEN_MATH_WRAP_DOUBLE_1(logFunc, log)
-GEN_MATH_WRAP_DOUBLE_1(log10Func, log10)
-GEN_MATH_WRAP_DOUBLE_1(expFunc, exp)
-
-/*
-** Fallback for systems where math.h doesn't define M_PI
-*/
-#undef M_PI
-#ifndef M_PI
-/*
-** static double PI = acos(-1.0);
-** #define M_PI (PI)
-*/
-#define M_PI 3.14159265358979323846
-#endif
-
-/* Convert Degrees into Radians */
-static double deg2rad(double x){
- return x*M_PI/180.0;
-}
-
-/* Convert Radians into Degrees */
-static double rad2deg(double x){
- return 180.0*x/M_PI;
-}
-
-GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg)
-GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad)
-
-/* constant function that returns the value of PI=3.1415... */
-static void piFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- wx_sqlite3_result_double(context, M_PI);
-}
-
-/*
-** Implements the sqrt function, it has the peculiarity of returning an integer when the
-** the argument is an integer.
-** Since SQLite isn't strongly typed (almost untyped actually) this is a bit pedantic
-*/
-static void squareFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- i64 iVal = 0;
- double rVal = 0.0;
- assert( argc==1 );
- switch( wx_sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: {
- iVal = wx_sqlite3_value_int64(argv[0]);
- wx_sqlite3_result_int64(context, iVal*iVal);
- break;
- }
- case SQLITE_NULL: {
- wx_sqlite3_result_null(context);
- break;
- }
- default: {
- rVal = wx_sqlite3_value_double(argv[0]);
- wx_sqlite3_result_double(context, rVal*rVal);
- break;
- }
- }
-}
-
-/*
-** Wraps the pow math.h function
-** When both the base and the exponent are integers the result should be integer
-** (see sqrt just before this). Here the result is always double
-*/
-/* LMH 2007-03-25 Changed to use errno; no pre-checking for errors. Also removes
- but that was present in the pre-checking that called wx_sqlite3_result_error on
- a non-positive first argument, which is not always an error. */
-static void powerFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- double r1 = 0.0;
- double r2 = 0.0;
- double val;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- r1 = wx_sqlite3_value_double(argv[0]);
- r2 = wx_sqlite3_value_double(argv[1]);
- errno = 0;
- val = pow(r1,r2);
- if (errno == 0) {
- wx_sqlite3_result_double(context, val);
- } else {
- wx_sqlite3_result_error(context, strerror(errno), errno);
- }
- }
-}
-
-/*
-** atan2 wrapper
-*/
-static void atn2Func(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- double r1 = 0.0;
- double r2 = 0.0;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- r1 = wx_sqlite3_value_double(argv[0]);
- r2 = wx_sqlite3_value_double(argv[1]);
- wx_sqlite3_result_double(context, atan2(r1,r2));
- }
-}
-
-/*
-** Implementation of the sign() function
-** return one of 3 possibilities +1,0 or -1 when the argument is respectively
-** positive, 0 or negative.
-** When the argument is NULL the result is also NULL (completly conventional)
-*/
-static void signFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- double rVal=0.0;
- i64 iVal=0;
- assert( argc==1 );
- switch( wx_sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: {
- iVal = wx_sqlite3_value_int64(argv[0]);
- iVal = ( iVal > 0) ? 1: ( iVal < 0 ) ? -1: 0;
- wx_sqlite3_result_int64(context, iVal);
- break;
- }
- case SQLITE_NULL: {
- wx_sqlite3_result_null(context);
- break;
- }
- default: {
- /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0; */
-
- rVal = wx_sqlite3_value_double(argv[0]);
- rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0;
- wx_sqlite3_result_double(context, rVal);
- break;
- }
- }
-}
-
-
-/*
-** smallest integer value not less than argument
-*/
-static void ceilFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- double rVal=0.0;
- i64 iVal=0;
- assert( argc==1 );
- switch( wx_sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: {
- i64 iVal = wx_sqlite3_value_int64(argv[0]);
- wx_sqlite3_result_int64(context, iVal);
- break;
- }
- case SQLITE_NULL: {
- wx_sqlite3_result_null(context);
- break;
- }
- default: {
- rVal = wx_sqlite3_value_double(argv[0]);
- wx_sqlite3_result_int64(context, (i64) ceil(rVal));
- break;
- }
- }
-}
-
-/*
-** largest integer value not greater than argument
-*/
-static void floorFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- double rVal=0.0;
- i64 iVal=0;
- assert( argc==1 );
- switch( wx_sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: {
- i64 iVal = wx_sqlite3_value_int64(argv[0]);
- wx_sqlite3_result_int64(context, iVal);
- break;
- }
- case SQLITE_NULL: {
- wx_sqlite3_result_null(context);
- break;
- }
- default: {
- rVal = wx_sqlite3_value_double(argv[0]);
- wx_sqlite3_result_int64(context, (i64) floor(rVal));
- break;
- }
- }
-}
-
-/*
-** Given a string (s) in the first argument and an integer (n) in the second returns the
-** string that constains s contatenated n times
-*/
-static void replicateFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- unsigned char *z; /* input string */
- unsigned char *zo; /* result string */
- i64 iCount; /* times to repeat */
- i64 nLen; /* length of the input string (no multibyte considerations) */
- i64 nTLen; /* length of the result string (no multibyte considerations) */
- i64 i=0;
-
- if( argc!=2 || SQLITE_NULL==wx_sqlite3_value_type(argv[0]) )
- return;
-
- iCount = wx_sqlite3_value_int64(argv[1]);
-
- if( iCount<0 ){
- wx_sqlite3_result_error(context, "domain error", -1);
- }else{
-
- nLen = wx_sqlite3_value_bytes(argv[0]);
- nTLen = nLen*iCount;
- z=wx_sqlite3_malloc(nTLen+1);
- zo=wx_sqlite3_malloc(nLen+1);
- if (!z || !zo){
- wx_sqlite3_result_error_nomem(context);
- if (z) wx_sqlite3_free(z);
- if (zo) wx_sqlite3_free(zo);
- return;
- }
- strcpy((char*)zo, (char*)wx_sqlite3_value_text(argv[0]));
-
- for(i=0; i<iCount; ++i){
- strcpy((char*)(z+i*nLen), (char*)zo);
- }
-
- wx_sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(z);
- wx_sqlite3_free(zo);
- }
-}
-
-/*
-** Some systems (win32 among others) don't have an isblank function, this will emulate it.
-** This function is not UFT-8 safe since it only analyses a byte character.
-*/
-#ifndef HAVE_ISBLANK
-int isblank(char c){
- return( ' '==c || '\t'==c );
-}
-#endif
-
-static void properFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const unsigned char *z; /* input string */
- unsigned char *zo; /* output string */
- unsigned char *zt; /* iterator */
- char r;
- int c=1;
-
- assert( argc==1);
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
-
- z = wx_sqlite3_value_text(argv[0]);
- zo = (unsigned char *)wx_sqlite3StrDup((char *) z);
- if (!zo) {
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- zt = zo;
-
- while( (r = *(z++))!=0 ){
- if( isblank(r) ){
- c=1;
- }else{
- if( c==1 ){
- r = toupper(r);
- }else{
- r = tolower(r);
- }
- c=0;
- }
- *(zt++) = r;
- }
- *zt = '\0';
-
- wx_sqlite3_result_text(context, (char*)zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
-}
-
-/*
-** given an input string (s) and an integer (n) adds spaces at the begining of s
-** until it has a length of n characters.
-** When s has a length >=n it's a NOP
-** padl(NULL) = NULL
-*/
-static void padlFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- i64 ilen; /* length to pad to */
- i64 zl; /* length of the input string (UTF-8 chars) */
- int i = 0;
- const char *zi; /* input string */
- char *zo; /* output string */
- char *zt;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- zi = (char *)wx_sqlite3_value_text(argv[0]);
- ilen = wx_sqlite3_value_int64(argv[1]);
- /* check domain */
- if(ilen<0){
- wx_sqlite3_result_error(context, "domain error", -1);
- return;
- }
- zl = wx_sqlite3Utf8CharLen(zi, -1);
- if( zl>=ilen ){
- /* string is longer than the requested pad length, return the same string (dup it) */
- zo = wx_sqlite3StrDup(zi);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- }else{
- zo = wx_sqlite3_malloc(strlen(zi)+ilen-zl+1);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- zt = zo;
- for(i=1; i+zl<=ilen; ++i){
- *(zt++)=' ';
- }
- /* no need to take UTF-8 into consideration here */
- strcpy(zt,zi);
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
- }
-}
-
-/*
-** given an input string (s) and an integer (n) appends spaces at the end of s
-** until it has a length of n characters.
-** When s has a length >=n it's a NOP
-** padl(NULL) = NULL
-*/
-static void padrFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- i64 ilen; /* length to pad to */
- i64 zl; /* length of the input string (UTF-8 chars) */
- i64 zll; /* length of the input string (bytes) */
- int i = 0;
- const char *zi; /* input string */
- char *zo; /* output string */
- char *zt;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- zi = (char *)wx_sqlite3_value_text(argv[0]);
- ilen = wx_sqlite3_value_int64(argv[1]);
- /* check domain */
- if(ilen<0){
- wx_sqlite3_result_error(context, "domain error", -1);
- return;
- }
- zl = wx_sqlite3Utf8CharLen(zi, -1);
- if( zl>=ilen ){
- /* string is longer than the requested pad length, return the same string (dup it) */
- zo = wx_sqlite3StrDup(zi);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- }else{
- zll = strlen(zi);
- zo = wx_sqlite3_malloc(zll+ilen-zl+1);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- zt = strcpy(zo,zi)+zll;
- for(i=1; i+zl<=ilen; ++i){
- *(zt++) = ' ';
- }
- *zt = '\0';
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
- }
-}
-
-/*
-** given an input string (s) and an integer (n) appends spaces at the end of s
-** and adds spaces at the begining of s until it has a length of n characters.
-** Tries to add has many characters at the left as at the right.
-** When s has a length >=n it's a NOP
-** padl(NULL) = NULL
-*/
-static void padcFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- i64 ilen; /* length to pad to */
- i64 zl; /* length of the input string (UTF-8 chars) */
- i64 zll; /* length of the input string (bytes) */
- int i = 0;
- const char *zi; /* input string */
- char *zo; /* output string */
- char *zt;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- zi = (char *)wx_sqlite3_value_text(argv[0]);
- ilen = wx_sqlite3_value_int64(argv[1]);
- /* check domain */
- if(ilen<0){
- wx_sqlite3_result_error(context, "domain error", -1);
- return;
- }
- zl = wx_sqlite3Utf8CharLen(zi, -1);
- if( zl>=ilen ){
- /* string is longer than the requested pad length, return the same string (dup it) */
- zo = wx_sqlite3StrDup(zi);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- }else{
- zll = strlen(zi);
- zo = wx_sqlite3_malloc(zll+ilen-zl+1);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- zt = zo;
- for(i=1; 2*i+zl<=ilen; ++i){
- *(zt++) = ' ';
- }
- strcpy(zt, zi);
- zt+=zll;
- for(; i+zl<=ilen; ++i){
- *(zt++) = ' ';
- }
- *zt = '\0';
- }
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
- }
-}
-
-/*
-** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed
-** assumes strings are UTF-8 encoded
-*/
-static void strfilterFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *zi1; /* first parameter string (searched string) */
- const char *zi2; /* second parameter string (vcontains valid characters) */
- const char *z1;
- const char *z21;
- const char *z22;
- char *zo; /* output string */
- char *zot;
- int c1 = 0;
- int c2 = 0;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- }else{
- zi1 = (char *)wx_sqlite3_value_text(argv[0]);
- zi2 = (char *)wx_sqlite3_value_text(argv[1]);
- /*
- ** maybe I could allocate less, but that would imply 2 passes, rather waste
- ** (possibly) some memory
- */
- zo = wx_sqlite3_malloc(strlen(zi1)+1);
- if (!zo){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- zot = zo;
- z1 = zi1;
- while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){
- z21=zi2;
- while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){
- sqliteNextChar(z21);
- }
- if( c2!=0){
- z22=z21;
- sqliteNextChar(z22);
- strncpy(zot, z21, z22-z21);
- zot+=z22-z21;
- }
- sqliteNextChar(z1);
- }
- *zot = '\0';
-
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
- }
-}
-
-/*
-** Given a string z1, retutns the (0 based) index of it's first occurence
-** in z2 after the first s characters.
-** Returns -1 when there isn't a match.
-** updates p to point to the character where the match occured.
-** This is an auxiliary function.
-*/
-static int _substr(const char* z1, const char* z2, int s, const char** p){
- int c = 0;
- int rVal=-1;
- const char* zt1;
- const char* zt2;
- int c1,c2;
-
- if( '\0'==*z1 ){
- return -1;
- }
-
- while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)<s){
- sqliteNextChar(z2);
- }
-
- c = 0;
- while( (sqliteCharVal((unsigned char *)z2)) != 0 ){
- zt1 = z1;
- zt2 = z2;
-
- do{
- c1 = sqliteCharVal((unsigned char *)zt1);
- c2 = sqliteCharVal((unsigned char *)zt2);
- sqliteNextChar(zt1);
- sqliteNextChar(zt2);
- }while( c1 == c2 && c1 != 0 && c2 != 0 );
-
- if( c1 == 0 ){
- rVal = c;
- break;
- }
-
- sqliteNextChar(z2);
- ++c;
- }
- if(p){
- *p=z2;
- }
- return rVal >=0 ? rVal+s : rVal;
-}
-
-/*
-** given 2 input strings (s1,s2) and an integer (n) searches from the nth character
-** for the string s1. Returns the position where the match occured.
-** Characters are counted from 1.
-** 0 is returned when no match occurs.
-*/
-
-static void charindexFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const u8 *z1; /* s1 string */
- u8 *z2; /* s2 string */
- int s=0;
- int rVal=0;
-
- assert( argc==3 ||argc==2);
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) || SQLITE_NULL==wx_sqlite3_value_type(argv[1])){
- wx_sqlite3_result_null(context);
- return;
- }
-
- z1 = wx_sqlite3_value_text(argv[0]);
- if( z1==0 ) return;
- z2 = (u8*) wx_sqlite3_value_text(argv[1]);
- if(argc==3){
- s = wx_sqlite3_value_int(argv[2])-1;
- if(s<0){
- s=0;
- }
- }else{
- s = 0;
- }
-
- rVal = _substr((char *)z1,(char *)z2,s,NULL);
- wx_sqlite3_result_int(context, rVal+1);
-}
-
-/*
-** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters
-** if the string has a length<=n or is NULL this function is NOP
-*/
-static void leftFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- int c=0;
- int cc=0;
- int l=0;
- const unsigned char *z; /* input string */
- const unsigned char *zt;
- unsigned char *rz; /* output string */
-
- assert( argc==2);
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) || SQLITE_NULL==wx_sqlite3_value_type(argv[1])){
- wx_sqlite3_result_null(context);
- return;
- }
-
- z = wx_sqlite3_value_text(argv[0]);
- l = wx_sqlite3_value_int(argv[1]);
- zt = z;
-
- while( sqliteCharVal(zt) && c++<l)
- sqliteNextChar(zt);
-
- cc=zt-z;
-
- rz = wx_sqlite3_malloc(zt-z+1);
- if (!rz){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- strncpy((char*) rz, (char*) z, zt-z);
- *(rz+cc) = '\0';
- wx_sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(rz);
-}
-
-/*
-** given a string (s) and an integer (n) returns the n rightmost (UTF-8) characters
-** if the string has a length<=n or is NULL this function is NOP
-*/
-static void rightFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- int l=0;
- int c=0;
- int cc=0;
- const char *z;
- const char *zt;
- const char *ze;
- char *rz;
-
- assert( argc==2);
-
- if( SQLITE_NULL == wx_sqlite3_value_type(argv[0]) || SQLITE_NULL == wx_sqlite3_value_type(argv[1])){
- wx_sqlite3_result_null(context);
- return;
- }
-
- z = (char *)wx_sqlite3_value_text(argv[0]);
- l = wx_sqlite3_value_int(argv[1]);
- zt = z;
-
- while( sqliteCharVal((unsigned char *)zt)!=0){
- sqliteNextChar(zt);
- ++c;
- }
-
- ze = zt;
- zt = z;
-
- cc=c-l;
- if(cc<0)
- cc=0;
-
- while( cc-- > 0 ){
- sqliteNextChar(zt);
- }
-
- rz = wx_sqlite3_malloc(ze-zt+1);
- if (!rz){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- strcpy((char*) rz, (char*) (zt));
- wx_sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(rz);
-}
-
-#ifndef HAVE_TRIM
-/*
-** removes the whitespaces at the begining of a string.
-*/
-const char* ltrim(const char* s){
- while( *s==' ' )
- ++s;
- return s;
-}
-
-/*
-** removes the whitespaces at the end of a string.
-** !mutates the input string!
-*/
-void rtrim(char* s){
- char* ss = s+strlen(s)-1;
- while( ss>=s && *ss==' ' )
- --ss;
- *(ss+1)='\0';
-}
-
-/*
-** Removes the whitespace at the begining of a string
-*/
-static void ltrimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *z;
-
- assert( argc==1);
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
- z = wx_sqlite3_value_text(argv[0]);
- wx_sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT);
-}
-
-/*
-** Removes the whitespace at the end of a string
-*/
-static void rtrimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *z;
- char *rz;
- /* try not to change data in argv */
-
- assert( argc==1);
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
- z = wx_sqlite3_value_text(argv[0]);
- rz = wx_sqlite3StrDup(z);
- rtrim(rz);
- wx_sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(rz);
-}
-
-/*
-** Removes the whitespace at the begining and end of a string
-*/
-static void trimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *z;
- char *rz;
- /* try not to change data in argv */
-
- assert( argc==1);
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
- z = wx_sqlite3_value_text(argv[0]);
- rz = wx_sqlite3StrDup(z);
- rtrim(rz);
- wx_sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(rz);
-}
-#endif
-
-/*
-** given a pointer to a string s1, the length of that string (l1), a new string (s2)
-** and it's length (l2) appends s2 to s1.
-** All lengths in bytes.
-** This is just an auxiliary function
-*/
-// static void _append(char **s1, int l1, const char *s2, int l2){
-// *s1 = realloc(*s1, (l1+l2+1)*sizeof(char));
-// strncpy((*s1)+l1, s2, l2);
-// *(*(s1)+l1+l2) = '\0';
-// }
-
-#ifndef HAVE_TRIM
-
-/*
-** given strings s, s1 and s2 replaces occurrences of s1 in s by s2
-*/
-static void replaceFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *z1; /* string s (first parameter) */
- const char *z2; /* string s1 (second parameter) string to look for */
- const char *z3; /* string s2 (third parameter) string to replace occurrences of s1 with */
- int lz1;
- int lz2;
- int lz3;
- int lzo=0;
- char *zo=0;
- int ret=0;
- const char *zt1;
- const char *zt2;
-
- assert( 3==argc );
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
-
- z1 = wx_sqlite3_value_text(argv[0]);
- z2 = wx_sqlite3_value_text(argv[1]);
- z3 = wx_sqlite3_value_text(argv[2]);
- /* handle possible null values */
- if( 0==z2 ){
- z2="";
- }
- if( 0==z3 ){
- z3="";
- }
-
- lz1 = strlen(z1);
- lz2 = strlen(z2);
- lz3 = strlen(z3);
-
-#if 0
- /* special case when z2 is empty (or null) nothing will be changed */
- if( 0==lz2 ){
- wx_sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT);
- return;
- }
-#endif
-
- zt1=z1;
- zt2=z1;
-
- while(1){
- ret=_substr(z2,zt1 , 0, &zt2);
-
- if( ret<0 )
- break;
-
- _append(&zo, lzo, zt1, zt2-zt1);
- lzo+=zt2-zt1;
- _append(&zo, lzo, z3, lz3);
- lzo+=lz3;
-
- zt1=zt2+lz2;
- }
- _append(&zo, lzo, zt1, lz1-(zt1-z1));
- wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(zo);
-}
-#endif
-
-/*
-** given a string returns the same string but with the characters in reverse order
-*/
-static void reverseFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- const char *z;
- const char *zt;
- char *rz;
- char *rzt;
- int l = 0;
- int i = 0;
-
- assert( 1==argc );
-
- if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){
- wx_sqlite3_result_null(context);
- return;
- }
- z = (char *)wx_sqlite3_value_text(argv[0]);
- l = strlen(z);
- rz = wx_sqlite3_malloc(l+1);
- if (!rz){
- wx_sqlite3_result_error_nomem(context);
- return;
- }
- rzt = rz+l;
- *(rzt--) = '\0';
-
- zt=z;
- while( sqliteCharVal((unsigned char *)zt)!=0 ){
- z=zt;
- sqliteNextChar(zt);
- for(i=1; zt-i>=z; ++i){
- *(rzt--)=*(zt-i);
- }
- }
-
- wx_sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT);
- wx_sqlite3_free(rz);
-}
-
-/*
-** An instance of the following structure holds the context of a
-** stdev() or variance() aggregate computation.
-** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II
-** less prone to rounding errors
-*/
-typedef struct StdevCtx StdevCtx;
-struct StdevCtx {
- double rM;
- double rS;
- i64 cnt; /* number of elements */
-};
-
-/*
-** An instance of the following structure holds the context of a
-** mode() or median() aggregate computation.
-** Depends on structures defined in map.c (see map & map)
-** These aggregate functions only work for integers and floats although
-** they could be made to work for strings. This is usually considered meaningless.
-** Only usuall order (for median), no use of collation functions (would this even make sense?)
-*/
-typedef struct ModeCtx ModeCtx;
-struct ModeCtx {
- i64 riM; /* integer value found so far */
- double rdM; /* double value found so far */
- i64 cnt; /* number of elements so far */
- double pcnt; /* number of elements smaller than a percentile */
- i64 mcnt; /* maximum number of occurrences (for mode) */
- i64 mn; /* number of occurrences (for mode and percentiles) */
- i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */
- map* m; /* map structure used for the computation */
- int done; /* whether the answer has been found */
-};
-
-/*
-** called for each value received during a calculation of stdev or variance
-*/
-static void varianceStep(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- StdevCtx *p;
-
- double delta;
- double x;
-
- assert( argc==1 );
- p = wx_sqlite3_aggregate_context(context, sizeof(*p));
- /* only consider non-null values */
- if( SQLITE_NULL != wx_sqlite3_value_numeric_type(argv[0]) ){
- p->cnt++;
- x = wx_sqlite3_value_double(argv[0]);
- delta = (x-p->rM);
- p->rM += delta/p->cnt;
- p->rS += delta*(x-p->rM);
- }
-}
-
-/*
-** called for each value received during a calculation of mode of median
-*/
-static void modeStep(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- ModeCtx *p;
- i64 xi=0;
- double xd=0.0;
- i64 *iptr;
- double *dptr;
- int type;
-
- assert( argc==1 );
- type = wx_sqlite3_value_numeric_type(argv[0]);
-
- if( type == SQLITE_NULL)
- return;
-
- p = wx_sqlite3_aggregate_context(context, sizeof(*p));
-
- if( 0==(p->m) ){
- p->m = calloc(1, sizeof(map));
- if( type==SQLITE_INTEGER ){
- /* map will be used for integers */
- *(p->m) = map_make(int_cmp);
- p->is_double = 0;
- }else{
- p->is_double = 1;
- /* map will be used for doubles */
- *(p->m) = map_make(double_cmp);
- }
- }
-
- ++(p->cnt);
-
- if( 0==p->is_double ){
- xi = wx_sqlite3_value_int64(argv[0]);
- iptr = (i64*)calloc(1,sizeof(i64));
- *iptr = xi;
- map_insert(p->m, iptr);
- }else{
- xd = wx_sqlite3_value_double(argv[0]);
- dptr = (double*)calloc(1,sizeof(double));
- *dptr = xd;
- map_insert(p->m, dptr);
- }
-}
-
-/*
-** Auxiliary function that iterates all elements in a map and finds the mode
-** (most frequent value)
-*/
-static void modeIterate(void* e, i64 c, void* pp){
- i64 ei;
- double ed;
- ModeCtx *p = (ModeCtx*)pp;
-
- if( 0==p->is_double ){
- ei = *(int*)(e);
-
- if( p->mcnt==c ){
- ++p->mn;
- }else if( p->mcnt<c ){
- p->riM = ei;
- p->mcnt = c;
- p->mn=1;
- }
- }else{
- ed = *(double*)(e);
-
- if( p->mcnt==c ){
- ++p->mn;
- }else if(p->mcnt<c){
- p->rdM = ed;
- p->mcnt = c;
- p->mn=1;
- }
- }
-}
-
-/*
-** Auxiliary function that iterates all elements in a map and finds the median
-** (the value such that the number of elements smaller is equal the the number of
-** elements larger)
-*/
-static void medianIterate(void* e, i64 c, void* pp){
- i64 ei;
- double ed;
- double iL;
- double iR;
- int il;
- int ir;
- ModeCtx *p = (ModeCtx*)pp;
-
- if(p->done>0)
- return;
-
- iL = p->pcnt;
- iR = p->cnt - p->pcnt;
- il = p->mcnt + c;
- ir = p->cnt - p->mcnt;
-
- if( il >= iL ){
- if( ir >= iR ){
- ++p->mn;
- if( 0==p->is_double ){
- ei = *(int*)(e);
- p->riM += ei;
- }else{
- ed = *(double*)(e);
- p->rdM += ed;
- }
- }else{
- p->done=1;
- }
- }
- p->mcnt+=c;
-}
-
-/*
-** Returns the mode value
-*/
-static void modeFinalize(wx_sqlite3_context *context){
- ModeCtx *p;
- p = wx_sqlite3_aggregate_context(context, 0);
- if( p && p->m ){
- map_iterate(p->m, modeIterate, p);
- map_destroy(p->m);
- free(p->m);
-
- if( 1==p->mn ){
- if( 0==p->is_double )
- wx_sqlite3_result_int64(context, p->riM);
- else
- wx_sqlite3_result_double(context, p->rdM);
- }
- }
-}
-
-/*
-** auxiliary function for percentiles
-*/
-static void _medianFinalize(wx_sqlite3_context *context){
- ModeCtx *p;
- p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0);
- if( p && p->m ){
- p->done=0;
- map_iterate(p->m, medianIterate, p);
- map_destroy(p->m);
- free(p->m);
-
- if( 0==p->is_double )
- if( 1==p->mn )
- wx_sqlite3_result_int64(context, p->riM);
- else
- wx_sqlite3_result_double(context, p->riM*1.0/p->mn);
- else
- wx_sqlite3_result_double(context, p->rdM/p->mn);
- }
-}
-
-/*
-** Returns the median value
-*/
-static void medianFinalize(wx_sqlite3_context *context){
- ModeCtx *p;
- p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0);
- if( p!=0 ){
- p->pcnt = (p->cnt)/2.0;
- _medianFinalize(context);
- }
-}
-
-/*
-** Returns the lower_quartile value
-*/
-static void lower_quartileFinalize(wx_sqlite3_context *context){
- ModeCtx *p;
- p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0);
- if( p!=0 ){
- p->pcnt = (p->cnt)/4.0;
- _medianFinalize(context);
- }
-}
-
-/*
-** Returns the upper_quartile value
-*/
-static void upper_quartileFinalize(wx_sqlite3_context *context){
- ModeCtx *p;
- p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0);
- if( p!=0 ){
- p->pcnt = (p->cnt)*3/4.0;
- _medianFinalize(context);
- }
-}
-
-/*
-** Returns the stdev value
-*/
-static void stdevFinalize(wx_sqlite3_context *context){
- StdevCtx *p;
- p = wx_sqlite3_aggregate_context(context, 0);
- if( p && p->cnt>1 ){
- wx_sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1)));
- }else{
- wx_sqlite3_result_double(context, 0.0);
- }
-}
-
-/*
-** Returns the variance value
-*/
-static void varianceFinalize(wx_sqlite3_context *context){
- StdevCtx *p;
- p = wx_sqlite3_aggregate_context(context, 0);
- if( p && p->cnt>1 ){
- wx_sqlite3_result_double(context, p->rS/(p->cnt-1));
- }else{
- wx_sqlite3_result_double(context, 0.0);
- }
-}
-
-#ifdef SQLITE_SOUNDEX
-
-/* relicoder factored code */
-/*
-** Calculates the soundex value of a string
-*/
-
-static void soundex(const u8 *zIn, char *zResult){
- int i, j;
- static const unsigned char iCode[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- };
-
- for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
- if( zIn[i] ){
- zResult[0] = toupper(zIn[i]);
- for(j=1; j<4 && zIn[i]; i++){
- int code = iCode[zIn[i]&0x7f];
- if( code>0 ){
- zResult[j++] = code + '0';
- }
- }
- while( j<4 ){
- zResult[j++] = '0';
- }
- zResult[j] = 0;
- }else{
- strcpy(zResult, "?000");
- }
-}
-
-/*
-** computes the number of different characters between the soundex value fo 2 strings
-*/
-static void differenceFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- char zResult1[8];
- char zResult2[8];
- char *zR1 = zResult1;
- char *zR2 = zResult2;
- int rVal = 0;
- int i = 0;
- const u8 *zIn1;
- const u8 *zIn2;
-
- assert( argc==2 );
-
- if( wx_sqlite3_value_type(argv[0])==SQLITE_NULL || wx_sqlite3_value_type(argv[1])==SQLITE_NULL ){
- wx_sqlite3_result_null(context);
- return;
- }
-
- zIn1 = (u8*)wx_sqlite3_value_text(argv[0]);
- zIn2 = (u8*)wx_sqlite3_value_text(argv[1]);
-
- soundex(zIn1, zR1);
- soundex(zIn2, zR2);
-
- for(i=0; i<4; ++i){
- if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) )
- ++rVal;
- sqliteNextChar(zR1);
- sqliteNextChar(zR2);
- }
- wx_sqlite3_result_int(context, rVal);
-}
-#endif
-
-static void lastRowsFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){
- wx_sqlite3 *db = wx_sqlite3_context_db_handle(context);
- wx_sqlite3_result_int64(context, wx_sqlite3_changes(db));
-}
-
-/*
-** This function registered all of the above C functions as SQL
-** functions. This should be the only routine in this file with
-** external linkage.
-*/
-int RegisterExtensionFunctions(wx_sqlite3 *db){
- static const struct FuncDef {
- char *zName;
- signed char nArg;
- u8 argType; /* 0: none. 1: db 2: (-1) */
- u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
- u8 needCollSeq;
- void (*xFunc)(wx_sqlite3_context*,int,wx_sqlite3_value **);
- } aFuncs[] = {
- /* math.h */
- { "acos", 1, 0, SQLITE_UTF8, 0, acosFunc },
- { "asin", 1, 0, SQLITE_UTF8, 0, asinFunc },
- { "atan", 1, 0, SQLITE_UTF8, 0, atanFunc },
- { "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func },
- /* XXX alias */
- { "atan2", 2, 0, SQLITE_UTF8, 0, atn2Func },
- { "acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc },
- { "asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc },
- { "atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc },
-
- { "difference", 2, 0, SQLITE_UTF8, 0, differenceFunc},
- { "degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc },
- { "radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc },
-
- { "cos", 1, 0, SQLITE_UTF8, 0, cosFunc },
- { "sin", 1, 0, SQLITE_UTF8, 0, sinFunc },
- { "tan", 1, 0, SQLITE_UTF8, 0, tanFunc },
- { "cot", 1, 0, SQLITE_UTF8, 0, cotFunc },
- { "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc },
- { "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc },
- { "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc },
- { "coth", 1, 0, SQLITE_UTF8, 0, cothFunc },
-
- { "exp", 1, 0, SQLITE_UTF8, 0, expFunc },
- { "log", 1, 0, SQLITE_UTF8, 0, logFunc },
- { "ln", 1, 0, SQLITE_UTF8, 0, logFunc },
- { "log10", 1, 0, SQLITE_UTF8, 0, log10Func },
- { "power", 2, 0, SQLITE_UTF8, 0, powerFunc },
- { "sign", 1, 0, SQLITE_UTF8, 0, signFunc },
- { "sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc },
- { "square", 1, 0, SQLITE_UTF8, 0, squareFunc },
-
- { "ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc },
- { "ceiling", 1, 0, SQLITE_UTF8, 0, ceilFunc },
- { "floor", 1, 0, SQLITE_UTF8, 0, floorFunc },
-
- { "pi", 0, 0, SQLITE_UTF8, 1, piFunc },
-
- { "last_rows_affected", 0, 0, SQLITE_UTF8, 0, lastRowsFunc },
-
- /* string */
- { "replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc },
- { "charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc },
- { "charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc },
- { "leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc },
- { "rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc },
-#ifndef HAVE_TRIM
- { "ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc },
- { "rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc },
- { "trim", 1, 0, SQLITE_UTF8, 0, trimFunc },
- { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
-#endif
- { "reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc },
- { "proper", 1, 0, SQLITE_UTF8, 0, properFunc },
- { "padl", 2, 0, SQLITE_UTF8, 0, padlFunc },
- { "padr", 2, 0, SQLITE_UTF8, 0, padrFunc },
- { "padc", 2, 0, SQLITE_UTF8, 0, padcFunc },
- { "strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc },
-
- };
- /* Aggregate functions */
- static const struct FuncDefAgg {
- char *zName;
- signed char nArg;
- u8 argType;
- u8 needCollSeq;
- void (*xStep)(wx_sqlite3_context*,int,wx_sqlite3_value**);
- void (*xFinalize)(wx_sqlite3_context*);
- } aAggs[] = {
- { "stdev", 1, 0, 0, varianceStep, stdevFinalize },
- { "variance", 1, 0, 0, varianceStep, varianceFinalize },
- { "mode", 1, 0, 0, modeStep, modeFinalize },
- { "median", 1, 0, 0, modeStep, medianFinalize },
- { "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize },
- { "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize },
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- void *pArg = 0;
- switch( aFuncs[i].argType ){
- case 1: pArg = db; break;
- case 2: pArg = (void *)(-1); break;
- }
- //wx_sqlite3CreateFunc
- /* LMH no error checking */
- wx_sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
- aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
-#if 0
- if( aFuncs[i].needCollSeq ){
- struct FuncDef *pFunc = wx_sqlite3FindFunction(db, aFuncs[i].zName,
- strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
- if( pFunc && aFuncs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
-#endif
- }
-
- for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
- void *pArg = 0;
- switch( aAggs[i].argType ){
- case 1: pArg = db; break;
- case 2: pArg = (void *)(-1); break;
- }
- //wx_sqlite3CreateFunc
- /* LMH no error checking */
- wx_sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
- pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
-#if 0
- if( aAggs[i].needCollSeq ){
- struct FuncDefAgg *pFunc = wx_sqlite3FindFunction( db, aAggs[i].zName,
- strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
- if( pFunc && aAggs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
-#endif
- }
- return 0;
-}
-
-#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
-int wx_sqlite3_extension_init(
- wx_sqlite3 *db, char **pzErrMsg, const wx_sqlite3_api_routines *pApi){
- SQLITE_EXTENSION_INIT2(pApi);
- RegisterExtensionFunctions(db);
- return 0;
-}
-#endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */
-
-map map_make(cmp_func cmp){
- map r;
- r.cmp=cmp;
- r.base = 0;
-
- return r;
-}
-
-void* xcalloc(size_t nmemb, size_t size, char* s){
- void* ret = calloc(nmemb, size);
- return ret;
-}
-
-void xfree(void* p){
- free(p);
-}
-
-void node_insert(node** n, cmp_func cmp, void *e){
- int c;
- node* nn;
- if(*n==0){
- nn = (node*)xcalloc(1,sizeof(node), "for node");
- nn->data = e;
- nn->count = 1;
- *n=nn;
- }else{
- c=cmp((*n)->data,e);
- if(0==c){
- ++((*n)->count);
- xfree(e);
- }else if(c>0){
- /* put it right here */
- node_insert(&((*n)->l), cmp, e);
- }else{
- node_insert(&((*n)->r), cmp, e);
- }
- }
-}
-
-void map_insert(map *m, void *e){
- node_insert(&(m->base), m->cmp, e);
-}
-
-void node_iterate(node *n, map_iterator iter, void* p){
- if(n){
- if(n->l)
- node_iterate(n->l, iter, p);
- iter(n->data, n->count, p);
- if(n->r)
- node_iterate(n->r, iter, p);
- }
-}
-
-void map_iterate(map *m, map_iterator iter, void* p){
- node_iterate(m->base, iter, p);
-}
-
-void node_destroy(node *n){
- if(0!=n){
- xfree(n->data);
- if(n->l)
- node_destroy(n->l);
- if(n->r)
- node_destroy(n->r);
-
- xfree(n);
- }
-}
-
-void map_destroy(map *m){
- node_destroy(m->base);
-}
-
-int int_cmp(const void *a, const void *b){
- i64 aa = *(i64 *)(a);
- i64 bb = *(i64 *)(b);
- /* printf("cmp %d <=> %d\n",aa,bb); */
- if(aa==bb)
- return 0;
- else if(aa<bb)
- return -1;
- else
- return 1;
-}
-
-int double_cmp(const void *a, const void *b){
- double aa = *(double *)(a);
- double bb = *(double *)(b);
- /* printf("cmp %d <=> %d\n",aa,bb); */
- if(aa==bb)
- return 0;
- else if(aa<bb)
- return -1;
- else
- return 1;
-}
-
-void print_elem(void *e, i64 c, void* p){
- int ee = *(int*)(e);
- printf("%d => %lld\n", ee,c);
-}
-
-
+/* +This library will provide common mathematical and string functions in +SQL queries using the operating system libraries or provided +definitions. It includes the following functions: + +Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, +degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, +log, log10, power, sign, sqrt, square, ceil, floor, pi. + +String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, +replace, reverse, proper, padl, padr, padc, strfilter. + +Aggregate: stdev, variance, mode, median, lower_quartile, +upper_quartile. + +The string functions ltrim, rtrim, trim, replace are included in +recent versions of SQLite and so by default do not build. + +Compilation instructions: + Compile this C source file into a dynamic library as follows: + * Linux: + gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so + * Mac OS X: + gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib + (You may need to add flags + -I /opt/local/include/ -L/opt/local/lib -lwx_sqlite3 + if your wx_sqlite3 is installed from Mac ports, or + -I /sw/include/ -L/sw/lib -lwx_sqlite3 + if installed with Fink.) + * Windows: + 1. Install MinGW (http://www.mingw.org/) and you will get the gcc + (gnu compiler collection) + 2. add the path to your path variable (isn't done during the + installation!) + 3. compile: + gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c + (path = path of wx_sqlite3ext.h; i.e. C:\programs\sqlite) + +Usage instructions for applications calling the wx_sqlite3 API functions: + In your application, call wx_sqlite3_enable_load_extension(db,1) to + allow loading external libraries. Then load the library libsqlitefunctions + using wx_sqlite3_load_extension; the third argument should be 0. + See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + Select statements may now use these functions, as in + SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544; + +Usage instructions for the wx_sqlite3 program: + If the program is built so that loading extensions is permitted, + the following will work: + sqlite> SELECT load_extension('./libsqlitefunctions.so'); + sqlite> select cos(radians(45)); + 0.707106781186548 + Note: Loading extensions is by default prohibited as a + security measure; see "Security Considerations" in + http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + If the wx_sqlite3 program and library are built this + way, you cannot use these functions from the program, you + must write your own program using the wx_sqlite3 API, and call + wx_sqlite3_enable_load_extension as described above, or else + rebuilt the wx_sqlite3 program to allow loadable extensions. + +Alterations: +The instructions are for Linux, Mac OS X, and Windows; users of other +OSes may need to modify this procedure. In particular, if your math +library lacks one or more of the needed trig or log functions, comment +out the appropriate HAVE_ #define at the top of file. If you do not +wish to make a loadable module, comment out the define for +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. If you are using a +version of SQLite without the trim functions and replace, comment out +the HAVE_TRIM #define. + +Liam Healy + +History: +2010-01-06 Correct check for argc in squareFunc, and add Windows +compilation instructions. +2009-06-24 Correct check for argc in properFunc. +2008-09-14 Add check that memory was actually allocated after +wx_sqlite3_malloc or wx_sqlite3StrDup, call wx_sqlite3_result_error_nomem if +not. Thanks to Robert Simpson. +2008-06-13 Change to instructions to indicate use of the math library +and that program might work. +2007-10-01 Minor clarification to instructions. +2007-09-29 Compilation as loadable module is optional with +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. +2007-09-28 Use wx_sqlite3_extension_init and macros +SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with +wx_sqlite3_load_extension. Thanks to Eric Higashino and Joe Wilson. +New instructions for Mac compilation. +2007-09-17 With help from Joe Wilson and Nuno Luca, made use of +external interfaces so that compilation is no longer dependent on +SQLite source code. Merged source, header, and README into a single +file. Added casts so that Mac will compile without warnings (unsigned +and signed char). +2007-09-05 Included some definitions from sqlite 3.3.13 so that this +will continue to work in newer versions of sqlite. Completed +description of functions available. +2007-03-27 Revised description. +2007-03-23 Small cleanup and a bug fix on the code. This was mainly +letting errno flag errors encountered in the math library and checking +the result, rather than pre-checking. This fixes a bug in power that +would cause an error if any non-positive number was raised to any +power. +2007-02-07 posted by Mikey C to sqlite mailing list. +Original code 2006 June 05 by relicoder. + +*/ + +/* #include "config.h" */ + +/* #define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1 */ +#if defined(_MSC_VER) && _MSC_VER <= 1700 +#else +#define HAVE_ACOSH 1 +#define HAVE_ASINH 1 +#define HAVE_ATANH 1 +#endif +#define HAVE_SINH 1 +#define HAVE_COSH 1 +#define HAVE_TANH 1 +#define HAVE_LOG10 1 +#if defined(_MSC_VER) && _MSC_VER <= 1700 +#else +#define HAVE_ISBLANK 1 +#endif +#define SQLITE_SOUNDEX 1 +#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +#include "wx_sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#else +#include "wxsqlite3.h" +#endif + +#include <ctype.h> +/* relicoder */ +#include <math.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> /* LMH 2007-03-25 */ + +#include <stdlib.h> +#include <assert.h> + +#ifndef _MAP_H_ +#define _MAP_H_ + +#if 0 +#if !defined(SQLITE_OS_WIN) || !defined(_MSC_VER) +#include <stdint.h> +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int int16_t; +typedef unsigned int uint16_t; +typedef signed long int int32_t; +typedef unsigned long int uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#endif +#endif + +/* +** Simple binary tree implementation to use in median, mode and quartile calculations +** Tree is not necessarily balanced. That would require something like red&black trees of AVL +*/ + +typedef int(*cmp_func)(const void *, const void *); +typedef void(*map_iterator)(void*, i64, void*); + +typedef struct node{ + struct node *l; + struct node *r; + void* data; + i64 count; +} node; + +typedef struct map{ + node *base; + cmp_func cmp; + short free; +} map; + +/* +** creates a map given a comparison function +*/ +map map_make(cmp_func cmp); + +/* +** inserts the element e into map m +*/ +void map_insert(map *m, void *e); + +/* +** executes function iter over all elements in the map, in key increasing order +*/ +void map_iterate(map *m, map_iterator iter, void* p); + +/* +** frees all memory used by a map +*/ +void map_destroy(map *m); + +/* +** compares 2 integers +** to use with map_make +*/ +int int_cmp(const void *a, const void *b); + +/* +** compares 2 doubles +** to use with map_make +*/ +int double_cmp(const void *a, const void *b); + +#endif /* _MAP_H_ */ + +static char *wx_sqlite3StrDup( const char *z ) { + char *res = wx_sqlite3_malloc( strlen(z)+1 ); + return strcpy( res, z ); +} + +/* +** These are copied verbatim from fun.c so as to not have the names exported +*/ + +/* LMH from wx_sqlite3 3.3.13 */ +/* +** This table maps from the first byte of a UTF-8 character to the number +** of trailing bytes expected. A value '4' indicates that the table key +** is not a legal first byte for a UTF-8 character. +*/ +static const u8 xtra_utf8_bytes[256] = { +/* 0xxxxxxx */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* 10wwwwww */ +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + +/* 110yyyyy */ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +/* 1110zzzz */ +2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + +/* 11110yyy */ +3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, +}; + + +/* +** This table maps from the number of trailing bytes in a UTF-8 character +** to an integer constant that is effectively calculated for each character +** read by a naive implementation of a UTF-8 character reader. The code +** in the READ_UTF8 macro explains things best. +*/ +static const int xtra_utf8_bits[] = { + 0, + 12416, /* (0xC0 << 6) + (0x80) */ + 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */ + 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */ +}; + +/* +** If a UTF-8 character contains N bytes extra bytes (N bytes follow +** the initial byte so that the total character length is N+1) then +** masking the character with utf8_mask[N] must produce a non-zero +** result. Otherwise, we have an (illegal) overlong encoding. +*/ +static const int utf_mask[] = { + 0x00000000, + 0xffffff80, + 0xfffff800, + 0xffff0000, +}; + +/* LMH salvaged from wx_sqlite3 3.3.13 source code src/utf.c */ +#define EXTFUNC_READ_UTF8(zIn, c) { \ + int xtra; \ + c = *(zIn)++; \ + xtra = xtra_utf8_bytes[c]; \ + switch( xtra ){ \ + case 4: c = (int)0xFFFD; break; \ + case 3: c = (c<<6) + *(zIn)++; \ + case 2: c = (c<<6) + *(zIn)++; \ + case 1: c = (c<<6) + *(zIn)++; \ + c -= xtra_utf8_bits[xtra]; \ + if( (utf_mask[xtra]&c)==0 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } \ +} + +static int wx_sqlite3ReadUtf8(const unsigned char *z){ + int c; + EXTFUNC_READ_UTF8(z, c); + return c; +} + +#define SKIP_UTF8(zIn) { \ + zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \ +} + +#if 0 +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to +** the first 0x00, whichever comes first). +*/ +static int wx_sqlite3Utf8CharLen(const char *z, int nByte){ + int r = 0; + const char *zTerm; + if( nByte>=0 ){ + zTerm = &z[nByte]; + }else{ + zTerm = (const char *)(-1); + } + assert( z<=zTerm ); + while( *z!=0 && z<zTerm ){ + SKIP_UTF8(z); + r++; + } + return r; +} +#endif + +/* +** X is a pointer to the first byte of a UTF-8 character. Increment +** X so that it points to the next character. This only works right +** if X points to a well-formed UTF-8 string. +*/ +#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} +#define sqliteCharVal(X) wx_sqlite3ReadUtf8(X) + +/* +** This is a macro that facilitates writting wrappers for math.h functions +** it creates code for a function to use in SQlite that gets one numeric input +** and returns a floating point value. +** +** Could have been implemented using pointers to functions but this way it's inline +** and thus more efficient. Lower * ranking though... +** +** Parameters: +** name: function name to de defined (eg: sinFunc) +** function: function defined in math.h to wrap (eg: sin) +** domain: boolean condition that CAN'T happen in terms of the input parameter rVal +** (eg: rval<0 for sqrt) +*/ +/* LMH 2007-03-25 Changed to use errno and remove domain; no pre-checking for errors. */ +#define GEN_MATH_WRAP_DOUBLE_1(name, function) \ +static void name(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){\ + double rVal = 0.0, val;\ + assert( argc==1 );\ + switch( wx_sqlite3_value_type(argv[0]) ){\ + case SQLITE_NULL: {\ + wx_sqlite3_result_null(context);\ + break;\ + }\ + default: {\ + rVal = wx_sqlite3_value_double(argv[0]);\ + errno = 0;\ + val = function(rVal);\ + if (errno == 0) {\ + wx_sqlite3_result_double(context, val);\ + } else {\ + wx_sqlite3_result_error(context, strerror(errno), errno);\ + }\ + break;\ + }\ + }\ +}\ + + +/* +** Example of GEN_MATH_WRAP_DOUBLE_1 usage +** this creates function sqrtFunc to wrap the math.h standard function sqrt(x)=x^0.5 +*/ +GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt) + +/* trignometric functions */ +GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos) +GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin) +GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan) + +/* +** Many of systems don't have inverse hyperbolic trig functions so this will emulate +** them on those systems in terms of log and sqrt (formulas are too trivial to demand +** written proof here) +*/ + +#ifndef HAVE_ACOSH +static double acosh(double x){ + return log(x + sqrt(x*x - 1.0)); +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh) + +#ifndef HAVE_ASINH +static double asinh(double x){ + return log(x + sqrt(x*x + 1.0)); +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh) + +#ifndef HAVE_ATANH +static double atanh(double x){ + return (1.0/2.0)*log((1+x)/(1-x)) ; +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh) + +/* +** math.h doesn't require cot (cotangent) so it's defined here +*/ +static double cot(double x){ + return 1.0/tan(x); +} + +GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin) +GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos) +GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan) +GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot) + +static double coth(double x){ + return 1.0/tanh(x); +} + +/* +** Many systems don't have hyperbolic trigonometric functions so this will emulate +** them on those systems directly from the definition in terms of exp +*/ +#ifndef HAVE_SINH +static double sinh(double x){ + return (exp(x)-exp(-x))/2.0; +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh) + +#ifndef HAVE_COSH +static double cosh(double x){ + return (exp(x)+exp(-x))/2.0; +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh) + +#ifndef HAVE_TANH +static double tanh(double x){ + return sinh(x)/cosh(x); +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh) + +GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth) + +/* +** Some systems lack log in base 10. This will emulate it +*/ + +#ifndef HAVE_LOG10 +static double log10(double x){ + static double l10 = -1.0; + if( l10<0.0 ){ + l10 = log(10.0); + } + return log(x)/l10; +} +#endif + +GEN_MATH_WRAP_DOUBLE_1(logFunc, log) +GEN_MATH_WRAP_DOUBLE_1(log10Func, log10) +GEN_MATH_WRAP_DOUBLE_1(expFunc, exp) + +/* +** Fallback for systems where math.h doesn't define M_PI +*/ +#undef M_PI +#ifndef M_PI +/* +** static double PI = acos(-1.0); +** #define M_PI (PI) +*/ +#define M_PI 3.14159265358979323846 +#endif + +/* Convert Degrees into Radians */ +static double deg2rad(double x){ + return x*M_PI/180.0; +} + +/* Convert Radians into Degrees */ +static double rad2deg(double x){ + return 180.0*x/M_PI; +} + +GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg) +GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad) + +/* constant function that returns the value of PI=3.1415... */ +static void piFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + wx_sqlite3_result_double(context, M_PI); +} + +/* +** Implements the sqrt function, it has the peculiarity of returning an integer when the +** the argument is an integer. +** Since SQLite isn't strongly typed (almost untyped actually) this is a bit pedantic +*/ +static void squareFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + i64 iVal = 0; + double rVal = 0.0; + assert( argc==1 ); + switch( wx_sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + iVal = wx_sqlite3_value_int64(argv[0]); + wx_sqlite3_result_int64(context, iVal*iVal); + break; + } + case SQLITE_NULL: { + wx_sqlite3_result_null(context); + break; + } + default: { + rVal = wx_sqlite3_value_double(argv[0]); + wx_sqlite3_result_double(context, rVal*rVal); + break; + } + } +} + +/* +** Wraps the pow math.h function +** When both the base and the exponent are integers the result should be integer +** (see sqrt just before this). Here the result is always double +*/ +/* LMH 2007-03-25 Changed to use errno; no pre-checking for errors. Also removes + but that was present in the pre-checking that called wx_sqlite3_result_error on + a non-positive first argument, which is not always an error. */ +static void powerFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + double r1 = 0.0; + double r2 = 0.0; + double val; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + r1 = wx_sqlite3_value_double(argv[0]); + r2 = wx_sqlite3_value_double(argv[1]); + errno = 0; + val = pow(r1,r2); + if (errno == 0) { + wx_sqlite3_result_double(context, val); + } else { + wx_sqlite3_result_error(context, strerror(errno), errno); + } + } +} + +/* +** atan2 wrapper +*/ +static void atn2Func(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + double r1 = 0.0; + double r2 = 0.0; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + r1 = wx_sqlite3_value_double(argv[0]); + r2 = wx_sqlite3_value_double(argv[1]); + wx_sqlite3_result_double(context, atan2(r1,r2)); + } +} + +/* +** Implementation of the sign() function +** return one of 3 possibilities +1,0 or -1 when the argument is respectively +** positive, 0 or negative. +** When the argument is NULL the result is also NULL (completly conventional) +*/ +static void signFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( wx_sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + iVal = wx_sqlite3_value_int64(argv[0]); + iVal = ( iVal > 0) ? 1: ( iVal < 0 ) ? -1: 0; + wx_sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + wx_sqlite3_result_null(context); + break; + } + default: { + /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0; */ + + rVal = wx_sqlite3_value_double(argv[0]); + rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0; + wx_sqlite3_result_double(context, rVal); + break; + } + } +} + + +/* +** smallest integer value not less than argument +*/ +static void ceilFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( wx_sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = wx_sqlite3_value_int64(argv[0]); + wx_sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + wx_sqlite3_result_null(context); + break; + } + default: { + rVal = wx_sqlite3_value_double(argv[0]); + wx_sqlite3_result_int64(context, (i64) ceil(rVal)); + break; + } + } +} + +/* +** largest integer value not greater than argument +*/ +static void floorFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( wx_sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = wx_sqlite3_value_int64(argv[0]); + wx_sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + wx_sqlite3_result_null(context); + break; + } + default: { + rVal = wx_sqlite3_value_double(argv[0]); + wx_sqlite3_result_int64(context, (i64) floor(rVal)); + break; + } + } +} + +/* +** Given a string (s) in the first argument and an integer (n) in the second returns the +** string that constains s contatenated n times +*/ +static void replicateFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + unsigned char *z; /* input string */ + unsigned char *zo; /* result string */ + i64 iCount; /* times to repeat */ + i64 nLen; /* length of the input string (no multibyte considerations) */ + i64 nTLen; /* length of the result string (no multibyte considerations) */ + i64 i=0; + + if( argc!=2 || SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ) + return; + + iCount = wx_sqlite3_value_int64(argv[1]); + + if( iCount<0 ){ + wx_sqlite3_result_error(context, "domain error", -1); + }else{ + + nLen = wx_sqlite3_value_bytes(argv[0]); + nTLen = nLen*iCount; + z=wx_sqlite3_malloc(nTLen+1); + zo=wx_sqlite3_malloc(nLen+1); + if (!z || !zo){ + wx_sqlite3_result_error_nomem(context); + if (z) wx_sqlite3_free(z); + if (zo) wx_sqlite3_free(zo); + return; + } + strcpy((char*)zo, (char*)wx_sqlite3_value_text(argv[0])); + + for(i=0; i<iCount; ++i){ + strcpy((char*)(z+i*nLen), (char*)zo); + } + + wx_sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(z); + wx_sqlite3_free(zo); + } +} + +/* +** Some systems (win32 among others) don't have an isblank function, this will emulate it. +** This function is not UFT-8 safe since it only analyses a byte character. +*/ +#ifndef HAVE_ISBLANK +int isblank(char c){ + return( ' '==c || '\t'==c ); +} +#endif + +static void properFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const unsigned char *z; /* input string */ + unsigned char *zo; /* output string */ + unsigned char *zt; /* iterator */ + char r; + int c=1; + + assert( argc==1); + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + + z = wx_sqlite3_value_text(argv[0]); + zo = (unsigned char *)wx_sqlite3StrDup((char *) z); + if (!zo) { + wx_sqlite3_result_error_nomem(context); + return; + } + zt = zo; + + while( (r = *(z++))!=0 ){ + if( isblank(r) ){ + c=1; + }else{ + if( c==1 ){ + r = toupper(r); + }else{ + r = tolower(r); + } + c=0; + } + *(zt++) = r; + } + *zt = '\0'; + + wx_sqlite3_result_text(context, (char*)zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); +} + +/* +** given an input string (s) and an integer (n) adds spaces at the begining of s +** until it has a length of n characters. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padlFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + zi = (char *)wx_sqlite3_value_text(argv[0]); + ilen = wx_sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + wx_sqlite3_result_error(context, "domain error", -1); + return; + } + zl = wx_sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = wx_sqlite3StrDup(zi); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zo = wx_sqlite3_malloc(strlen(zi)+ilen-zl+1); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; i+zl<=ilen; ++i){ + *(zt++)=' '; + } + /* no need to take UTF-8 into consideration here */ + strcpy(zt,zi); + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** until it has a length of n characters. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padrFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + zi = (char *)wx_sqlite3_value_text(argv[0]); + ilen = wx_sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + wx_sqlite3_result_error(context, "domain error", -1); + return; + } + zl = wx_sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = wx_sqlite3StrDup(zi); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = wx_sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + zt = strcpy(zo,zi)+zll; + for(i=1; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** and adds spaces at the begining of s until it has a length of n characters. +** Tries to add has many characters at the left as at the right. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padcFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + zi = (char *)wx_sqlite3_value_text(argv[0]); + ilen = wx_sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + wx_sqlite3_result_error(context, "domain error", -1); + return; + } + zl = wx_sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = wx_sqlite3StrDup(zi); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = wx_sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; 2*i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + strcpy(zt, zi); + zt+=zll; + for(; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); + } +} + +/* +** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed +** assumes strings are UTF-8 encoded +*/ +static void strfilterFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *zi1; /* first parameter string (searched string) */ + const char *zi2; /* second parameter string (vcontains valid characters) */ + const char *z1; + const char *z21; + const char *z22; + char *zo; /* output string */ + char *zot; + int c1 = 0; + int c2 = 0; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0]) == SQLITE_NULL || wx_sqlite3_value_type(argv[1]) == SQLITE_NULL ){ + wx_sqlite3_result_null(context); + }else{ + zi1 = (char *)wx_sqlite3_value_text(argv[0]); + zi2 = (char *)wx_sqlite3_value_text(argv[1]); + /* + ** maybe I could allocate less, but that would imply 2 passes, rather waste + ** (possibly) some memory + */ + zo = wx_sqlite3_malloc(strlen(zi1)+1); + if (!zo){ + wx_sqlite3_result_error_nomem(context); + return; + } + zot = zo; + z1 = zi1; + while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){ + z21=zi2; + while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){ + sqliteNextChar(z21); + } + if( c2!=0){ + z22=z21; + sqliteNextChar(z22); + strncpy(zot, z21, z22-z21); + zot+=z22-z21; + } + sqliteNextChar(z1); + } + *zot = '\0'; + + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); + } +} + +/* +** Given a string z1, retutns the (0 based) index of it's first occurence +** in z2 after the first s characters. +** Returns -1 when there isn't a match. +** updates p to point to the character where the match occured. +** This is an auxiliary function. +*/ +static int _substr(const char* z1, const char* z2, int s, const char** p){ + int c = 0; + int rVal=-1; + const char* zt1; + const char* zt2; + int c1,c2; + + if( '\0'==*z1 ){ + return -1; + } + + while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)<s){ + sqliteNextChar(z2); + } + + c = 0; + while( (sqliteCharVal((unsigned char *)z2)) != 0 ){ + zt1 = z1; + zt2 = z2; + + do{ + c1 = sqliteCharVal((unsigned char *)zt1); + c2 = sqliteCharVal((unsigned char *)zt2); + sqliteNextChar(zt1); + sqliteNextChar(zt2); + }while( c1 == c2 && c1 != 0 && c2 != 0 ); + + if( c1 == 0 ){ + rVal = c; + break; + } + + sqliteNextChar(z2); + ++c; + } + if(p){ + *p=z2; + } + return rVal >=0 ? rVal+s : rVal; +} + +/* +** given 2 input strings (s1,s2) and an integer (n) searches from the nth character +** for the string s1. Returns the position where the match occured. +** Characters are counted from 1. +** 0 is returned when no match occurs. +*/ + +static void charindexFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const u8 *z1; /* s1 string */ + u8 *z2; /* s2 string */ + int s=0; + int rVal=0; + + assert( argc==3 ||argc==2); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) || SQLITE_NULL==wx_sqlite3_value_type(argv[1])){ + wx_sqlite3_result_null(context); + return; + } + + z1 = wx_sqlite3_value_text(argv[0]); + if( z1==0 ) return; + z2 = (u8*) wx_sqlite3_value_text(argv[1]); + if(argc==3){ + s = wx_sqlite3_value_int(argv[2])-1; + if(s<0){ + s=0; + } + }else{ + s = 0; + } + + rVal = _substr((char *)z1,(char *)z2,s,NULL); + wx_sqlite3_result_int(context, rVal+1); +} + +/* +** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters +** if the string has a length<=n or is NULL this function is NOP +*/ +static void leftFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + int c=0; + int cc=0; + int l=0; + const unsigned char *z; /* input string */ + const unsigned char *zt; + unsigned char *rz; /* output string */ + + assert( argc==2); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) || SQLITE_NULL==wx_sqlite3_value_type(argv[1])){ + wx_sqlite3_result_null(context); + return; + } + + z = wx_sqlite3_value_text(argv[0]); + l = wx_sqlite3_value_int(argv[1]); + zt = z; + + while( sqliteCharVal(zt) && c++<l) + sqliteNextChar(zt); + + cc=zt-z; + + rz = wx_sqlite3_malloc(zt-z+1); + if (!rz){ + wx_sqlite3_result_error_nomem(context); + return; + } + strncpy((char*) rz, (char*) z, zt-z); + *(rz+cc) = '\0'; + wx_sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(rz); +} + +/* +** given a string (s) and an integer (n) returns the n rightmost (UTF-8) characters +** if the string has a length<=n or is NULL this function is NOP +*/ +static void rightFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + int l=0; + int c=0; + int cc=0; + const char *z; + const char *zt; + const char *ze; + char *rz; + + assert( argc==2); + + if( SQLITE_NULL == wx_sqlite3_value_type(argv[0]) || SQLITE_NULL == wx_sqlite3_value_type(argv[1])){ + wx_sqlite3_result_null(context); + return; + } + + z = (char *)wx_sqlite3_value_text(argv[0]); + l = wx_sqlite3_value_int(argv[1]); + zt = z; + + while( sqliteCharVal((unsigned char *)zt)!=0){ + sqliteNextChar(zt); + ++c; + } + + ze = zt; + zt = z; + + cc=c-l; + if(cc<0) + cc=0; + + while( cc-- > 0 ){ + sqliteNextChar(zt); + } + + rz = wx_sqlite3_malloc(ze-zt+1); + if (!rz){ + wx_sqlite3_result_error_nomem(context); + return; + } + strcpy((char*) rz, (char*) (zt)); + wx_sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(rz); +} + +#ifndef HAVE_TRIM +/* +** removes the whitespaces at the begining of a string. +*/ +const char* ltrim(const char* s){ + while( *s==' ' ) + ++s; + return s; +} + +/* +** removes the whitespaces at the end of a string. +** !mutates the input string! +*/ +void rtrim(char* s){ + char* ss = s+strlen(s)-1; + while( ss>=s && *ss==' ' ) + --ss; + *(ss+1)='\0'; +} + +/* +** Removes the whitespace at the begining of a string +*/ +static void ltrimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *z; + + assert( argc==1); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + z = wx_sqlite3_value_text(argv[0]); + wx_sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); +} + +/* +** Removes the whitespace at the end of a string +*/ +static void rtrimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + z = wx_sqlite3_value_text(argv[0]); + rz = wx_sqlite3StrDup(z); + rtrim(rz); + wx_sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(rz); +} + +/* +** Removes the whitespace at the begining and end of a string +*/ +static void trimFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + z = wx_sqlite3_value_text(argv[0]); + rz = wx_sqlite3StrDup(z); + rtrim(rz); + wx_sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT); + wx_sqlite3_free(rz); +} +#endif + +/* +** given a pointer to a string s1, the length of that string (l1), a new string (s2) +** and it's length (l2) appends s2 to s1. +** All lengths in bytes. +** This is just an auxiliary function +*/ +#if 0 +static void _append(char **s1, int l1, const char *s2, int l2){ + *s1 = realloc(*s1, (l1+l2+1)*sizeof(char)); + strncpy((*s1)+l1, s2, l2); + *(*(s1)+l1+l2) = '\0'; +} +#endif + +#ifndef HAVE_TRIM + +/* +** given strings s, s1 and s2 replaces occurrences of s1 in s by s2 +*/ +static void replaceFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *z1; /* string s (first parameter) */ + const char *z2; /* string s1 (second parameter) string to look for */ + const char *z3; /* string s2 (third parameter) string to replace occurrences of s1 with */ + int lz1; + int lz2; + int lz3; + int lzo=0; + char *zo=0; + int ret=0; + const char *zt1; + const char *zt2; + + assert( 3==argc ); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + + z1 = wx_sqlite3_value_text(argv[0]); + z2 = wx_sqlite3_value_text(argv[1]); + z3 = wx_sqlite3_value_text(argv[2]); + /* handle possible null values */ + if( 0==z2 ){ + z2=""; + } + if( 0==z3 ){ + z3=""; + } + + lz1 = strlen(z1); + lz2 = strlen(z2); + lz3 = strlen(z3); + +#if 0 + /* special case when z2 is empty (or null) nothing will be changed */ + if( 0==lz2 ){ + wx_sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT); + return; + } +#endif + + zt1=z1; + zt2=z1; + + while(1){ + ret=_substr(z2,zt1 , 0, &zt2); + + if( ret<0 ) + break; + + _append(&zo, lzo, zt1, zt2-zt1); + lzo+=zt2-zt1; + _append(&zo, lzo, z3, lz3); + lzo+=lz3; + + zt1=zt2+lz2; + } + _append(&zo, lzo, zt1, lz1-(zt1-z1)); + wx_sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(zo); +} +#endif + +/* +** given a string returns the same string but with the characters in reverse order +*/ +static void reverseFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + const char *z; + const char *zt; + char *rz; + char *rzt; + int l = 0; + int i = 0; + + assert( 1==argc ); + + if( SQLITE_NULL==wx_sqlite3_value_type(argv[0]) ){ + wx_sqlite3_result_null(context); + return; + } + z = (char *)wx_sqlite3_value_text(argv[0]); + l = strlen(z); + rz = wx_sqlite3_malloc(l+1); + if (!rz){ + wx_sqlite3_result_error_nomem(context); + return; + } + rzt = rz+l; + *(rzt--) = '\0'; + + zt=z; + while( sqliteCharVal((unsigned char *)zt)!=0 ){ + z=zt; + sqliteNextChar(zt); + for(i=1; zt-i>=z; ++i){ + *(rzt--)=*(zt-i); + } + } + + wx_sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + wx_sqlite3_free(rz); +} + +/* +** An instance of the following structure holds the context of a +** stdev() or variance() aggregate computation. +** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II +** less prone to rounding errors +*/ +typedef struct StdevCtx StdevCtx; +struct StdevCtx { + double rM; + double rS; + i64 cnt; /* number of elements */ +}; + +/* +** An instance of the following structure holds the context of a +** mode() or median() aggregate computation. +** Depends on structures defined in map.c (see map & map) +** These aggregate functions only work for integers and floats although +** they could be made to work for strings. This is usually considered meaningless. +** Only usuall order (for median), no use of collation functions (would this even make sense?) +*/ +typedef struct ModeCtx ModeCtx; +struct ModeCtx { + i64 riM; /* integer value found so far */ + double rdM; /* double value found so far */ + i64 cnt; /* number of elements so far */ + double pcnt; /* number of elements smaller than a percentile */ + i64 mcnt; /* maximum number of occurrences (for mode) */ + i64 mn; /* number of occurrences (for mode and percentiles) */ + i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */ + map* m; /* map structure used for the computation */ + int done; /* whether the answer has been found */ +}; + +/* +** called for each value received during a calculation of stdev or variance +*/ +static void varianceStep(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + StdevCtx *p; + + double delta; + double x; + + assert( argc==1 ); + p = wx_sqlite3_aggregate_context(context, sizeof(*p)); + /* only consider non-null values */ + if( SQLITE_NULL != wx_sqlite3_value_numeric_type(argv[0]) ){ + p->cnt++; + x = wx_sqlite3_value_double(argv[0]); + delta = (x-p->rM); + p->rM += delta/p->cnt; + p->rS += delta*(x-p->rM); + } +} + +/* +** called for each value received during a calculation of mode of median +*/ +static void modeStep(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + ModeCtx *p; + i64 xi=0; + double xd=0.0; + i64 *iptr; + double *dptr; + int type; + + assert( argc==1 ); + type = wx_sqlite3_value_numeric_type(argv[0]); + + if( type == SQLITE_NULL) + return; + + p = wx_sqlite3_aggregate_context(context, sizeof(*p)); + + if( 0==(p->m) ){ + p->m = calloc(1, sizeof(map)); + if( type==SQLITE_INTEGER ){ + /* map will be used for integers */ + *(p->m) = map_make(int_cmp); + p->is_double = 0; + }else{ + p->is_double = 1; + /* map will be used for doubles */ + *(p->m) = map_make(double_cmp); + } + } + + ++(p->cnt); + + if( 0==p->is_double ){ + xi = wx_sqlite3_value_int64(argv[0]); + iptr = (i64*)calloc(1,sizeof(i64)); + *iptr = xi; + map_insert(p->m, iptr); + }else{ + xd = wx_sqlite3_value_double(argv[0]); + dptr = (double*)calloc(1,sizeof(double)); + *dptr = xd; + map_insert(p->m, dptr); + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the mode +** (most frequent value) +*/ +static void modeIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + ModeCtx *p = (ModeCtx*)pp; + + if( 0==p->is_double ){ + ei = *(int*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if( p->mcnt<c ){ + p->riM = ei; + p->mcnt = c; + p->mn=1; + } + }else{ + ed = *(double*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if(p->mcnt<c){ + p->rdM = ed; + p->mcnt = c; + p->mn=1; + } + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the median +** (the value such that the number of elements smaller is equal the the number of +** elements larger) +*/ +static void medianIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + double iL; + double iR; + int il; + int ir; + ModeCtx *p = (ModeCtx*)pp; + + if(p->done>0) + return; + + iL = p->pcnt; + iR = p->cnt - p->pcnt; + il = p->mcnt + c; + ir = p->cnt - p->mcnt; + + if( il >= iL ){ + if( ir >= iR ){ + ++p->mn; + if( 0==p->is_double ){ + ei = *(int*)(e); + p->riM += ei; + }else{ + ed = *(double*)(e); + p->rdM += ed; + } + }else{ + p->done=1; + } + } + p->mcnt+=c; +} + +/* +** Returns the mode value +*/ +static void modeFinalize(wx_sqlite3_context *context){ + ModeCtx *p; + p = wx_sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + map_iterate(p->m, modeIterate, p); + map_destroy(p->m); + free(p->m); + + if( 1==p->mn ){ + if( 0==p->is_double ) + wx_sqlite3_result_int64(context, p->riM); + else + wx_sqlite3_result_double(context, p->rdM); + } + } +} + +/* +** auxiliary function for percentiles +*/ +static void _medianFinalize(wx_sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + p->done=0; + map_iterate(p->m, medianIterate, p); + map_destroy(p->m); + free(p->m); + + if( 0==p->is_double ) + if( 1==p->mn ) + wx_sqlite3_result_int64(context, p->riM); + else + wx_sqlite3_result_double(context, p->riM*1.0/p->mn); + else + wx_sqlite3_result_double(context, p->rdM/p->mn); + } +} + +/* +** Returns the median value +*/ +static void medianFinalize(wx_sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/2.0; + _medianFinalize(context); + } +} + +/* +** Returns the lower_quartile value +*/ +static void lower_quartileFinalize(wx_sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the upper_quartile value +*/ +static void upper_quartileFinalize(wx_sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) wx_sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)*3/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the stdev value +*/ +static void stdevFinalize(wx_sqlite3_context *context){ + StdevCtx *p; + p = wx_sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + wx_sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1))); + }else{ + wx_sqlite3_result_double(context, 0.0); + } +} + +/* +** Returns the variance value +*/ +static void varianceFinalize(wx_sqlite3_context *context){ + StdevCtx *p; + p = wx_sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + wx_sqlite3_result_double(context, p->rS/(p->cnt-1)); + }else{ + wx_sqlite3_result_double(context, 0.0); + } +} + +#ifdef SQLITE_SOUNDEX + +/* relicoder factored code */ +/* +** Calculates the soundex value of a string +*/ + +static void soundex(const u8 *zIn, char *zResult){ + int i, j; + static const unsigned char iCode[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + zResult[j++] = code + '0'; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + }else{ + strcpy(zResult, "?000"); + } +} + +/* +** computes the number of different characters between the soundex value fo 2 strings +*/ +static void differenceFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + char zResult1[8]; + char zResult2[8]; + char *zR1 = zResult1; + char *zR2 = zResult2; + int rVal = 0; + int i = 0; + const u8 *zIn1; + const u8 *zIn2; + + assert( argc==2 ); + + if( wx_sqlite3_value_type(argv[0])==SQLITE_NULL || wx_sqlite3_value_type(argv[1])==SQLITE_NULL ){ + wx_sqlite3_result_null(context); + return; + } + + zIn1 = (u8*)wx_sqlite3_value_text(argv[0]); + zIn2 = (u8*)wx_sqlite3_value_text(argv[1]); + + soundex(zIn1, zR1); + soundex(zIn2, zR2); + + for(i=0; i<4; ++i){ + if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) ) + ++rVal; + sqliteNextChar(zR1); + sqliteNextChar(zR2); + } + wx_sqlite3_result_int(context, rVal); +} +#endif + +static void lastRowsFunc(wx_sqlite3_context *context, int argc, wx_sqlite3_value **argv){ + wx_sqlite3 *db = wx_sqlite3_context_db_handle(context); + wx_sqlite3_result_int64(context, wx_sqlite3_changes(db)); +} + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +int RegisterExtensionFunctions(wx_sqlite3 *db){ + static const struct FuncDef { + char *zName; + signed char nArg; + u8 argType; /* 0: none. 1: db 2: (-1) */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(wx_sqlite3_context*,int,wx_sqlite3_value **); + } aFuncs[] = { + /* math.h */ + { "acos", 1, 0, SQLITE_UTF8, 0, acosFunc }, + { "asin", 1, 0, SQLITE_UTF8, 0, asinFunc }, + { "atan", 1, 0, SQLITE_UTF8, 0, atanFunc }, + { "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + /* XXX alias */ + { "atan2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + { "acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc }, + { "asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc }, + { "atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc }, + + { "difference", 2, 0, SQLITE_UTF8, 0, differenceFunc}, + { "degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc }, + { "radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc }, + + { "cos", 1, 0, SQLITE_UTF8, 0, cosFunc }, + { "sin", 1, 0, SQLITE_UTF8, 0, sinFunc }, + { "tan", 1, 0, SQLITE_UTF8, 0, tanFunc }, + { "cot", 1, 0, SQLITE_UTF8, 0, cotFunc }, + { "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc }, + { "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc }, + { "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc }, + { "coth", 1, 0, SQLITE_UTF8, 0, cothFunc }, + + { "exp", 1, 0, SQLITE_UTF8, 0, expFunc }, + { "log", 1, 0, SQLITE_UTF8, 0, logFunc }, + { "ln", 1, 0, SQLITE_UTF8, 0, logFunc }, + { "log10", 1, 0, SQLITE_UTF8, 0, log10Func }, + { "power", 2, 0, SQLITE_UTF8, 0, powerFunc }, + { "sign", 1, 0, SQLITE_UTF8, 0, signFunc }, + { "sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc }, + { "square", 1, 0, SQLITE_UTF8, 0, squareFunc }, + + { "ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc }, + { "ceiling", 1, 0, SQLITE_UTF8, 0, ceilFunc }, + { "floor", 1, 0, SQLITE_UTF8, 0, floorFunc }, + + { "pi", 0, 0, SQLITE_UTF8, 1, piFunc }, + + { "last_rows_affected", 0, 0, SQLITE_UTF8, 0, lastRowsFunc }, + + /* string */ + { "replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc }, + { "charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc }, + { "charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc }, + { "leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc }, + { "rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc }, +#ifndef HAVE_TRIM + { "ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc }, + { "rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc }, + { "trim", 1, 0, SQLITE_UTF8, 0, trimFunc }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, +#endif + { "reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc }, + { "proper", 1, 0, SQLITE_UTF8, 0, properFunc }, + { "padl", 2, 0, SQLITE_UTF8, 0, padlFunc }, + { "padr", 2, 0, SQLITE_UTF8, 0, padrFunc }, + { "padc", 2, 0, SQLITE_UTF8, 0, padcFunc }, + { "strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc }, + + }; + /* Aggregate functions */ + static const struct FuncDefAgg { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(wx_sqlite3_context*,int,wx_sqlite3_value**); + void (*xFinalize)(wx_sqlite3_context*); + } aAggs[] = { + { "stdev", 1, 0, 0, varianceStep, stdevFinalize }, + { "variance", 1, 0, 0, varianceStep, varianceFinalize }, + { "mode", 1, 0, 0, modeStep, modeFinalize }, + { "median", 1, 0, 0, modeStep, medianFinalize }, + { "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize }, + { "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize }, + }; + int i; + + for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ + void *pArg = 0; + switch( aFuncs[i].argType ){ + case 1: pArg = db; break; + case 2: pArg = (void *)(-1); break; + } + /* wx_sqlite3CreateFunc */ + /* LMH no error checking */ + wx_sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, + aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0); +#if 0 + if( aFuncs[i].needCollSeq ){ + struct FuncDef *pFunc = wx_sqlite3FindFunction(db, aFuncs[i].zName, + strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0); + if( pFunc && aFuncs[i].needCollSeq ){ + pFunc->needCollSeq = 1; + } + } +#endif + } + + for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ + void *pArg = 0; + switch( aAggs[i].argType ){ + case 1: pArg = db; break; + case 2: pArg = (void *)(-1); break; + } + /* wx_sqlite3CreateFunc */ + /* LMH no error checking */ + wx_sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, + pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); +#if 0 + if( aAggs[i].needCollSeq ){ + struct FuncDefAgg *pFunc = wx_sqlite3FindFunction( db, aAggs[i].zName, + strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0); + if( pFunc && aAggs[i].needCollSeq ){ + pFunc->needCollSeq = 1; + } + } +#endif + } + return 0; +} + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +int wx_sqlite3_extension_init( + wx_sqlite3 *db, char **pzErrMsg, const wx_sqlite3_api_routines *pApi){ + SQLITE_EXTENSION_INIT2(pApi); + RegisterExtensionFunctions(db); + return 0; +} +#endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */ + +map map_make(cmp_func cmp){ + map r; + r.cmp=cmp; + r.base = 0; + + return r; +} + +void* xcalloc(size_t nmemb, size_t size, char* s){ + void* ret = calloc(nmemb, size); + return ret; +} + +void xfree(void* p){ + free(p); +} + +void node_insert(node** n, cmp_func cmp, void *e){ + int c; + node* nn; + if(*n==0){ + nn = (node*)xcalloc(1,sizeof(node), "for node"); + nn->data = e; + nn->count = 1; + *n=nn; + }else{ + c=cmp((*n)->data,e); + if(0==c){ + ++((*n)->count); + xfree(e); + }else if(c>0){ + /* put it right here */ + node_insert(&((*n)->l), cmp, e); + }else{ + node_insert(&((*n)->r), cmp, e); + } + } +} + +void map_insert(map *m, void *e){ + node_insert(&(m->base), m->cmp, e); +} + +void node_iterate(node *n, map_iterator iter, void* p){ + if(n){ + if(n->l) + node_iterate(n->l, iter, p); + iter(n->data, n->count, p); + if(n->r) + node_iterate(n->r, iter, p); + } +} + +void map_iterate(map *m, map_iterator iter, void* p){ + node_iterate(m->base, iter, p); +} + +void node_destroy(node *n){ + if(0!=n){ + xfree(n->data); + if(n->l) + node_destroy(n->l); + if(n->r) + node_destroy(n->r); + + xfree(n); + } +} + +void map_destroy(map *m){ + node_destroy(m->base); +} + +int int_cmp(const void *a, const void *b){ + i64 aa = *(i64 *)(a); + i64 bb = *(i64 *)(b); + /* printf("cmp %d <=> %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa<bb) + return -1; + else + return 1; +} + +int double_cmp(const void *a, const void *b){ + double aa = *(double *)(a); + double bb = *(double *)(b); + /* printf("cmp %d <=> %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa<bb) + return -1; + else + return 1; +} + +void print_elem(void *e, i64 c, void* p){ + int ee = *(int*)(e); + printf("%d => %lld\n", ee,c); +} + + |
