📄 func.c
字号:
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)); sqlite_set_result_int(context, p ? p->n : 0);}/*** 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 || argv[0]==0 ) return; if( p->z==0 || sqliteCompare(argv[0],p->z)<0 ){ int len; if( p->z && p->z!=p->zBuf ){ sqliteFree(p->z); } 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]); }}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 || argv[0]==0 ) return; if( p->z==0 || sqliteCompare(argv[0],p->z)>0 ){ int len; if( p->z && p->z!=p->zBuf ){ sqliteFree(p->z); } 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]); }}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); }}/****************************************************************************** Time and date functions.**** SQLite processes all times and dates as Julian Day numbers. The** dates and times are stored as the number of days since noon** in Greenwich on November 24, 4714 B.C. according to the Gregorian** calendar system.**** This implement requires years to be expressed as a 4-digit number** which means that only dates between 0000-01-01 and 9999-12-31 can** be represented, even though julian day numbers allow a much wider** range of dates.**** The Gregorian calendar system is used for all dates and times,** even those that predate the Gregorian calendar. Historians usually** use the Julian calendar for dates prior to 1582-10-15 and for some** dates afterwards, depending on locale. Beware of this difference.**** The conversion algorithms are implemented based on descriptions** in the following text:**** Jean Meeus** Astronomical Algorithms, 2nd Edition, 1998** ISBM 0-943396-61-1** Willmann-Bell, Inc** Richmond, Virginia (USA)*/#ifndef SQLITE_OMIT_DATETIME_FUNCS/*** Convert N digits from zDate into an integer. Return** -1 if zDate does not begin with N digits.*/static int getDigits(const char *zDate, int N){ int val = 0; while( N-- ){ if( !isdigit(*zDate) ) return -1; val = val*10 + *zDate - '0'; zDate++; } return val;}/*** Parse times of the form HH:MM:SS or HH:MM. Store the** result (in days) in *prJD.**** Return 1 if there is a parsing error and 0 on success.*/static int parseHhMmSs(const char *zDate, double *prJD){ int h, m, s; h = getDigits(zDate, 2); if( h<0 || zDate[2]!=':' ) return 1; zDate += 3; m = getDigits(zDate, 2); if( m<0 || m>59 ) return 1; zDate += 2; if( *zDate==':' ){ s = getDigits(&zDate[1], 2); if( s<0 || s>59 ) return 1; zDate += 3; }else{ s = 0; } while( isspace(*zDate) ){ zDate++; } *prJD = (h*3600.0 + m*60.0 + s)/86400.0; return 0;}/*** Parse dates of the form**** YYYY-MM-DD HH:MM:SS** YYYY-MM-DD HH:MM** YYYY-MM-DD**** Write the result as a julian day number in *prJD. Return 0** on success and 1 if the input string is not a well-formed** date.*/static int parseYyyyMmDd(const char *zDate, double *prJD){ int Y, M, D; double rTime; int A, B, X1, X2; Y = getDigits(zDate, 4); if( Y<0 || zDate[4]!='-' ) return 1; zDate += 5; M = getDigits(zDate, 2); if( M<=0 || M>12 || zDate[2]!='-' ) return 1; zDate += 3; D = getDigits(zDate, 2); if( D<=0 || D>31 ) return 1; zDate += 2; while( isspace(*zDate) ){ zDate++; } if( isdigit(*zDate) ){ if( parseHhMmSs(zDate, &rTime) ) return 1; }else if( *zDate==0 ){ rTime = 0.0; }else{ return 1; } /* The year, month, and day are now stored in Y, M, and D. Convert ** these into the Julian Day number. See Meeus page 61. */ if( M<=2 ){ Y--; M += 12; } A = Y/100; B = 2 - A + (A/4); X1 = 365.25*(Y+4716); X2 = 30.6001*(M+1); *prJD = X1 + X2 + D + B - 1524.5 + rTime; return 0;}/*** Attempt to parse the given string into a Julian Day Number. Return** the number of errors.**** The following are acceptable forms for the input string:**** YYYY-MM-DD** YYYY-MM-DD HH:MM** YYYY-MM-DD HH:MM:SS** HH:MM** HH:MM:SS** DDDD.DD ** now*/static int parseDateOrTime(const char *zDate, double *prJD){ int i; for(i=0; isdigit(zDate[i]); i++){} if( i==4 && zDate[i]=='-' ){ return parseYyyyMmDd(zDate, prJD); }else if( i==2 && zDate[i]==':' ){ return parseHhMmSs(zDate, prJD); }else if( i==0 && sqliteStrICmp(zDate,"now")==0 ){ return sqliteOsCurrentTime(prJD); }else if( sqliteIsNumber(zDate) ){ *prJD = atof(zDate); return 0; } return 1;}/*** A structure for holding date and time.*/typedef struct DateTime DateTime;struct DateTime { double rJD; /* The julian day number */ int Y, M, D; /* Year, month, and day */ int h, m, s; /* Hour minute and second */};/*** Break up a julian day number into year, month, day, hour, minute, second.** This function assume the Gregorian calendar - even for dates prior** to the invention of the Gregorian calendar in 1582.**** See Meeus page 63.**** If mode==1 only the year, month, and day are computed. If mode==2** then only the hour, minute, and second are computed. If mode==3 then** everything is computed. If mode==0, this routine is a no-op.*/static void decomposeDate(DateTime *p, int mode){ int Z; Z = p->rJD + 0.5; if( mode & 1 ){ int A, B, C, D, E, X1; A = (Z - 1867216.25)/36524.25; A = Z + 1 + A - (A/4); B = A + 1524; C = (B - 122.1)/365.25; D = 365.25*C; E = (B-D)/30.6001; X1 = 30.6001*E; p->D = B - D - X1; p->M = E<14 ? E-1 : E-13; p->Y = p->M>2 ? C - 4716 : C - 4715; } if( mode & 2 ){ p->s = (p->rJD + 0.5 - Z)*86400.0; p->h = p->s/3600; p->s -= p->h*3600; p->m = p->s/60; p->s -= p->m*60; }}/*** Check to see that all arguments are valid date strings. If any ** argument is not a valid date string, return 0. If all arguments** are valid, return 1 and write into *p->rJD the sum of the julian day** numbers for all date strings.**** A "valid" date string is one that is accepted by parseDateOrTime().**** The mode argument is passed through to decomposeDate() in order to** fill in the year, month, day, hour, minute, and second of the *p** structure, if desired.*/static int isDate(int argc, const char **argv, DateTime *p, int mode){ double r; int i; p->rJD = 0.0; for(i=0; i<argc; i++){ if( argv[i]==0 ) return 0; if( parseDateOrTime(argv[i], &r) ) return 0; p->rJD += r; } decomposeDate(p, mode); return 1;}/*** The following routines implement the various date and time functions** of SQLite.*/static void juliandayFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 0) ){ sqlite_set_result_double(context, x.rJD); }}static void timestampFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 3) ){ char zBuf[100]; sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m, x.s); sqlite_set_result_string(context, zBuf, -1); }}static void timeFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 2) ){ char zBuf[100]; sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, x.s); sqlite_set_result_string(context, zBuf, -1); }}static void dateFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 1) ){ char zBuf[100]; sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); sqlite_set_result_string(context, zBuf, -1); }}static void yearFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 1) ){ sqlite_set_result_int(context, x.Y); }}static void monthFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 1) ){ sqlite_set_result_int(context, x.M); }}static void dayofweekFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 0) ){ int Z = x.rJD + 1.5; sqlite_set_result_int(context, Z % 7); }}static void dayofmonthFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 1) ){ sqlite_set_result_int(context, x.D); }}static void secondFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 2) ){ sqlite_set_result_int(context, x.s); }}static void minuteFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 2) ){ sqlite_set_result_int(context, x.m); }}static void hourFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x, 2) ){ sqlite_set_result_int(context, x.h); }}#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) *//***************************************************************************//*** This function registered all of the above C functions as SQL** functions. This should be the only routine in this file with** external linkage.*/void sqliteRegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; int nArg; int dataType; void (*xFunc)(sqlite_func*,int,const char**); } aFuncs[] = { { "min", -1, SQLITE_ARGS, minFunc }, { "min", 0, 0, 0 }, { "max", -1, SQLITE_ARGS, maxFunc }, { "max", 0, 0, 0 }, { "length", 1, SQLITE_NUMERIC, lengthFunc }, { "substr", 3, SQLITE_TEXT, substrFunc }, { "abs", 1, SQLITE_NUMERIC, absFunc }, { "round", 1, SQLITE_NUMERIC, roundFunc }, { "round", 2, SQLITE_NUMERIC, roundFunc }, { "upper", 1, SQLITE_TEXT, upperFunc }, { "lower", 1, SQLITE_TEXT, lowerFunc }, { "coalesce", -1, SQLITE_ARGS, ifnullFunc }, { "coalesce", 0, 0, 0 }, { "coalesce", 1, 0, 0 }, { "ifnull", 2, SQLITE_ARGS, ifnullFunc }, { "random", -1, SQLITE_NUMERIC, randomFunc }, { "like", 2, SQLITE_NUMERIC, likeFunc }, { "glob", 2, SQLITE_NUMERIC, globFunc }, { "nullif", 2, SQLITE_ARGS, nullifFunc }, { "sqlite_version",0,SQLITE_TEXT, versionFunc}, { "quote", 1, SQLITE_ARGS, quoteFunc },#ifndef SQLITE_OMIT_DATETIME_FUNCS { "julianday", -1, SQLITE_NUMERIC, juliandayFunc }, { "timestamp", -1, SQLITE_TEXT, timestampFunc }, { "time", -1, SQLITE_TEXT, timeFunc }, { "date", -1, SQLITE_TEXT, dateFunc }, { "year", -1, SQLITE_NUMERIC, yearFunc }, { "month", -1, SQLITE_NUMERIC, monthFunc }, { "dayofmonth",-1, SQLITE_NUMERIC, dayofmonthFunc }, { "dayofweek", -1, SQLITE_NUMERIC, dayofweekFunc }, { "hour", -1, SQLITE_NUMERIC, hourFunc }, { "minute", -1, SQLITE_NUMERIC, minuteFunc }, { "second", -1, SQLITE_NUMERIC, secondFunc },#endif#ifdef SQLITE_SOUNDEX { "soundex", 1, SQLITE_TEXT, soundexFunc},#endif#ifdef SQLITE_TEST { "randstr", 2, SQLITE_TEXT, randStr },#endif }; static struct { char *zName; int nArg; int dataType; void (*xStep)(sqlite_func*,int,const char**); void (*xFinalize)(sqlite_func*); } aAggs[] = { { "min", 1, 0, minStep, minMaxFinalize }, { "max", 1, 0, maxStep, minMaxFinalize }, { "sum", 1, SQLITE_NUMERIC, sumStep, sumFinalize }, { "avg", 1, SQLITE_NUMERIC, sumStep, avgFinalize }, { "count", 0, SQLITE_NUMERIC, countStep, countFinalize }, { "count", 1, SQLITE_NUMERIC, countStep, countFinalize },#if 0 { "stddev", 1, SQLITE_NUMERIC, stdDevStep, stdDevFinalize },#endif }; 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); if( aFuncs[i].xFunc ){ sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); } } sqlite_create_function(db, "last_insert_rowid", 0, last_insert_rowid, db); sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC); 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); sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -