/* This comparison routine is what we use for comparison operations ** between numeric values in an SQL expression. "Numeric" is a little ** bit misleading here. What we mean is that the strings have a ** type of "numeric" from the point of view of SQL. The strings ** do not necessarily contain numbers. They could contain text. ** ** If the input strings both look like actual numbers then they ** compare in numerical order. Numerical strings are always less ** than non-numeric strings so if one input string looks like a ** number and the other does not, then the one that looks like ** a number is the smaller. Non-numeric strings compare in ** lexigraphical order (the same order as strcmp()). */ int sqliteCompare(const char *atext, const char *btext){ int result; int isNumA, isNumB; if( atext==0 ){ return -1; }else if( btext==0 ){ return 1; } isNumA = sqliteIsNumber(atext); isNumB = sqliteIsNumber(btext); if( isNumA ){ if( !isNumB ){ result = -1; }else{ double rA, rB; rA = sqliteAtoF(atext, 0); rB = sqliteAtoF(btext, 0); if( rA<rB ){ result = -1; }else if( rA>rB ){ result = +1; }else{ result = 0; } } }else if( isNumB ){ result = +1; }else { result = strcmp(atext, btext); } return result; }
/* ** This routine is used for sorting. Each key is a list of one or more ** null-terminated elements. The list is terminated by two nulls in ** a row. For example, the following text is a key with three elements ** ** Aone\000Dtwo\000Athree\000\000 ** ** All elements begin with one of the characters "+-AD" and end with "\000" ** with zero or more text elements in between. Except, NULL elements ** consist of the special two-character sequence "N\000". ** ** Both arguments will have the same number of elements. This routine ** returns negative, zero, or positive if the first argument is less ** than, equal to, or greater than the first. (Result is a-b). ** ** Each element begins with one of the characters "+", "-", "A", "D". ** This character determines the sort order and collating sequence: ** ** + Sort numerically in ascending order ** - Sort numerically in descending order ** A Sort as strings in ascending order ** D Sort as strings in descending order. ** ** For the "+" and "-" sorting, pure numeric strings (strings for which the ** isNum() function above returns TRUE) always compare less than strings ** that are not pure numerics. Non-numeric strings compare in memcmp() ** order. This is the same sort order as the sqliteCompare() function ** above generates. ** ** The last point is a change from version 2.6.3 to version 2.7.0. In ** version 2.6.3 and earlier, substrings of digits compare in numerical ** and case was used only to break a tie. ** ** Elements that begin with 'A' or 'D' compare in memcmp() order regardless ** of whether or not they look like a number. ** ** Note that the sort order imposed by the rules above is the same ** from the ordering defined by the "<", "<=", ">", and ">=" operators ** of expressions and for indices. This was not the case for version ** 2.6.3 and earlier. */ int sqliteSortCompare(const char *a, const char *b){ int res = 0; int isNumA, isNumB; int dir = 0; while( res==0 && *a && *b ){ if( a[0]=='N' || b[0]=='N' ){ if( a[0]==b[0] ){ a += 2; b += 2; continue; } if( a[0]=='N' ){ dir = b[0]; res = -1; }else{ dir = a[0]; res = +1; } break; } assert( a[0]==b[0] ); if( (dir=a[0])=='A' || a[0]=='D' ){ res = strcmp(&a[1],&b[1]); if( res ) break; }else{ isNumA = sqliteIsNumber(&a[1]); isNumB = sqliteIsNumber(&b[1]); if( isNumA ){ double rA, rB; if( !isNumB ){ res = -1; break; } rA = sqliteAtoF(&a[1], 0); rB = sqliteAtoF(&b[1], 0); if( rA<rB ){ res = -1; break; } if( rA>rB ){ res = +1; break; } }else if( isNumB ){ res = +1; break; }else{ res = strcmp(&a[1],&b[1]); if( res ) break; } } a += strlen(&a[1]) + 2; b += strlen(&b[1]) + 2; } if( dir=='-' || dir=='D' ) res = -res; return res; }
/* ** Routines used to compute the sum or average. */ static void sumStep(sqlite_func *context, int argc, const char **argv){ SumCtx *p; if( argc<1 ) return; p = sqlite_aggregate_context(context, sizeof(*p)); if( p && argv[0] ){ p->sum += sqliteAtoF(argv[0], 0); p->cnt++; } }
/* ** Routines used to compute the standard deviation as an aggregate. */ static void stdDevStep(sqlite_func *context, int argc, const char **argv){ StdDevCtx *p; double x; if( argc<1 ) return; p = sqlite_aggregate_context(context, sizeof(*p)); if( p && argv[0] ){ x = sqliteAtoF(argv[0], 0); p->sum += x; p->sum2 += x*x; p->cnt++; } }
/* ** 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 ); if( argv[0]==0 || (argc==2 && argv[1]==0) ) return; n = argc==2 ? atoi(argv[1]) : 0; if( n>30 ) n = 30; if( n<0 ) n = 0; r = sqliteAtoF(argv[0], 0); sprintf(zBuf,"%.*f",n,r); sqlite_set_result_string(context, zBuf, -1); }
/* ** The following routine is a user-defined SQL function whose purpose ** is to test the sqlite_set_result() API. */ static void testFunc(sqlite_func *context, int argc, const char **argv){ while( argc>=2 ){ if( argv[0]==0 ){ sqlite_set_result_error(context, "first argument to test function " "may not be NULL", -1); }else if( sqliteStrICmp(argv[0],"string")==0 ){ sqlite_set_result_string(context, argv[1], -1); }else if( argv[1]==0 ){ sqlite_set_result_error(context, "2nd argument may not be NULL if the " "first argument is not \"string\"", -1); }else if( sqliteStrICmp(argv[0],"int")==0 ){ sqlite_set_result_int(context, atoi(argv[1])); }else if( sqliteStrICmp(argv[0],"double")==0 ){ sqlite_set_result_double(context, sqliteAtoF(argv[1], 0)); }else{ sqlite_set_result_error(context,"first argument should be one of: " "string int double", -1); } argc -= 2; argv += 2; } }
/* ** 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 HH:MM:SS.FFF +/-HH:MM ** DDDD.DD ** now ** ** In the first form, the +/-HH:MM is always optional. The fractional ** seconds extension (the ".FFF") is optional. The seconds portion ** (":SS.FFF") is option. The year and date can be omitted as long ** as there is a time string. The time string can be omitted as long ** as there is a year and date. */ static int parseDateOrTime(const char *zDate, DateTime *p){ int i; memset(p, 0, sizeof(*p)); for(i=0; isdigit(zDate[i]); i++){} if( i==4 && zDate[i]=='-' ){ return parseYyyyMmDd(zDate, p); }else if( i==2 && zDate[i]==':' ){ return parseHhMmSs(zDate, p); return 0; }else if( i==0 && sqliteStrICmp(zDate,"now")==0 ){ double r; if( sqliteOsCurrentTime(&r)==0 ){ p->rJD = r; p->validJD = 1; return 0; } return 1; }else if( sqliteIsNumber(zDate) ){ p->rJD = sqliteAtoF(zDate); p->validJD = 1; return 0; } return 1; }