This source file includes following definitions.
- sqlite3GetFuncCollSeq
- minmaxFunc
- typeofFunc
- lengthFunc
- absFunc
- substrFunc
- roundFunc
- contextMalloc
- upperFunc
- lowerFunc
- ifnullFunc
- randomFunc
- randomBlob
- last_insert_rowid
- changes
- total_changes
- patternCompare
- likeFunc
- nullifFunc
- versionFunc
- sourceidFunc
- compileoptionusedFunc
- compileoptiongetFunc
- quoteFunc
- hexFunc
- zeroblobFunc
- replaceFunc
- trimFunc
- soundexFunc
- loadExt
- sumStep
- sumFinalize
- avgFinalize
- totalFinalize
- countStep
- countFinalize
- minmaxStep
- minMaxFinalize
- groupConcatStep
- groupConcatFinalize
- sqlite3RegisterBuiltinFunctions
- setLikeOptFlag
- sqlite3RegisterLikeFunctions
- sqlite3IsLikeFunction
- sqlite3RegisterGlobalFunctions
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
return context->pColl;
}
static void minmaxFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
int mask;
int iBest;
CollSeq *pColl;
assert( argc>1 );
mask = sqlite3_user_data(context)==0 ? 0 : -1;
pColl = sqlite3GetFuncCollSeq(context);
assert( pColl );
assert( mask==-1 || mask==0 );
iBest = 0;
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
for(i=1; i<argc; i++){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return;
if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=0 ){
testcase( mask==0 );
iBest = i;
}
}
sqlite3_result_value(context, argv[iBest]);
}
static void typeofFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
const char *z = 0;
UNUSED_PARAMETER(NotUsed);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER: z = "integer"; break;
case SQLITE_TEXT: z = "text"; break;
case SQLITE_FLOAT: z = "real"; break;
case SQLITE_BLOB: z = "blob"; break;
default: z = "null"; break;
}
sqlite3_result_text(context, z, -1, SQLITE_STATIC);
}
static void lengthFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int len;
assert( argc==1 );
UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_BLOB:
case SQLITE_INTEGER:
case SQLITE_FLOAT: {
sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
break;
}
case SQLITE_TEXT: {
const unsigned char *z = sqlite3_value_text(argv[0]);
if( z==0 ) return;
len = 0;
while( *z ){
len++;
SQLITE_SKIP_UTF8(z);
}
sqlite3_result_int(context, len);
break;
}
default: {
sqlite3_result_null(context);
break;
}
}
}
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER: {
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal<0 ){
if( (iVal<<1)==0 ){
sqlite3_result_error(context, "integer overflow", -1);
return;
}
iVal = -iVal;
}
sqlite3_result_int64(context, iVal);
break;
}
case SQLITE_NULL: {
sqlite3_result_null(context);
break;
}
default: {
double rVal = sqlite3_value_double(argv[0]);
if( rVal<0 ) rVal = -rVal;
sqlite3_result_double(context, rVal);
break;
}
}
}
static void substrFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *z;
const unsigned char *z2;
int len;
int p0type;
i64 p1, p2;
int negP2 = 0;
assert( argc==3 || argc==2 );
if( sqlite3_value_type(argv[1])==SQLITE_NULL
|| (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
){
return;
}
p0type = sqlite3_value_type(argv[0]);
p1 = sqlite3_value_int(argv[1]);
if( p0type==SQLITE_BLOB ){
len = sqlite3_value_bytes(argv[0]);
z = sqlite3_value_blob(argv[0]);
if( z==0 ) return;
assert( len==sqlite3_value_bytes(argv[0]) );
}else{
z = sqlite3_value_text(argv[0]);
if( z==0 ) return;
len = 0;
if( p1<0 ){
for(z2=z; *z2; len++){
SQLITE_SKIP_UTF8(z2);
}
}
}
if( argc==3 ){
p2 = sqlite3_value_int(argv[2]);
if( p2<0 ){
p2 = -p2;
negP2 = 1;
}
}else{
p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
}
if( p1<0 ){
p1 += len;
if( p1<0 ){
p2 += p1;
if( p2<0 ) p2 = 0;
p1 = 0;
}
}else if( p1>0 ){
p1--;
}else if( p2>0 ){
p2--;
}
if( negP2 ){
p1 -= p2;
if( p1<0 ){
p2 += p1;
p1 = 0;
}
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
while( *z && p1 ){
SQLITE_SKIP_UTF8(z);
p1--;
}
for(z2=z; *z2 && p2; p2--){
SQLITE_SKIP_UTF8(z2);
}
sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
}else{
if( p1+p2>len ){
p2 = len-p1;
if( p2<0 ) p2 = 0;
}
sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
}
}
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
int n = 0;
double r;
char *zBuf;
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
n = sqlite3_value_int(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
r = (double)((sqlite_int64)(r+0.5));
}else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
r = -(double)((sqlite_int64)((-r)+0.5));
}else{
zBuf = sqlite3_mprintf("%.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
}
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
sqlite3_free(zBuf);
}
sqlite3_result_double(context, r);
}
#endif
static void *contextMalloc(sqlite3_context *context, i64 nByte){
char *z;
sqlite3 *db = sqlite3_context_db_handle(context);
assert( nByte>0 );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
z = 0;
}else{
z = sqlite3Malloc((int)nByte);
if( !z ){
sqlite3_result_error_nomem(context);
}
}
return z;
}
static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
char *z1;
const char *z2;
int i, n;
UNUSED_PARAMETER(argc);
z2 = (char*)sqlite3_value_text(argv[0]);
n = sqlite3_value_bytes(argv[0]);
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
z1[i] = (char)sqlite3Toupper(z1[i]);
}
sqlite3_result_text(context, z1, -1, sqlite3_free);
}
}
}
static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
u8 *z1;
const char *z2;
int i, n;
UNUSED_PARAMETER(argc);
z2 = (char*)sqlite3_value_text(argv[0]);
n = sqlite3_value_bytes(argv[0]);
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
z1[i] = sqlite3Tolower(z1[i]);
}
sqlite3_result_text(context, (char *)z1, -1, sqlite3_free);
}
}
}
#if 0
static void ifnullFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
for(i=0; i<argc; i++){
if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
sqlite3_result_value(context, argv[i]);
break;
}
}
}
#endif
#define ifnullFunc versionFunc
static void randomFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite_int64 r;
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_randomness(sizeof(r), &r);
if( r<0 ){
r = -(r ^ (((sqlite3_int64)1)<<63));
}
sqlite3_result_int64(context, r);
}
static void randomBlob(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int n;
unsigned char *p;
assert( argc==1 );
UNUSED_PARAMETER(argc);
n = sqlite3_value_int(argv[0]);
if( n<1 ){
n = 1;
}
p = contextMalloc(context, n);
if( p ){
sqlite3_randomness(n, p);
sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
}
}
static void last_insert_rowid(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
static void changes(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int(context, sqlite3_changes(db));
}
static void total_changes(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int(context, sqlite3_total_changes(db));
}
struct compareInfo {
u8 matchAll;
u8 matchOne;
u8 matchSet;
u8 noCase;
};
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A,C) (*(A++))
# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
#else
# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
#endif
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
static int patternCompare(
const u8 *zPattern,
const u8 *zString,
const struct compareInfo *pInfo,
const int esc
){
int c, c2;
int invert;
int seen;
u8 matchOne = pInfo->matchOne;
u8 matchAll = pInfo->matchAll;
u8 matchSet = pInfo->matchSet;
u8 noCase = pInfo->noCase;
int prevEscape = 0;
while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
if( !prevEscape && c==matchAll ){
while( (c=sqlite3Utf8Read(zPattern,&zPattern)) == matchAll
|| c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(zString, &zString)==0 ){
return 0;
}
}
if( c==0 ){
return 1;
}else if( c==esc ){
c = sqlite3Utf8Read(zPattern, &zPattern);
if( c==0 ){
return 0;
}
}else if( c==matchSet ){
assert( esc==0 );
assert( matchSet<0x80 );
while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
SQLITE_SKIP_UTF8(zString);
}
return *zString!=0;
}
while( (c2 = sqlite3Utf8Read(zString,&zString))!=0 ){
if( noCase ){
GlogUpperToLower(c2);
GlogUpperToLower(c);
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, &zString);
GlogUpperToLower(c2);
}
}else{
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, &zString);
}
}
if( c2==0 ) return 0;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
return 0;
}else if( !prevEscape && c==matchOne ){
if( sqlite3Utf8Read(zString, &zString)==0 ){
return 0;
}
}else if( c==matchSet ){
int prior_c = 0;
assert( esc==0 );
seen = 0;
invert = 0;
c = sqlite3Utf8Read(zString, &zString);
if( c==0 ) return 0;
c2 = sqlite3Utf8Read(zPattern, &zPattern);
if( c2=='^' ){
invert = 1;
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
while( c2 && c2!=']' ){
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
c2 = sqlite3Utf8Read(zPattern, &zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else{
if( c==c2 ){
seen = 1;
}
prior_c = c2;
}
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
return 0;
}
}else if( esc==c && !prevEscape ){
prevEscape = 1;
}else{
c2 = sqlite3Utf8Read(zString, &zString);
if( noCase ){
GlogUpperToLower(c);
GlogUpperToLower(c2);
}
if( c!=c2 ){
return 0;
}
prevEscape = 0;
}
}
return *zString==0;
}
#ifdef SQLITE_TEST
int sqlite3_like_count = 0;
#endif
static void likeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *zA, *zB;
int escape = 0;
int nPat;
sqlite3 *db = sqlite3_context_db_handle(context);
zB = sqlite3_value_text(argv[0]);
zA = sqlite3_value_text(argv[1]);
nPat = sqlite3_value_bytes(argv[0]);
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
return;
}
assert( zB==sqlite3_value_text(argv[0]) );
if( argc==3 ){
const unsigned char *zEsc = sqlite3_value_text(argv[2]);
if( zEsc==0 ) return;
if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
escape = sqlite3Utf8Read(zEsc, &zEsc);
}
if( zA && zB ){
struct compareInfo *pInfo = sqlite3_user_data(context);
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
}
}
static void nullifFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
CollSeq *pColl = sqlite3GetFuncCollSeq(context);
UNUSED_PARAMETER(NotUsed);
if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){
sqlite3_result_value(context, argv[0]);
}
}
static void versionFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
}
static void sourceidFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
}
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptionusedFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zOptName;
assert( argc==1 );
UNUSED_PARAMETER(argc);
if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
}
}
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptiongetFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int n;
assert( argc==1 );
UNUSED_PARAMETER(argc);
n = sqlite3_value_int(argv[0]);
sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
#endif
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER:
case SQLITE_FLOAT: {
sqlite3_result_value(context, argv[0]);
break;
}
case SQLITE_BLOB: {
char *zText = 0;
char const *zBlob = sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( zBlob==sqlite3_value_blob(argv[0]) );
zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
if( zText ){
int i;
for(i=0; i<nBlob; i++){
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
}
zText[(nBlob*2)+2] = '\'';
zText[(nBlob*2)+3] = '\0';
zText[0] = 'X';
zText[1] = '\'';
sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
sqlite3_free(zText);
}
break;
}
case SQLITE_TEXT: {
int i,j;
u64 n;
const unsigned char *zArg = sqlite3_value_text(argv[0]);
char *z;
if( zArg==0 ) return;
for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
z = contextMalloc(context, ((i64)i)+((i64)n)+3);
if( z ){
z[0] = '\'';
for(i=0, j=1; zArg[i]; i++){
z[j++] = zArg[i];
if( zArg[i]=='\'' ){
z[j++] = '\'';
}
}
z[j++] = '\'';
z[j] = 0;
sqlite3_result_text(context, z, j, sqlite3_free);
}
break;
}
default: {
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
break;
}
}
}
static void hexFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i, n;
const unsigned char *pBlob;
char *zHex, *z;
assert( argc==1 );
UNUSED_PARAMETER(argc);
pBlob = sqlite3_value_blob(argv[0]);
n = sqlite3_value_bytes(argv[0]);
assert( pBlob==sqlite3_value_blob(argv[0]) );
z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
if( zHex ){
for(i=0; i<n; i++, pBlob++){
unsigned char c = *pBlob;
*(z++) = hexdigits[(c>>4)&0xf];
*(z++) = hexdigits[c&0xf];
}
*z = 0;
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
}
}
static void zeroblobFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
i64 n;
sqlite3 *db = sqlite3_context_db_handle(context);
assert( argc==1 );
UNUSED_PARAMETER(argc);
n = sqlite3_value_int64(argv[0]);
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
sqlite3_result_zeroblob(context, (int)n);
}
}
static void replaceFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *zStr;
const unsigned char *zPattern;
const unsigned char *zRep;
unsigned char *zOut;
int nStr;
int nPattern;
int nRep;
i64 nOut;
int loopLimit;
int i, j;
assert( argc==3 );
UNUSED_PARAMETER(argc);
zStr = sqlite3_value_text(argv[0]);
if( zStr==0 ) return;
nStr = sqlite3_value_bytes(argv[0]);
assert( zStr==sqlite3_value_text(argv[0]) );
zPattern = sqlite3_value_text(argv[1]);
if( zPattern==0 ){
assert( sqlite3_value_type(argv[1])==SQLITE_NULL
|| sqlite3_context_db_handle(context)->mallocFailed );
return;
}
if( zPattern[0]==0 ){
assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
sqlite3_result_value(context, argv[0]);
return;
}
nPattern = sqlite3_value_bytes(argv[1]);
assert( zPattern==sqlite3_value_text(argv[1]) );
zRep = sqlite3_value_text(argv[2]);
if( zRep==0 ) return;
nRep = sqlite3_value_bytes(argv[2]);
assert( zRep==sqlite3_value_text(argv[2]) );
nOut = nStr + 1;
assert( nOut<SQLITE_MAX_LENGTH );
zOut = contextMalloc(context, (i64)nOut);
if( zOut==0 ){
return;
}
loopLimit = nStr - nPattern;
for(i=j=0; i<=loopLimit; i++){
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
}else{
u8 *zOld;
sqlite3 *db = sqlite3_context_db_handle(context);
nOut += nRep - nPattern;
testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
sqlite3_free(zOut);
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3_free(zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
j += nRep;
i += nPattern-1;
}
}
assert( j+nStr-i+1==nOut );
memcpy(&zOut[j], &zStr[i], nStr-i);
j += nStr - i;
assert( j<=nOut );
zOut[j] = 0;
sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
}
static void trimFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *zIn;
const unsigned char *zCharSet;
int nIn;
int flags;
int i;
unsigned char *aLen = 0;
unsigned char **azChar = 0;
int nChar;
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
return;
}
zIn = sqlite3_value_text(argv[0]);
if( zIn==0 ) return;
nIn = sqlite3_value_bytes(argv[0]);
assert( zIn==sqlite3_value_text(argv[0]) );
if( argc==1 ){
static const unsigned char lenOne[] = { 1 };
static unsigned char * const azOne[] = { (u8*)" " };
nChar = 1;
aLen = (u8*)lenOne;
azChar = (unsigned char **)azOne;
zCharSet = 0;
}else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
return;
}else{
const unsigned char *z;
for(z=zCharSet, nChar=0; *z; nChar++){
SQLITE_SKIP_UTF8(z);
}
if( nChar>0 ){
azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
if( azChar==0 ){
return;
}
aLen = (unsigned char*)&azChar[nChar];
for(z=zCharSet, nChar=0; *z; nChar++){
azChar[nChar] = (unsigned char *)z;
SQLITE_SKIP_UTF8(z);
aLen[nChar] = (u8)(z - azChar[nChar]);
}
}
}
if( nChar>0 ){
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
if( flags & 1 ){
while( nIn>0 ){
int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
}
if( i>=nChar ) break;
zIn += len;
nIn -= len;
}
}
if( flags & 2 ){
while( nIn>0 ){
int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
}
if( i>=nChar ) break;
nIn -= len;
}
}
if( zCharSet ){
sqlite3_free((void*)azChar);
}
}
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
#ifdef SQLITE_SOUNDEX
static void soundexFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
char zResult[8];
const u8 *zIn;
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,
};
assert( argc==1 );
zIn = (u8*)sqlite3_value_text(argv[0]);
if( zIn==0 ) zIn = (u8*)"";
for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){}
if( zIn[i] ){
u8 prevcode = iCode[zIn[i]&0x7f];
zResult[0] = sqlite3Toupper(zIn[i]);
for(j=1; j<4 && zIn[i]; i++){
int code = iCode[zIn[i]&0x7f];
if( code>0 ){
if( code!=prevcode ){
prevcode = code;
zResult[j++] = code + '0';
}
}else{
prevcode = 0;
}
}
while( j<4 ){
zResult[j++] = '0';
}
zResult[j] = 0;
sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
}else{
sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
}
}
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *zFile = (const char *)sqlite3_value_text(argv[0]);
const char *zProc;
sqlite3 *db = sqlite3_context_db_handle(context);
char *zErrMsg = 0;
if( argc==2 ){
zProc = (const char *)sqlite3_value_text(argv[1]);
}else{
zProc = 0;
}
if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){
sqlite3_result_error(context, zErrMsg, -1);
sqlite3_free(zErrMsg);
}
}
#endif
typedef struct SumCtx SumCtx;
struct SumCtx {
double rSum;
i64 iSum;
i64 cnt;
u8 overflow;
u8 approx;
};
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
int type;
assert( argc==1 );
UNUSED_PARAMETER(argc);
p = sqlite3_aggregate_context(context, sizeof(*p));
type = sqlite3_value_numeric_type(argv[0]);
if( p && type!=SQLITE_NULL ){
p->cnt++;
if( type==SQLITE_INTEGER ){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
p->overflow = 1;
}
}else{
p->rSum += sqlite3_value_double(argv[0]);
p->approx = 1;
}
}
}
static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
if( p->overflow ){
sqlite3_result_error(context,"integer overflow",-1);
}else if( p->approx ){
sqlite3_result_double(context, p->rSum);
}else{
sqlite3_result_int64(context, p->iSum);
}
}
}
static void avgFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
sqlite3_result_double(context, p->rSum/(double)p->cnt);
}
}
static void totalFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_double(context, p ? p->rSum : (double)0);
}
typedef struct CountCtx CountCtx;
struct CountCtx {
i64 n;
};
static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){
p->n++;
}
#ifndef SQLITE_OMIT_DEPRECATED
assert( argc==1 || p==0 || p->n>0x7fffffff
|| p->n==sqlite3_aggregate_count(context) );
#endif
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_int64(context, p ? p->n : 0);
}
static void minmaxStep(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
Mem *pArg = (Mem *)argv[0];
Mem *pBest;
UNUSED_PARAMETER(NotUsed);
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
if( !pBest ) return;
if( pBest->flags ){
int max;
int cmp;
CollSeq *pColl = sqlite3GetFuncCollSeq(context);
max = sqlite3_user_data(context)!=0;
cmp = sqlite3MemCompare(pBest, pArg, pColl);
if( (max && cmp<0) || (!max && cmp>0) ){
sqlite3VdbeMemCopy(pBest, pArg);
}
}else{
sqlite3VdbeMemCopy(pBest, pArg);
}
}
static void minMaxFinalize(sqlite3_context *context){
sqlite3_value *pRes;
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
if( pRes ){
if( ALWAYS(pRes->flags) ){
sqlite3_result_value(context, pRes);
}
sqlite3VdbeMemRelease(pRes);
}
}
static void groupConcatStep(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zVal;
StrAccum *pAccum;
const char *zSep;
int nVal, nSep;
assert( argc==1 || argc==2 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
int firstTerm = pAccum->useMalloc==0;
pAccum->useMalloc = 2;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
zSep = (char*)sqlite3_value_text(argv[1]);
nSep = sqlite3_value_bytes(argv[1]);
}else{
zSep = ",";
nSep = 1;
}
sqlite3StrAccumAppend(pAccum, zSep, nSep);
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
sqlite3StrAccumAppend(pAccum, zVal, nVal);
}
}
static void groupConcatFinalize(sqlite3_context *context){
StrAccum *pAccum;
pAccum = sqlite3_aggregate_context(context, 0);
if( pAccum ){
if( pAccum->tooBig ){
sqlite3_result_error_toobig(context);
}else if( pAccum->mallocFailed ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
sqlite3_free);
}
}
}
void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
}
static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
FuncDef *pDef;
pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
2, SQLITE_UTF8, 0);
if( ALWAYS(pDef) ){
pDef->flags = flagVal;
}
}
void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
struct compareInfo *pInfo;
if( caseSensitive ){
pInfo = (struct compareInfo*)&likeInfoAlt;
}else{
pInfo = (struct compareInfo*)&likeInfoNorm;
}
sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
(struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "like",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
}
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
if( pExpr->op!=TK_FUNCTION
|| !pExpr->x.pList
|| pExpr->x.pList->nExpr!=2
){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
memcpy(aWc, pDef->pUserData, 3);
assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
*pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
return 1;
}
void sqlite3RegisterGlobalFunctions(void){
static SQLITE_WSD FuncDef aBuiltinFunc[] = {
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
FUNCTION(rtrim, 2, 2, 0, trimFunc ),
FUNCTION(trim, 1, 3, 0, trimFunc ),
FUNCTION(trim, 2, 3, 0, trimFunc ),
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
FUNCTION(typeof, 1, 0, 0, typeofFunc ),
FUNCTION(length, 1, 0, 0, lengthFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ),
#ifndef SQLITE_OMIT_FLOATING_POINT
FUNCTION(round, 1, 0, 0, roundFunc ),
FUNCTION(round, 2, 0, 0, roundFunc ),
#endif
FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
{-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0},
FUNCTION(hex, 1, 0, 0, hexFunc ),
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0},
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
FUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
FUNCTION(load_extension, 1, 0, 0, loadExt ),
FUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
{0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#else
LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
#endif
};
int i;
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
for(i=0; i<ArraySize(aBuiltinFunc); i++){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
sqlite3RegisterDateTimeFunctions();
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
#endif
}