mirror of
https://github.com/sqlite/sqlite.git
synced 2025-12-24 14:17:58 +03:00
Completely remove the old SQL function system and replace it with the
new user functions. The code currently compiles but it coredumps on the test suite. Do not use in its present state. (CVS 400) FossilOrigin-Name: 50797fee5066ec9ea23b720e5ab7e8fc8ccc1988
This commit is contained in:
259
src/func.c
259
src/func.c
@@ -16,12 +16,130 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.5 2002/02/27 19:50:59 drh Exp $
|
||||
** $Id: func.c,v 1.6 2002/02/28 00:41:10 drh Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "sqlite.h"
|
||||
#include <assert.h>
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Implementation of the non-aggregate min() and max() functions
|
||||
*/
|
||||
static void minFunc(sqlite_func *context, int argc, const char **argv){
|
||||
const char *zBest;
|
||||
int i;
|
||||
|
||||
zBest = argv[0];
|
||||
for(i=1; i<argc; i++){
|
||||
if( sqliteCompare(argv[i], zBest)<0 ){
|
||||
zBest = argv[i];
|
||||
}
|
||||
}
|
||||
sqlite_set_result_string(context, zBest, -1);
|
||||
}
|
||||
static void maxFunc(sqlite_func *context, int argc, const char **argv){
|
||||
const char *zBest;
|
||||
int i;
|
||||
|
||||
zBest = argv[0];
|
||||
for(i=1; i<argc; i++){
|
||||
if( sqliteCompare(argv[i], zBest)>0 ){
|
||||
zBest = argv[i];
|
||||
}
|
||||
}
|
||||
sqlite_set_result_string(context, zBest, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the length() function
|
||||
*/
|
||||
static void lengthFunc(sqlite_func *context, int argc, const char **argv){
|
||||
const char *z;
|
||||
int len;
|
||||
|
||||
assert( argc==1 );
|
||||
z = argv[0];
|
||||
if( z==0 ){
|
||||
len = 0;
|
||||
}else{
|
||||
#ifdef SQLITE_UTF8
|
||||
for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
|
||||
#else
|
||||
len = strlen(z);
|
||||
#endif
|
||||
}
|
||||
sqlite_set_result_int(context, len);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the abs() function
|
||||
*/
|
||||
static void absFunc(sqlite_func *context, int argc, const char **argv){
|
||||
const char *z;
|
||||
assert( argc==1 );
|
||||
z = argv[0];
|
||||
if( z && z[0]=='-' && isdigit(z[1]) ) z++;
|
||||
sqlite_set_result_string(context, z, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the substr() function
|
||||
*/
|
||||
static void substrFunc(sqlite_func *context, int argc, const char **argv){
|
||||
const char *z;
|
||||
#ifdef SQLITE_UTF8
|
||||
const char *z2;
|
||||
int i;
|
||||
#endif
|
||||
int p1, p2, len;
|
||||
assert( argc==3 );
|
||||
z = argv[0];
|
||||
if( z==0 ) return;
|
||||
p1 = atoi(argv[1]?argv[1]:0);
|
||||
p2 = atoi(argv[2]?argv[2]:0);
|
||||
#ifdef SQLITE_UTF8
|
||||
for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z)!=0x80 ) len++; }
|
||||
#else
|
||||
len = strlen(z);
|
||||
#endif
|
||||
if( p1<0 ){
|
||||
p1 = len-p1;
|
||||
}else if( p1>0 ){
|
||||
p1--;
|
||||
}
|
||||
if( p1+p2>len ){
|
||||
p2 = len-p1;
|
||||
}
|
||||
#ifdef SQLITE_UTF8
|
||||
for(i=0; i<p1; i++){
|
||||
assert( z[i] );
|
||||
if( (z[i]&0xc0)!=0x80 ) p1++;
|
||||
}
|
||||
for(; i<p1+p2; i++){
|
||||
assert( z[i] );
|
||||
if( (z[i]&0xc0)!=0x80 ) p2++;
|
||||
}
|
||||
#endif
|
||||
sqlite_set_result_string(context, &z[p1], p2);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the round() function
|
||||
*/
|
||||
static void roundFunc(sqlite_func *context, int argc, const char **argv){
|
||||
int n;
|
||||
double r;
|
||||
char zBuf[100];
|
||||
assert( argc==1 || argc==2 );
|
||||
n = argc==2 && argv[1] ? atoi(argv[1]) : 0;
|
||||
if( n>30 ) n = 30;
|
||||
if( n<0 ) n = 0;
|
||||
r = argv[0] ? atof(argv[0]) : 0.0;
|
||||
sprintf(zBuf,"%.*f",n,r);
|
||||
sqlite_set_result_string(context, zBuf, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the upper() and lower() SQL functions.
|
||||
@@ -117,7 +235,100 @@ static void stdDevFinalize(sqlite_func *context){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The following structure keeps track of state information for the
|
||||
** count() aggregate function.
|
||||
*/
|
||||
typedef struct CountCtx CountCtx;
|
||||
struct CountCtx {
|
||||
int n;
|
||||
};
|
||||
|
||||
/*
|
||||
** Routines to implement the count() aggregate function.
|
||||
*/
|
||||
static void countStep(sqlite_func *context, int argc, const char **argv){
|
||||
CountCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( (argc==0 || argv[0]) && p ){
|
||||
p->n++;
|
||||
}
|
||||
}
|
||||
static void countFinalize(sqlite_func *context){
|
||||
CountCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p ){
|
||||
sqlite_set_result_int(context, p->n);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This function tracks state information for the min() and max()
|
||||
** aggregate functions.
|
||||
*/
|
||||
typedef struct MinMaxCtx MinMaxCtx;
|
||||
struct MinMaxCtx {
|
||||
char *z; /* The best so far */
|
||||
char zBuf[28]; /* Space that can be used for storage */
|
||||
};
|
||||
|
||||
/*
|
||||
** Routines to implement min() and max() aggregate functions.
|
||||
*/
|
||||
static void minStep(sqlite_func *context, int argc, const char **argv){
|
||||
MinMaxCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p==0 || argc<1 ) return;
|
||||
if( sqlite_aggregate_count(context)==1 || sqliteCompare(argv[0],p->z)<0 ){
|
||||
if( p->z && p->z!=p->zBuf ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
if( argv[0] ){
|
||||
int len = strlen(argv[0]);
|
||||
if( len < sizeof(p->zBuf) ){
|
||||
p->z = p->zBuf;
|
||||
}else{
|
||||
p->z = sqliteMalloc( len+1 );
|
||||
if( p->z==0 ) return;
|
||||
}
|
||||
strcpy(p->z, argv[0]);
|
||||
}else{
|
||||
p->z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void maxStep(sqlite_func *context, int argc, const char **argv){
|
||||
MinMaxCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p==0 || argc<1 ) return;
|
||||
if( sqlite_aggregate_count(context)==1 || sqliteCompare(argv[0],p->z)>0 ){
|
||||
if( p->z && p->z!=p->zBuf ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
if( argv[0] ){
|
||||
int len = strlen(argv[0]);
|
||||
if( len < sizeof(p->zBuf) ){
|
||||
p->z = p->zBuf;
|
||||
}else{
|
||||
p->z = sqliteMalloc( len+1 );
|
||||
if( p->z==0 ) return;
|
||||
}
|
||||
strcpy(p->z, argv[0]);
|
||||
}else{
|
||||
p->z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void minMaxFinalize(sqlite_func *context){
|
||||
MinMaxCtx *p;
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p && p->z ){
|
||||
sqlite_set_result_string(context, p->z, strlen(p->z));
|
||||
}
|
||||
if( p && p->z && p->z!=p->zBuf ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This function registered all of the above C functions as SQL
|
||||
@@ -125,9 +336,43 @@ static void stdDevFinalize(sqlite_func *context){
|
||||
** external linkage.
|
||||
*/
|
||||
void sqliteRegisterBuildinFunctions(sqlite *db){
|
||||
sqlite_create_function(db, "upper", 1, upperFunc, 0);
|
||||
sqlite_create_function(db, "lower", 1, lowerFunc, 0);
|
||||
sqlite_create_aggregate(db, "stddev", 1, stdDevStep, stdDevFinalize, 0);
|
||||
sqlite_create_aggregate(db, "x_sum", 1, sumStep, sumFinalize, 0);
|
||||
sqlite_create_aggregate(db, "x_avg", 1, sumStep, avgFinalize, 0);
|
||||
static struct {
|
||||
char *zName;
|
||||
int nArg;
|
||||
void (*xFunc)(sqlite_func*,int,const char**);
|
||||
} aFuncs[] = {
|
||||
{ "min", -1, minFunc },
|
||||
{ "max", -1, maxFunc },
|
||||
{ "length", 1, lengthFunc },
|
||||
{ "substr", 3, substrFunc },
|
||||
{ "abs", 1, absFunc },
|
||||
{ "round", 1, roundFunc },
|
||||
{ "round", 2, roundFunc },
|
||||
{ "upper", 1, upperFunc },
|
||||
{ "lower", 1, lowerFunc },
|
||||
};
|
||||
static struct {
|
||||
char *zName;
|
||||
int nArg;
|
||||
void (*xStep)(sqlite_func*,int,const char**);
|
||||
void (*xFinalize)(sqlite_func*);
|
||||
} aAggs[] = {
|
||||
{ "min", 1, minStep, minMaxFinalize },
|
||||
{ "max", 1, maxStep, minMaxFinalize },
|
||||
{ "sum", 1, sumStep, sumFinalize },
|
||||
{ "avg", 1, sumStep, avgFinalize },
|
||||
{ "count", 0, countStep, countFinalize },
|
||||
{ "count", 1, countStep, countFinalize },
|
||||
{ "stddev", 1, stdDevStep, stdDevFinalize },
|
||||
};
|
||||
int i;
|
||||
|
||||
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
|
||||
sqlite_create_function(db, aFuncs[i].zName,
|
||||
aFuncs[i].nArg, aFuncs[i].xFunc, 0);
|
||||
}
|
||||
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
|
||||
sqlite_create_aggregate(db, aAggs[i].zName,
|
||||
aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user