extension-functions.c

download extension-functions.c

of 51

Transcript of extension-functions.c

  • 7/28/2019 extension-functions.c

    1/51

    /*This library will provide commonmathematical and string functions inSQL queries using the operating systemlibraries or provideddefinitions. It includes the followingfunctions:

    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 inrecent versions of SQLite and so by defaultdo 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 -lsqlite3if your sqlite3 is installed from Mac ports,

    or-I /sw/include/ -L/sw/lib -lsqlite3if installed with Fink.)* Windows:1. Install MinGW (http://www.mingw.org/)

    and you will get the gcc

  • 7/28/2019 extension-functions.c

    2/51

    (gnu compiler collection)2. add the path to your path variable (isn't

    done during theinstallation!)3. compile:gcc -shared -I "path" -o

    libsqlitefunctions.so extension-functions.c

    (path = path of sqlite3ext.h; i.e.C:\programs\sqlite)

    Usage instructions for applications callingthe sqlite3 API functions:

    In your application, callsqlite3_enable_load_extension(db,1) to

    allow loading external libraries. Then loadthe library libsqlitefunctions

    using sqlite3_load_extension; the thirdargument should be 0.

    See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions.

    Select statements may now use thesefunctions, as in

    SELECT cos(radians(inclination)) FROMsatsum WHERE satnum = 25544;

    Usage instructions for the 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.707106781186548Note: Loading extensions is by default

    prohibited as asecurity measure; see "Security

    Considerations" inhttp://www.sqlite.org/cvstrac/wiki?

    p=LoadableExtensions.If the sqlite3 program and library are built

    thisway, you cannot use these functions from

    the program, you

    must write your own program using thesqlite3 API, and call

    sqlite3_enable_load_extension asdescribed above, or else

  • 7/28/2019 extension-functions.c

    3/51

    rebuilt the sqlite3 program to allowloadable extensions.

    Alterations:The instructions are for Linux, Mac OS X,and Windows; users of otherOSes may need to modify this procedure.

    In particular, if your mathlibrary lacks one or more of the needed trigor log functions, commentout the appropriate HAVE_ #define at thetop of file. If you do notwish to make a loadable module, commentout the define forCOMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE.If you are using a

    version of SQLite without the trim functionsand replace, comment outthe HAVE_TRIM #define.

    Liam Healy

    History:2010-01-06 Correct check for argc insquareFunc, and add Windows

    compilation instructions.2009-06-24 Correct check for argc inproperFunc.2008-09-14 Add check that memory wasactually allocated aftersqlite3_malloc or sqlite3StrDup, callsqlite3_result_error_nomem ifnot. Thanks to Robert Simpson.2008-06-13 Change to instructions to

    indicate use of the math libraryand that program might work.2007-10-01 Minor clarification toinstructions.2007-09-29 Compilation as loadable moduleis optional withCOMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE.2007-09-28 Use sqlite3_extension_init andmacros

    SQLITE_EXTENSION_INIT1,SQLITE_EXTENSION_INIT2, so that it workswithsqlite3_load_extension. Thanks to Eric

  • 7/28/2019 extension-functions.c

    4/51

    Higashino and Joe Wilson.New instructions for Mac compilation.2007-09-17 With help from Joe Wilson andNuno Luca, made use ofexternal interfaces so that compilation is nolonger dependent onSQLite source code. Merged source,

    header, and README into a singlefile. Added casts so that Mac will compilewithout warnings (unsignedand signed char).2007-09-05 Included some definitions fromsqlite 3.3.13 so that thiswill continue to work in newer versions ofsqlite. Completeddescription of functions available.

    2007-03-27 Revised description.2007-03-23 Small cleanup and a bug fix onthe code. This was mainlyletting errno flag errors encountered in themath library and checkingthe result, rather than pre-checking. Thisfixes a bug in power thatwould cause an error if any non-positivenumber was raised to any

    power.2007-02-07 posted by Mikey C to sqlitemailing list.Original code 2006 June 05 by relicoder.

    */

    //#include "config.h"

    #defineCOMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE1#define HAVE_ACOSH 1#define HAVE_ASINH 1#define HAVE_ATANH 1#define HAVE_SINH 1#define HAVE_COSH 1#define HAVE_TANH 1

    #define HAVE_LOG10 1#define HAVE_ISBLANK 1#define SQLITE_SOUNDEX 1#define HAVE_TRIM 1 /* LMH 2007-03-25

  • 7/28/2019 extension-functions.c

    5/51

    if sqlite has trim functions */

    #ifdefCOMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE#include "sqlite3ext.h"SQLITE_EXTENSION_INIT1#else

    #include "sqlite3.h"#endif

    #include /* relicoder */#include #include #include #include /* LMH 2007-03-25 */

    #include #include

    #ifndef _MAP_H_#define _MAP_H_

    #include

    /*** Simple binary tree implementation to usein median, mode and quartile calculations** Tree is not necessarily balanced. Thatwould require something like red&blacktrees of AVL*/

    typedef int(*cmp_func)(const void *, const

    void *);typedef void(*map_iterator)(void*, int64_t,void*);

    typedef struct node{struct node *l;struct node *r;void* data;int64_t count;

    } node;

    typedef struct map{node *base;

  • 7/28/2019 extension-functions.c

    6/51

    cmp_func cmp;short free;

    } map;

    /*** creates a map given a comparisonfunction

    */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 inthe 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 *sqlite3StrDup( const char *z ) {

  • 7/28/2019 extension-functions.c

    7/51

    char *res = sqlite3_malloc( strlen(z)+1 );return strcpy( res, z );

    }

    /*** These are copied verbatim from fun.c soas to not have the names exported

    */

    /* LMH from sqlite3 3.3.13 *//*** This table maps from the first byte of aUTF-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,};

  • 7/28/2019 extension-functions.c

    8/51

    /*** This table maps from the number oftrailing bytes in a UTF-8 character** to an integer constant that is effectivelycalculated for each character** read by a naive implementation of a UTF-8character reader. The code

    ** in the READ_UTF8 macro explains thingsbest.*/static const int xtra_utf8_bits[] = {

    0,12416, /* (0xC0

  • 7/28/2019 extension-functions.c

    9/51

    case 1: c = (c

  • 7/28/2019 extension-functions.c

    10/51

    return r;}

    /*** X is a pointer to the first byte of a UTF-8character. 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)sqlite3ReadUtf8(X)

    /*

    ** This is a macro that facilitates writtingwrappers for math.h functions** it creates code for a function to use inSQlite that gets one numeric input** and returns a floating point value.**** Could have been implemented usingpointers 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 towrap (eg: sin)** domain: boolean condition that CAN'Thappen in terms of the input parameter rVal

    ** (eg: rval

  • 7/28/2019 extension-functions.c

    11/51

  • 7/28/2019 extension-functions.c

    12/51

    static double acosh(double x){return log(x + sqrt(x*x - 1.0));

    }#endif

    GEN_MATH_WRAP_DOUBLE_1(acoshFunc,acosh)

    #ifndef HAVE_ASINHstatic double asinh(double x){

    return log(x + sqrt(x*x + 1.0));}#endif

    GEN_MATH_WRAP_DOUBLE_1(asinhFunc,asinh)

    #ifndef HAVE_ATANHstatic 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) soit'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);

    }

  • 7/28/2019 extension-functions.c

    13/51

    /*** Many systems don't have hyperbolictrigonometric functions so this will emulate** them on those systems directly from thedefinition 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. Thiswill emulate it*/

    #ifndef HAVE_LOG10static double log10(double x){

    static double l10 = -1.0;if( l10

  • 7/28/2019 extension-functions.c

    14/51

    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.hdoesn'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 ofPI=3.1415... */static void piFunc(sqlite3_context *context,int argc, sqlite3_value **argv){

    sqlite3_result_double(context, M_PI);}

    /*

  • 7/28/2019 extension-functions.c

    15/51

    ** Implements the sqrt function, it has thepeculiarity of returning an integer when the** the argument is an integer.** Since SQLite isn't strongly typed (almostuntyped actually) this is a bit pedantic*/static void squareFunc(sqlite3_context

    *context, int argc, sqlite3_value **argv){i64 iVal = 0;double rVal = 0.0;assert( argc==1 );switch( sqlite3_value_type(argv[0]) ){

    case SQLITE_INTEGER: {iVal = sqlite3_value_int64(argv[0]);sqlite3_result_int64(context, iVal*iVal);break;

    }case SQLITE_NULL: {

    sqlite3_result_null(context);break;

    }default: {

    rVal = sqlite3_value_double(argv[0]);sqlite3_result_double(context,

    rVal*rVal);

    break;}

    }}

    /*** Wraps the pow math.h function** When both the base and the exponent areintegers the result should be integer

    ** (see sqrt just before this). Here the resultis always double*//* LMH 2007-03-25 Changed to use errno; nopre-checking for errors. Also removes

    but that was present in the pre-checkingthat called sqlite3_result_error on

    a non-positive first argument, which is notalways an error. */

    static void powerFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    double r1 = 0.0;double r2 = 0.0;

  • 7/28/2019 extension-functions.c

    16/51

    double val;

    assert( argc==2 );

    if( sqlite3_value_type(argv[0]) ==SQLITE_NULL || sqlite3_value_type(argv[1])== SQLITE_NULL ){

    sqlite3_result_null(context);}else{

    r1 = sqlite3_value_double(argv[0]);r2 = sqlite3_value_double(argv[1]);errno = 0;val = pow(r1,r2);if (errno == 0) {

    sqlite3_result_double(context, val);} else {

    sqlite3_result_error(context,strerror(errno), errno);

    }}

    }

    /*** atan2 wrapper*/

    static void atn2Func(sqlite3_context*context, int argc, sqlite3_value **argv){

    double r1 = 0.0;double r2 = 0.0;

    assert( argc==2 );

    if( sqlite3_value_type(argv[0]) ==SQLITE_NULL || sqlite3_value_type(argv[1])

    == SQLITE_NULL ){sqlite3_result_null(context);

    }else{r1 = sqlite3_value_double(argv[0]);r2 = sqlite3_value_double(argv[1]);sqlite3_result_double(context,

    atan2(r1,r2));}

    }

    /*** Implementation of the sign() function** return one of 3 possibilities +1,0 or -1

  • 7/28/2019 extension-functions.c

    17/51

    when the argument is respectively** positive, 0 or negative.** When the argument is NULL the result isalso NULL (completly conventional)*/static void signFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    double rVal=0.0;i64 iVal=0;assert( argc==1 );switch( sqlite3_value_type(argv[0]) ){

    case SQLITE_INTEGER: {iVal = sqlite3_value_int64(argv[0]);iVal = ( iVal > 0) ? 1: ( iVal < 0 ) ? -1: 0;sqlite3_result_int64(context, iVal);break;

    }case SQLITE_NULL: {

    sqlite3_result_null(context);break;

    }default: {

    /* 2nd change below. Line for abs was: if(rVal 0) ? 1: ( rVal < 0 ) ? -1: 0;sqlite3_result_double(context, rVal);break;

    }}

    }

    /*** smallest integer value not less thanargument*/static void ceilFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    double rVal=0.0;i64 iVal=0;assert( argc==1 );

    switch( sqlite3_value_type(argv[0]) ){case SQLITE_INTEGER: {

    i64 iVal = sqlite3_value_int64(argv[0]);sqlite3_result_int64(context, iVal);

  • 7/28/2019 extension-functions.c

    18/51

    break;}case SQLITE_NULL: {

    sqlite3_result_null(context);break;

    }default: {

    rVal = sqlite3_value_double(argv[0]);sqlite3_result_int64(context, (i64)

    ceil(rVal));break;

    }}

    }

    /*

    ** largest integer value not greater thanargument*/static void floorFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    double rVal=0.0;i64 iVal=0;assert( argc==1 );switch( sqlite3_value_type(argv[0]) ){

    case SQLITE_INTEGER: {i64 iVal = sqlite3_value_int64(argv[0]);sqlite3_result_int64(context, iVal);break;

    }case SQLITE_NULL: {

    sqlite3_result_null(context);break;

    }

    default: {rVal = sqlite3_value_double(argv[0]);sqlite3_result_int64(context, (i64)

    floor(rVal));break;

    }}

    }

    /*** Given a string (s) in the first argumentand an integer (n) in the second returns the** string that constains s contatenated n

  • 7/28/2019 extension-functions.c

    19/51

    times*/static void replicateFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    unsigned char *z; /* input string */unsigned char *zo; /* result string */i64 iCount; /* times to repeat */

    i64 nLen; /* length of the inputstring (no multibyte considerations) */

    i64 nTLen; /* length of the resultstring (no multibyte considerations) */

    i64 i=0;

    if( argc!=2 ||SQLITE_NULL==sqlite3_value_type(argv[0]))

    return;

    iCount = sqlite3_value_int64(argv[1]);

    if( iCount

  • 7/28/2019 extension-functions.c

    20/51

    }

    /*** Some systems (win32 among others)don't have an isblank function, this willemulate it.** This function is not UFT-8 safe since it

    only analyses a byte character.*/#ifndef HAVE_ISBLANKint isblank(char c){

    return( ' '==c || '\t'==c );}#endif

    static void properFunc(sqlite3_context

    *context, int argc, 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==sqlite3_value_type(argv[0])){

    sqlite3_result_null(context);return;

    }

    z = sqlite3_value_text(argv[0]);zo = (unsigned char *)sqlite3StrDup((char

    *) z);

    if (!zo) {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{

  • 7/28/2019 extension-functions.c

    21/51

    r = tolower(r);}c=0;

    }*(zt++) = r;

    }*zt = '\0';

    sqlite3_result_text(context, (char*)zo, -1,SQLITE_TRANSIENT);

    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(sqlite3_context*context, int argc, 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( sqlite3_value_type(argv[0]) ==SQLITE_NULL ){

    sqlite3_result_null(context);}else{

    zi = (char *)sqlite3_value_text(argv[0]);ilen = sqlite3_value_int64(argv[1]);/* check domain */if(ilen=ilen ){

    /* string is longer than the requested

  • 7/28/2019 extension-functions.c

    22/51

    pad length, return the same string (dup it) */zo = sqlite3StrDup(zi);if (!zo){sqlite3_result_error_nomem(context);return;

    }sqlite3_result_text(context, zo, -1,

    SQLITE_TRANSIENT);}else{

    zo = sqlite3_malloc(strlen(zi)+ilen-zl+1);if (!zo){sqlite3_result_error_nomem(context);return;

    }zt = zo;for(i=1; i+zl=n it's a NOP** padl(NULL) = NULL

    */static void padrFunc(sqlite3_context*context, int argc, 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;

  • 7/28/2019 extension-functions.c

    23/51

    assert( argc==2 );

    if( sqlite3_value_type(argv[0]) ==SQLITE_NULL ){

    sqlite3_result_null(context);}else{

    zi = (char *)sqlite3_value_text(argv[0]);

    ilen = sqlite3_value_int64(argv[1]);/* check domain */if(ilen=ilen ){

    /* string is longer than the requestedpad length, return the same string (dup it) */

    zo = sqlite3StrDup(zi);if (!zo){sqlite3_result_error_nomem(context);return;

    }sqlite3_result_text(context, zo, -1,

    SQLITE_TRANSIENT);

    }else{zll = strlen(zi);zo = sqlite3_malloc(zll+ilen-zl+1);if (!zo){sqlite3_result_error_nomem(context);return;

    }zt = strcpy(zo,zi)+zll;for(i=1; i+zl

  • 7/28/2019 extension-functions.c

    24/51

    ** and adds spaces at the begining of s untilit has a length of n characters.** Tries to add has many characters at theleft as at the right.** When s has a length >=n it's a NOP** padl(NULL) = NULL*/

    static void padcFunc(sqlite3_context*context, int argc, 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( sqlite3_value_type(argv[0]) ==SQLITE_NULL ){

    sqlite3_result_null(context);}else{

    zi = (char *)sqlite3_value_text(argv[0]);ilen = sqlite3_value_int64(argv[1]);/* check domain */if(ilen=ilen ){/* string is longer than the requested

    pad length, return the same string (dup it) */zo = sqlite3StrDup(zi);if (!zo){sqlite3_result_error_nomem(context);return;

    }sqlite3_result_text(context, zo, -1,

    SQLITE_TRANSIENT);}else{

    zll = strlen(zi);zo = sqlite3_malloc(zll+ilen-zl+1);

  • 7/28/2019 extension-functions.c

    25/51

    if (!zo){sqlite3_result_error_nomem(context);return;

    }zt = zo;for(i=1; 2*i+zl

  • 7/28/2019 extension-functions.c

    26/51

    zi1 = (char *)sqlite3_value_text(argv[0]);zi2 = (char *)sqlite3_value_text(argv[1]);/*** maybe I could allocate less, but that

    would imply 2 passes, rather waste** (possibly) some memory*/

    zo = sqlite3_malloc(strlen(zi1)+1);if (!zo){

    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';

    sqlite3_result_text(context, zo, -1,SQLITE_TRANSIENT);

    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*

  • 7/28/2019 extension-functions.c

    27/51

    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++)=0 ? rVal+s : rVal;

    }

    /*** given 2 input strings (s1,s2) and aninteger (n) searches from the nth character** for the string s1. Returns the position

  • 7/28/2019 extension-functions.c

    28/51

    where the match occured.** Characters are counted from 1.** 0 is returned when no match occurs.*/

    static void charindexFunc(sqlite3_context*context, int argc, 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==sqlite3_value_type(argv[0])

    ||SQLITE_NULL==sqlite3_value_type(argv[1])){

    sqlite3_result_null(context);return;

    }

    z1 = sqlite3_value_text(argv[0]);if( z1==0 ) return;z2 = (u8*) sqlite3_value_text(argv[1]);

    if(argc==3){s = sqlite3_value_int(argv[2])-1;if(s

  • 7/28/2019 extension-functions.c

    29/51

    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==sqlite3_value_type(argv[0])||SQLITE_NULL==sqlite3_value_type(argv[1])){

    sqlite3_result_null(context);return;

    }

    z = sqlite3_value_text(argv[0]);l = sqlite3_value_int(argv[1]);zt = z;

    while( sqliteCharVal(zt) && c++

  • 7/28/2019 extension-functions.c

    30/51

    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 ==sqlite3_value_type(argv[0]) || SQLITE_NULL== sqlite3_value_type(argv[1])){

    sqlite3_result_null(context);return;

    }

    z = (char *)sqlite3_value_text(argv[0]);l = 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 ){sqliteNextChar(zt);

    }

    rz = sqlite3_malloc(ze-zt+1);if (!rz){

    sqlite3_result_error_nomem(context);return;

    }

    strcpy((char*) rz, (char*) (zt));sqlite3_result_text(context, (char*)rz, -1,

    SQLITE_TRANSIENT);sqlite3_free(rz);

  • 7/28/2019 extension-functions.c

    31/51

    }

    #ifndef HAVE_TRIM/*** removes the whitespaces at the beginingof a string.*/

    const char* ltrim(const char* s){while( *s==' ' )

    ++s;return s;

    }

    /*** removes the whitespaces at the end of astring.

    ** !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 beginingof a string*/static void ltrimFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    const char *z;

    assert( argc==1);

    if(SQLITE_NULL==sqlite3_value_type(argv[0])){

    sqlite3_result_null(context);return;

    }z = sqlite3_value_text(argv[0]);sqlite3_result_text(context, ltrim(z), -1,

    SQLITE_TRANSIENT);}

    /*

  • 7/28/2019 extension-functions.c

    32/51

    ** Removes the whitespace at the end of astring*/static void rtrimFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    const char *z;char *rz;

    /* try not to change data in argv */

    assert( argc==1);

    if(SQLITE_NULL==sqlite3_value_type(argv[0])){

    sqlite3_result_null(context);return;

    }z = sqlite3_value_text(argv[0]);rz = sqlite3StrDup(z);rtrim(rz);sqlite3_result_text(context, rz, -1,

    SQLITE_TRANSIENT);sqlite3_free(rz);

    }

    /*** Removes the whitespace at the beginingand end of a string*/static void trimFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    const char *z;char *rz;/* try not to change data in argv */

    assert( argc==1);

    if(SQLITE_NULL==sqlite3_value_type(argv[0])){

    sqlite3_result_null(context);return;

    }

    z = sqlite3_value_text(argv[0]);rz = sqlite3StrDup(z);rtrim(rz);sqlite3_result_text(context, ltrim(rz), -1,

  • 7/28/2019 extension-functions.c

    33/51

    SQLITE_TRANSIENT);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, constchar *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 replacesoccurrences of s1 in s by s2*/

    static void replaceFunc(sqlite3_context*context, int argc, sqlite3_value **argv){

    const char *z1; /* string s (firstparameter) */

    const char *z2; /* string s1 (secondparameter) string to look for */

    const char *z3; /* string s2 (thirdparameter) string to replace occurrences ofs1 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==sqlite3_value_type(argv[0])

  • 7/28/2019 extension-functions.c

    34/51

    ){sqlite3_result_null(context);return;

    }

    z1 = sqlite3_value_text(argv[0]);z2 = sqlite3_value_text(argv[1]);

    z3 = 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 ){

    sqlite3_result_text(context, z1, -1,

    SQLITE_TRANSIENT);return;

    }#endif

    zt1=z1;zt2=z1;

    while(1){

    ret=_substr(z2,zt1 , 0, &zt2);

    if( ret

  • 7/28/2019 extension-functions.c

    35/51

    sqlite3_result_text(context, zo, -1,SQLITE_TRANSIENT);

    sqlite3_free(zo);}#endif

    /*

    ** given a string returns the same string butwith the characters in reverse order*/static void reverseFunc(sqlite3_context*context, int argc, 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==sqlite3_value_type(argv[0])){

    sqlite3_result_null(context);

    return;}z = (char *)sqlite3_value_text(argv[0]);l = strlen(z);rz = sqlite3_malloc(l+1);if (!rz){

    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);}

    }

  • 7/28/2019 extension-functions.c

    36/51

    sqlite3_result_text(context, rz, -1,SQLITE_TRANSIENT);

    sqlite3_free(rz);}

    /*** An instance of the following structure

    holds the context of a** stdev() or variance() aggregatecomputation.** implementaion ofhttp://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 structureholds the context of a** mode() or median() aggregate

    computation.** Depends on structures defined in map.c(see map & map)** These aggregate functions only work forintegers and floats although** they could be made to work for strings.This is usually considered meaningless.** Only usuall order (for median), no use ofcollation functions (would this even make

    sense?)*/typedef struct ModeCtx ModeCtx;struct ModeCtx {

    i64 riM; /* integer value found so far*/

    double rdM; /* double value found sofar */

    i64 cnt; /* number of elements so far

    */double pcnt; /* number of elements

    smaller than a percentile */i64 mcnt; /* maximum number of

  • 7/28/2019 extension-functions.c

    37/51

    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 acalculation of stdev or variance*/

    static void varianceStep(sqlite3_context*context, int argc, sqlite3_value **argv){

    StdevCtx *p;

    double delta;double x;

    assert( argc==1 );p = sqlite3_aggregate_context(context,

    sizeof(*p));/* only consider non-null values */if( SQLITE_NULL !=

    sqlite3_value_numeric_type(argv[0]) ){p->cnt++;x = 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 acalculation of mode of median*/static void modeStep(sqlite3_context*context, int argc, sqlite3_value **argv){

    ModeCtx *p;i64 xi=0;double xd=0.0;i64 *iptr;

  • 7/28/2019 extension-functions.c

    38/51

    double *dptr;int type;

    assert( argc==1 );type =

    sqlite3_value_numeric_type(argv[0]);

    if( type == SQLITE_NULL)return;

    p = 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 = sqlite3_value_int64(argv[0]);iptr = (i64*)calloc(1,sizeof(i64));*iptr = xi;map_insert(p->m, iptr);

    }else{

    xd = 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*

  • 7/28/2019 extension-functions.c

    39/51

    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->mcntriM = ei;p->mcnt = c;p->mn=1;

    }}else{

    ed = *(double*)(e);

    if( p->mcnt==c ){++p->mn;

    }else if(p->mcntrdM = ed;p->mcnt = c;p->mn=1;

    }

    }}

    /*** Auxiliary function that iterates allelements in a map and finds the median** (the value such that the number ofelements 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;

  • 7/28/2019 extension-functions.c

    40/51

  • 7/28/2019 extension-functions.c

    41/51

    static void _medianFinalize(sqlite3_context*context){

    ModeCtx *p;p = (ModeCtx*)

    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 )

    sqlite3_result_int64(context, p->riM);else

    sqlite3_result_double(context, p-

    >riM*1.0/p->mn);else

    sqlite3_result_double(context, p->rdM/p->mn);

    }}

    /*** Returns the median value

    */static void medianFinalize(sqlite3_context*context){

    ModeCtx *p;p = (ModeCtx*)

    sqlite3_aggregate_context(context, 0);if( p!=0 ){

    p->pcnt = (p->cnt)/2.0;_medianFinalize(context);

    }}

    /*** Returns the lower_quartile value*/static voidlower_quartileFinalize(sqlite3_context*context){

    ModeCtx *p;p = (ModeCtx*)

    sqlite3_aggregate_context(context, 0);if( p!=0 ){

  • 7/28/2019 extension-functions.c

    42/51

    p->pcnt = (p->cnt)/4.0;_medianFinalize(context);

    }}

    /*** Returns the upper_quartile value

    */static voidupper_quartileFinalize(sqlite3_context*context){

    ModeCtx *p;p = (ModeCtx*)

    sqlite3_aggregate_context(context, 0);if( p!=0 ){

    p->pcnt = (p->cnt)*3/4.0;

    _medianFinalize(context);}

    }

    /*** Returns the stdev value*/static void stdevFinalize(sqlite3_context*context){

    StdevCtx *p;p = sqlite3_aggregate_context(context, 0);if( p && p->cnt>1 ){

    sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1)));

    }else{sqlite3_result_double(context, 0.0);

    }}

    /*** Returns the variance value*/static void varianceFinalize(sqlite3_context*context){

    StdevCtx *p;p = sqlite3_aggregate_context(context, 0);if( p && p->cnt>1 ){

    sqlite3_result_double(context, p->rS/(p->cnt-1));

    }else{sqlite3_result_double(context, 0.0);

  • 7/28/2019 extension-functions.c

    43/51

  • 7/28/2019 extension-functions.c

    44/51

    static void differenceFunc(sqlite3_context*context, int argc, 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(sqlite3_value_type(argv[0])==SQLITE_NULL||

    sqlite3_value_type(argv[1])==SQLITE_NULL){

    sqlite3_result_null(context);return;

    }

    zIn1 = (u8*)sqlite3_value_text(argv[0]);zIn2 = (u8*)sqlite3_value_text(argv[1]);

    soundex(zIn1, zR1);soundex(zIn2, zR2);

    for(i=0; i

  • 7/28/2019 extension-functions.c

    45/51

    int RegisterExtensionFunctions(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)(sqlite3_context*,int,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,

  • 7/28/2019 extension-functions.c

    46/51

  • 7/28/2019 extension-functions.c

    47/51

    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)(sqlite3_context*,int,sqlite3_value**);void (*xFinalize)(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;

  • 7/28/2019 extension-functions.c

    48/51

    for(i=0; ineedCollSeq = 1;

    }}

    #endif}

    for(i=0; i

  • 7/28/2019 extension-functions.c

    49/51

    pFunc->needCollSeq = 1;}

    }#endif

    }return 0;

    }

    #ifdefCOMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULEint sqlite3_extension_init(

    sqlite3 *db, char **pzErrMsg, constsqlite3_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;

  • 7/28/2019 extension-functions.c

    50/51

    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);}

    }

  • 7/28/2019 extension-functions.c

    51/51