summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/func.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/func.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/func.c179
1 files changed, 123 insertions, 56 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/func.c b/ext/pdo_sqlite/sqlite/src/func.c
index cdb674fa28..bf422f92c5 100644
--- a/ext/pdo_sqlite/sqlite/src/func.c
+++ b/ext/pdo_sqlite/sqlite/src/func.c
@@ -20,7 +20,6 @@
*/
#include "sqliteInt.h"
#include <ctype.h>
-#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
@@ -101,7 +100,7 @@ static void lengthFunc(
break;
}
case SQLITE_TEXT: {
- const char *z = sqlite3_value_text(argv[0]);
+ const unsigned char *z = sqlite3_value_text(argv[0]);
for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
sqlite3_result_int(context, len);
break;
@@ -121,7 +120,13 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER: {
i64 iVal = sqlite3_value_int64(argv[0]);
- if( iVal<0 ) iVal = iVal * -1;
+ if( iVal<0 ){
+ if( (iVal<<1)==0 ){
+ sqlite3_result_error(context, "integer overflow", -1);
+ return;
+ }
+ iVal = -iVal;
+ }
sqlite3_result_int64(context, iVal);
break;
}
@@ -131,7 +136,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
default: {
double rVal = sqlite3_value_double(argv[0]);
- if( rVal<0 ) rVal = rVal * -1.0;
+ if( rVal<0 ) rVal = -rVal;
sqlite3_result_double(context, rVal);
break;
}
@@ -146,8 +151,8 @@ static void substrFunc(
int argc,
sqlite3_value **argv
){
- const char *z;
- const char *z2;
+ const unsigned char *z;
+ const unsigned char *z2;
int i;
int p1, p2, len;
@@ -178,7 +183,7 @@ static void substrFunc(
}
while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
if( p2<0 ) p2 = 0;
- sqlite3_result_text(context, &z[p1], p2, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, (char*)&z[p1], p2, SQLITE_TRANSIENT);
}
/*
@@ -195,10 +200,11 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
- if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ sqlite3AtoF(zBuf, &r);
+ sqlite3_result_double(context, r);
}
/*
@@ -210,11 +216,11 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1);
if( z==0 ) return;
- strcpy(z, sqlite3_value_text(argv[0]));
+ strcpy((char*)z, (char*)sqlite3_value_text(argv[0]));
for(i=0; z[i]; i++){
z[i] = toupper(z[i]);
}
- sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
sqliteFree(z);
}
static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
@@ -223,11 +229,11 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1);
if( z==0 ) return;
- strcpy(z, sqlite3_value_text(argv[0]));
+ strcpy((char*)z, (char*)sqlite3_value_text(argv[0]));
for(i=0; z[i]; i++){
z[i] = tolower(z[i]);
}
- sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
sqliteFree(z);
}
@@ -258,9 +264,11 @@ static void randomFunc(
int argc,
sqlite3_value **argv
){
- int r;
+ sqlite_int64 r;
sqlite3Randomness(sizeof(r), &r);
- sqlite3_result_int(context, r);
+ if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */
+ /* can always do abs() of the result */
+ sqlite3_result_int64(context, r);
}
/*
@@ -495,7 +503,7 @@ static void likeFunc(
** Otherwise, return an error.
*/
const unsigned char *zEsc = sqlite3_value_text(argv[2]);
- if( sqlite3utf8CharLen(zEsc, -1)!=1 ){
+ if( sqlite3utf8CharLen((char*)zEsc, -1)!=1 ){
sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
@@ -539,6 +547,19 @@ static void versionFunc(
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
+/*
+** The MATCH() function is unimplemented. If anybody tries to use it,
+** return an error.
+*/
+static void matchStub(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ static const char zErr[] = "MATCH is not implemented";
+ sqlite3_result_error(context, zErr, sizeof(zErr)-1);
+}
+
/*
** EXPERIMENTAL - This is not an official function. The interface may
@@ -592,7 +613,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
case SQLITE_TEXT: {
int i,j,n;
- const char *zArg = sqlite3_value_text(argv[0]);
+ const unsigned char *zArg = sqlite3_value_text(argv[0]);
char *z;
for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
@@ -633,6 +654,7 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv
};
assert( argc==1 );
zIn = (u8*)sqlite3_value_text(argv[0]);
+ if( zIn==0 ) zIn = "";
for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
if( zIn[i] ){
zResult[0] = toupper(zIn[i]);
@@ -653,6 +675,26 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv
}
#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** A function that loads a shared-library extension then returns NULL.
+*/
+static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
+ const char *zFile = (const char *)sqlite3_value_text(argv[0]);
+ const char *zProc = 0;
+ sqlite3 *db = sqlite3_user_data(context);
+ char *zErrMsg = 0;
+
+ if( argc==2 ){
+ zProc = (const char *)sqlite3_value_text(argv[1]);
+ }
+ if( sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){
+ sqlite3_result_error(context, zErrMsg, -1);
+ sqlite3_free(zErrMsg);
+ }
+}
+#endif
+
#ifdef SQLITE_TEST
/*
** This function generates a string of random characters. Used for
@@ -692,7 +734,7 @@ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
}
zBuf[n] = 0;
- sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
}
#endif /* SQLITE_TEST */
@@ -728,17 +770,17 @@ static void test_destructor(
test_destructor_count_var++;
assert( nArg==1 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- len = sqlite3ValueBytes(argv[0], db->enc);
+ len = sqlite3ValueBytes(argv[0], ENC(db));
zVal = sqliteMalloc(len+3);
zVal[len] = 0;
zVal[len-1] = 0;
assert( zVal );
zVal++;
- memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len);
- if( db->enc==SQLITE_UTF8 ){
+ memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
+ if( ENC(db)==SQLITE_UTF8 ){
sqlite3_result_text(pCtx, zVal, -1, destructor);
#ifndef SQLITE_OMIT_UTF16
- }else if( db->enc==SQLITE_UTF16LE ){
+ }else if( ENC(db)==SQLITE_UTF16LE ){
sqlite3_result_text16le(pCtx, zVal, -1, destructor);
}else{
sqlite3_result_text16be(pCtx, zVal, -1, destructor);
@@ -776,7 +818,7 @@ static void test_auxdata(
char *zRet = sqliteMalloc(nArg*2);
if( !zRet ) return;
for(i=0; i<nArg; i++){
- char const *z = sqlite3_value_text(argv[i]);
+ char const *z = (char*)sqlite3_value_text(argv[i]);
if( z ){
char *zAux = sqlite3_get_auxdata(pCtx, i);
if( zAux ){
@@ -807,7 +849,7 @@ static void test_error(
int nArg,
sqlite3_value **argv
){
- sqlite3_result_error(pCtx, sqlite3_value_text(argv[0]), 0);
+ sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), 0);
}
#endif /* SQLITE_TEST */
@@ -817,25 +859,45 @@ static void test_error(
*/
typedef struct SumCtx SumCtx;
struct SumCtx {
- double sum; /* Sum of terms */
- int cnt; /* Number of elements summed */
- u8 seenFloat; /* True if there has been any floating point value */
+ double rSum; /* Floating point sum */
+ i64 iSum; /* Integer sum */
+ i64 cnt; /* Number of elements summed */
+ u8 overflow; /* True if integer overflow seen */
+ u8 approx; /* True if non-integer value was input to the sum */
};
/*
-** Routines used to compute the sum or average.
+** Routines used to compute the sum, average, and total.
+**
+** The SUM() function follows the (broken) SQL standard which means
+** that it returns NULL if it sums over no inputs. TOTAL returns
+** 0.0 in that case. In addition, TOTAL always returns a float where
+** SUM might return an integer if it never encounters a floating point
+** value. TOTAL never fails, but SUM might through an exception if
+** it overflows an integer.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
int type;
assert( argc==1 );
p = sqlite3_aggregate_context(context, sizeof(*p));
- type = sqlite3_value_type(argv[0]);
+ type = sqlite3_value_numeric_type(argv[0]);
if( p && type!=SQLITE_NULL ){
- p->sum += sqlite3_value_double(argv[0]);
p->cnt++;
- if( type==SQLITE_FLOAT ){
- p->seenFloat = 1;
+ if( type==SQLITE_INTEGER ){
+ i64 v = sqlite3_value_int64(argv[0]);
+ p->rSum += v;
+ if( (p->approx|p->overflow)==0 ){
+ i64 iNewSum = p->iSum + v;
+ int s1 = p->iSum >> (sizeof(i64)*8-1);
+ int s2 = v >> (sizeof(i64)*8-1);
+ int s3 = iNewSum >> (sizeof(i64)*8-1);
+ p->overflow = (s1&s2&~s3) | (~s1&~s2&s3);
+ p->iSum = iNewSum;
+ }
+ }else{
+ p->rSum += sqlite3_value_double(argv[0]);
+ p->approx = 1;
}
}
}
@@ -843,10 +905,12 @@ static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
- if( p->seenFloat ){
- sqlite3_result_double(context, p->sum);
+ 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, (i64)p->sum);
+ sqlite3_result_int64(context, p->iSum);
}
}
}
@@ -854,20 +918,14 @@ static void avgFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
- sqlite3_result_double(context, p->sum/(double)p->cnt);
+ sqlite3_result_double(context, p->rSum/(double)p->cnt);
}
}
-
-/*
-** An instance of the following structure holds the context of a
-** variance or standard deviation computation.
-*/
-typedef struct StdDevCtx StdDevCtx;
-struct StdDevCtx {
- double sum; /* Sum of terms */
- double sum2; /* Sum of the squares of terms */
- int cnt; /* Number of terms counted */
-};
+static void totalFinalize(sqlite3_context *context){
+ SumCtx *p;
+ p = sqlite3_aggregate_context(context, 0);
+ sqlite3_result_double(context, p ? p->rSum : 0.0);
+}
/*
** The following structure keeps track of state information for the
@@ -875,7 +933,7 @@ struct StdDevCtx {
*/
typedef struct CountCtx CountCtx;
struct CountCtx {
- int n;
+ i64 n;
};
/*
@@ -891,7 +949,7 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
static void countFinalize(sqlite3_context *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, 0);
- sqlite3_result_int(context, p ? p->n : 0);
+ sqlite3_result_int64(context, p ? p->n : 0);
}
/*
@@ -978,9 +1036,14 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
+ { "match", 2, 0, SQLITE_UTF8, 0, matchStub },
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt },
+ { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt },
+#endif
#ifdef SQLITE_TEST
{ "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
{ "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor},
@@ -1000,6 +1063,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
{ "sum", 1, 0, 0, sumStep, sumFinalize },
+ { "total", 1, 0, 0, sumStep, totalFinalize },
{ "avg", 1, 0, 0, sumStep, avgFinalize },
{ "count", 0, 0, 0, countStep, countFinalize },
{ "count", 1, 0, 0, countStep, countFinalize },
@@ -1012,7 +1076,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
case 1: pArg = db; break;
case 2: pArg = (void *)(-1); break;
}
- sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
+ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
if( aFuncs[i].needCollSeq ){
FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
@@ -1025,13 +1089,16 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
+#ifndef SQLITE_OMIT_PARSER
+ sqlite3AttachFunctions(db);
+#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,
+ sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
if( aAggs[i].needCollSeq ){
FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
@@ -1043,7 +1110,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
sqlite3RegisterDateTimeFunctions(db);
#ifdef SQLITE_SSE
- sqlite3SseFunctions(db);
+ (void)sqlite3SseFunctions(db);
#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
sqlite3RegisterLikeFunctions(db, 1);
@@ -1075,9 +1142,9 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
}else{
pInfo = (struct compareInfo*)&likeInfoNorm;
}
- sqlite3_create_function(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
- sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
- sqlite3_create_function(db, "glob", 2, SQLITE_UTF8,
+ sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
+ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
+ sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
(struct compareInfo*)&globInfo, likeFunc, 0,0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "like",
@@ -1099,7 +1166,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
if( pExpr->pList->nExpr!=2 ){
return 0;
}
- pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2,
+ pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
SQLITE_UTF8, 0);
if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
return 0;