#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
#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
#include "sqlite3.h"
#endif
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#ifndef _MAP_H_
#define _MAP_H_
#if 0#endif
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;
map map_make(cmp_func cmp);
void map_insert(map *m, void *e);
void map_iterate(map *m, map_iterator iter, void* p);
void map_destroy(map *m);
int int_cmp(const void *a, const void *b);
int double_cmp(const void *a, const void *b);
#endif
static char *sqlite3StrDup( const char *z ) {
char *res = sqlite3_malloc( (int) (strlen(z)+1) );
return strcpy( res, z );
}
static const u8 xtra_utf8_bytes[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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,
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,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
};
static const int xtra_utf8_bits[] = {
0,
12416,
925824,
63447168
};
static const int utf_mask[] = {
0x00000000,
0xffffff80,
0xfffff800,
0xffff0000,
};
#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 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#endif
#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
#define sqliteCharVal(X) sqlite3ReadUtf8(X)
#define GEN_MATH_WRAP_DOUBLE_1(name, function) \
static void name(sqlite3_context *context, int argc, sqlite3_value **argv){\
double rVal = 0.0, val;\
assert( argc==1 );\
switch( sqlite3_value_type(argv[0]) ){\
case SQLITE_NULL: {\
sqlite3_result_null(context);\
break;\
}\
default: {\
rVal = sqlite3_value_double(argv[0]);\
errno = 0;\
val = function(rVal);\
if (errno == 0) {\
sqlite3_result_double(context, val);\
} else {\
sqlite3_result_error(context, strerror(errno), errno);\
}\
break;\
}\
}\
}\
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt)
GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos)
GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin)
GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan)
#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)
#endif
static double cot(double x){
return 1.0/tan(x);
}
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin)
GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos)
GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan)
#endif
GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot)
static double coth(double x){
return 1.0/tanh(x);
}
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
#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)
#endif
GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth)
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
#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)
#undef M_PI
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static double deg2rad(double x){
return x*M_PI/180.0;
}
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)
static void piFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_result_double(context, M_PI);
}
#endif
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;
}
}
}
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
static void powerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
double r1 = 0.0;
double r2 = 0.0;
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);
}
}
}
#endif
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));
}
}
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
#if SQLITE_VERSION_NUMBER < 3035000
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: {
rVal = sqlite3_value_double(argv[0]);
rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0;
sqlite3_result_double(context, rVal);
break;
}
}
}
#endif
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: {
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) ceil(rVal));
break;
}
}
}
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: {
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;
}
}
}
#endif
static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
unsigned char *z;
unsigned char *zo;
i64 iCount;
i64 nLen;
i64 nTLen;
i64 i=0;
if( argc!=2 || SQLITE_NULL==sqlite3_value_type(argv[0]) )
return;
iCount = sqlite3_value_int64(argv[1]);
if( iCount<0 ){
sqlite3_result_error(context, "domain error", -1);
}else{
nLen = sqlite3_value_bytes(argv[0]);
nTLen = nLen*iCount;
z=sqlite3_malloc(nTLen+1);
zo=sqlite3_malloc(nLen+1);
if (!z || !zo){
sqlite3_result_error_nomem(context);
if (z) sqlite3_free(z);
if (zo) sqlite3_free(zo);
return;
}
strcpy((char*)zo, (char*)sqlite3_value_text(argv[0]));
for(i=0; i<iCount; ++i){
strcpy((char*)(z+i*nLen), (char*)zo);
}
sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
sqlite3_free(z);
sqlite3_free(zo);
}
}
#ifndef HAVE_ISBLANK
int isblank(char c){
return( ' '==c || '\t'==c );
}
#endif
static void properFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const unsigned char *z;
unsigned char *zo;
unsigned char *zt;
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{
r = tolower(r);
}
c=0;
}
*(zt++) = r;
}
*zt = '\0';
sqlite3_result_text(context, (char*)zo, -1, SQLITE_TRANSIENT);
sqlite3_free(zo);
}
static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 ilen;
i64 zl;
int i = 0;
const char *zi;
char *zo;
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]);
if(ilen<0){
sqlite3_result_error(context, "domain error", -1);
return;
}
zl = sqlite3Utf8CharLen(zi, -1);
if( zl>=ilen ){
zo = sqlite3StrDup(zi);
if (!zo){
sqlite3_result_error_nomem(context);
return;
}
sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
}else{
zo = sqlite3_malloc((int) (strlen(zi)+ilen-zl+1));
if (!zo){
sqlite3_result_error_nomem(context);
return;
}
zt = zo;
for(i=1; i+zl<=ilen; ++i){
*(zt++)=' ';
}
strcpy(zt,zi);
}
sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
sqlite3_free(zo);
}
}
static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 ilen;
i64 zl;
i64 zll;
int i = 0;
const char *zi;
char *zo;
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]);
if(ilen<0){
sqlite3_result_error(context, "domain error", -1);
return;
}
zl = sqlite3Utf8CharLen(zi, -1);
if( zl>=ilen ){
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<=ilen; ++i){
*(zt++) = ' ';
}
*zt = '\0';
}
sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
sqlite3_free(zo);
}
}
static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 ilen;
i64 zl;
i64 zll;
int i = 0;
const char *zi;
char *zo;
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]);
if(ilen<0){
sqlite3_result_error(context, "domain error", -1);
return;
}
zl = sqlite3Utf8CharLen(zi, -1);
if( zl>=ilen ){
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 = zo;
for(i=1; 2*i+zl<=ilen; ++i){
*(zt++) = ' ';
}
strcpy(zt, zi);
zt+=zll;
for(; i+zl<=ilen; ++i){
*(zt++) = ' ';
}
*zt = '\0';
}
sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
sqlite3_free(zo);
}
}
static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *zi1;
const char *zi2;
const char *z1;
const char *z21;
const char *z22;
char *zo;
char *zot;
int c1 = 0;
int c2 = 0;
assert( argc==2 );
if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){
sqlite3_result_null(context);
}else{
zi1 = (char *)sqlite3_value_text(argv[0]);
zi2 = (char *)sqlite3_value_text(argv[1]);
zo = sqlite3_malloc((int) (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);
}
}
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;
}
static void charindexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const u8 *z1;
u8 *z2;
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<0){
s=0;
}
}else{
s = 0;
}
rVal = _substr((char *)z1,(char *)z2,s,NULL);
sqlite3_result_int(context, rVal+1);
}
static void leftFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
int c=0;
int cc=0;
int l=0;
const unsigned char *z;
const unsigned char *zt;
unsigned 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 = sqlite3_value_text(argv[0]);
l = sqlite3_value_int(argv[1]);
zt = z;
while( sqliteCharVal(zt) && c++<l)
sqliteNextChar(zt);
cc=zt-z;
rz = sqlite3_malloc(zt-z+1);
if (!rz){
sqlite3_result_error_nomem(context);
return;
}
strncpy((char*) rz, (char*) z, zt-z);
*(rz+cc) = '\0';
sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT);
sqlite3_free(rz);
}
static void rightFunc(sqlite3_context *context, int argc, 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 == 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)
cc=0;
while( 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);
}
#ifndef HAVE_TRIM
const char* ltrim(const char* s){
while( *s==' ' )
++s;
return s;
}
void rtrim(char* s){
char* ss = s+strlen(s)-1;
while( ss>=s && *ss==' ' )
--ss;
*(ss+1)='\0';
}
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);
}
static void rtrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *z;
char *rz;
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);
}
static void trimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *z;
char *rz;
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, SQLITE_TRANSIENT);
sqlite3_free(rz);
}
#endif
#if 0#endif
#ifndef HAVE_TRIM
static void replaceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *z1;
const char *z2;
const char *z3;
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]) ){
sqlite3_result_null(context);
return;
}
z1 = sqlite3_value_text(argv[0]);
z2 = sqlite3_value_text(argv[1]);
z3 = sqlite3_value_text(argv[2]);
if( 0==z2 ){
z2="";
}
if( 0==z3 ){
z3="";
}
lz1 = strlen(z1);
lz2 = strlen(z2);
lz3 = strlen(z3);
#if 0#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));
sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
sqlite3_free(zo);
}
#endif
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 = (int) 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);
}
}
sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT);
sqlite3_free(rz);
}
typedef struct StdevCtx StdevCtx;
struct StdevCtx {
double rM;
double rS;
i64 cnt;
};
typedef struct ModeCtx ModeCtx;
struct ModeCtx {
i64 riM;
double rdM;
i64 cnt;
double pcnt;
i64 mcnt;
i64 mn;
i64 is_double;
map* m;
int done;
};
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));
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);
}
}
static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){
ModeCtx *p;
i64 xi=0;
double xd=0.0;
i64 *iptr;
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 ){
*(p->m) = map_make(int_cmp);
p->is_double = 0;
}else{
p->is_double = 1;
*(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);
}
}
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;
}
}
}
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;
}
static void modeFinalize(sqlite3_context *context){
ModeCtx *p;
p = 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 )
sqlite3_result_int64(context, p->riM);
else
sqlite3_result_double(context, p->rdM);
}
}
}
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);
}
}
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);
}
}
static void lower_quartileFinalize(sqlite3_context *context){
ModeCtx *p;
p = (ModeCtx*) sqlite3_aggregate_context(context, 0);
if( p!=0 ){
p->pcnt = (p->cnt)/4.0;
_medianFinalize(context);
}
}
static void upper_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);
}
}
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);
}
}
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);
}
}
#ifdef SQLITE_SOUNDEX
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");
}
}
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<4; ++i){
if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) )
++rVal;
sqliteNextChar(zR1);
sqliteNextChar(zR2);
}
sqlite3_result_int(context, rVal);
}
#endif
static void lastRowsFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_result_int64(context, sqlite3_changes(db));
}
int RegisterExtensionFunctions(sqlite3 *db){
static const struct FuncDef {
char *zName;
signed char nArg;
u8 argType;
u8 eTextRep;
u8 needCollSeq;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
{ "acos", 1, 0, SQLITE_UTF8, 0, acosFunc },
{ "asin", 1, 0, SQLITE_UTF8, 0, asinFunc },
{ "atan", 1, 0, SQLITE_UTF8, 0, atanFunc },
#endif
{ "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func },
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
{ "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 },
#endif
{ "cot", 1, 0, SQLITE_UTF8, 0, cotFunc },
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
{ "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc },
{ "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc },
{ "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc },
#endif
{ "coth", 1, 0, SQLITE_UTF8, 0, cothFunc },
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
{ "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 },
#endif
{ "square", 1, 0, SQLITE_UTF8, 0, squareFunc },
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
{ "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 },
#endif
{ "last_rows_affected", 0, 0, SQLITE_UTF8, 0, lastRowsFunc },
{ "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 },
};
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;
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;
}
sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
#if 0#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;
}
sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
#if 0#endif
}
return 0;
}
#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
int sqlite3_extension_init(
sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){
SQLITE_EXTENSION_INIT2(pApi);
RegisterExtensionFunctions(db);
return 0;
}
#endif
map map_make(cmp_func cmp){
map r;
r.cmp=cmp;
r.base = 0;
return r;
}
static
void* xcalloc(size_t nmemb, size_t size, char* s){
void* ret = calloc(nmemb, size);
return ret;
}
static
void xfree(void* p){
free(p);
}
static
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){
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);
}
static
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);
}
static
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);
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);
if(aa==bb)
return 0;
else if(aa<bb)
return -1;
else
return 1;
}
#if 0#endif