| | @@ -262,10 +262,11 @@ |
| 262 | 262 | /* Deselect most features from the console I/O package for Fiddle. */ |
| 263 | 263 | # define SQLITE_CIO_NO_REDIRECT |
| 264 | 264 | # define SQLITE_CIO_NO_CLASSIFY |
| 265 | 265 | # define SQLITE_CIO_NO_TRANSLATE |
| 266 | 266 | # define SQLITE_CIO_NO_SETMODE |
| 267 | +# define SQLITE_CIO_NO_FLUSH |
| 267 | 268 | #endif |
| 268 | 269 | /************************* Begin ../ext/consio/console_io.h ******************/ |
| 269 | 270 | /* |
| 270 | 271 | ** 2023 November 1 |
| 271 | 272 | ** |
| | @@ -442,16 +443,23 @@ |
| 442 | 443 | #ifdef CONSIO_EPUTB |
| 443 | 444 | SQLITE_INTERNAL_LINKAGE int |
| 444 | 445 | ePutbUtf8(const char *cBuf, int nAccept); |
| 445 | 446 | #endif |
| 446 | 447 | |
| 448 | +/* |
| 449 | +** Flush the given output stream. Return non-zero for success, else 0. |
| 450 | +*/ |
| 451 | +#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE) |
| 452 | +SQLITE_INTERNAL_LINKAGE int |
| 453 | +fFlushBuffer(FILE *pfOut); |
| 454 | +#endif |
| 455 | + |
| 447 | 456 | /* |
| 448 | 457 | ** Collect input like fgets(...) with special provisions for input |
| 449 | | -** from the console on platforms that require same. Defers to the |
| 450 | | -** C library fgets() when input is not from the console. Newline |
| 451 | | -** translation may be done as set by set{Binary,Text}Mode(). As a |
| 452 | | -** convenience, pfIn==NULL is treated as stdin. |
| 458 | +** from the console on such platforms as require same. Newline |
| 459 | +** translation may be done as set by set{Binary,Text}Mode(). |
| 460 | +** As a convenience, pfIn==NULL is treated as stdin. |
| 453 | 461 | */ |
| 454 | 462 | SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn); |
| 455 | 463 | /* Like fGetsUtf8 except stream is always the designated input. */ |
| 456 | 464 | /* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */ |
| 457 | 465 | |
| | @@ -1144,10 +1152,90 @@ |
| 1144 | 1152 | # if CIO_WIN_WC_XLATE |
| 1145 | 1153 | } |
| 1146 | 1154 | # endif |
| 1147 | 1155 | } |
| 1148 | 1156 | |
| 1157 | +/* |
| 1158 | +** Flush the given output stream. Return non-zero for success, else 0. |
| 1159 | +*/ |
| 1160 | +#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE) |
| 1161 | +SQLITE_INTERNAL_LINKAGE int |
| 1162 | +fFlushBuffer(FILE *pfOut){ |
| 1163 | +# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE) |
| 1164 | + return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0; |
| 1165 | +# else |
| 1166 | + return fflush(pfOut); |
| 1167 | +# endif |
| 1168 | +} |
| 1169 | +#endif |
| 1170 | + |
| 1171 | +#if CIO_WIN_WC_XLATE \ |
| 1172 | + && !defined(SHELL_OMIT_FIO_DUPE) \ |
| 1173 | + && defined(SQLITE_USE_ONLY_WIN32) |
| 1174 | +static struct FileAltIds { |
| 1175 | + int fd; |
| 1176 | + HANDLE fh; |
| 1177 | +} altIdsOfFile(FILE *pf){ |
| 1178 | + struct FileAltIds rv = { _fileno(pf) }; |
| 1179 | + union { intptr_t osfh; HANDLE fh; } fid = { |
| 1180 | + (rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE |
| 1181 | + }; |
| 1182 | + rv.fh = fid.fh; |
| 1183 | + return rv; |
| 1184 | +} |
| 1185 | + |
| 1186 | +SQLITE_INTERNAL_LINKAGE size_t |
| 1187 | +cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){ |
| 1188 | + size_t rv = 0; |
| 1189 | + struct FileAltIds fai = altIdsOfFile(pf); |
| 1190 | + int fmode = _setmode(fai.fd, _O_BINARY); |
| 1191 | + _setmode(fai.fd, fmode); |
| 1192 | + while( rv < ocnt ){ |
| 1193 | + size_t nbo = osz; |
| 1194 | + while( nbo > 0 ){ |
| 1195 | + DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo; |
| 1196 | + BOOL wrc = TRUE; |
| 1197 | + BOOL genCR = (fmode & _O_TEXT)!=0; |
| 1198 | + if( genCR ){ |
| 1199 | + const char *pnl = (const char*)memchr(buf, '\n', nbo); |
| 1200 | + if( pnl ) nbo = pnl - (const char*)buf; |
| 1201 | + else genCR = 0; |
| 1202 | + } |
| 1203 | + if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0); |
| 1204 | + if( genCR && wrc ){ |
| 1205 | + wrc = WriteFile(fai.fh, "\r\n", 2, 0,0); |
| 1206 | + ++dwno; /* Skip over the LF */ |
| 1207 | + } |
| 1208 | + if( !wrc ) return rv; |
| 1209 | + buf = (const char*)buf + dwno; |
| 1210 | + nbo += dwno; |
| 1211 | + } |
| 1212 | + ++rv; |
| 1213 | + } |
| 1214 | + return rv; |
| 1215 | +} |
| 1216 | + |
| 1217 | +SQLITE_INTERNAL_LINKAGE char * |
| 1218 | +cfGets(char *cBuf, int n, FILE *pf){ |
| 1219 | + int nci = 0; |
| 1220 | + struct FileAltIds fai = altIdsOfFile(pf); |
| 1221 | + int fmode = _setmode(fai.fd, _O_BINARY); |
| 1222 | + BOOL eatCR = (fmode & _O_TEXT)!=0; |
| 1223 | + _setmode(fai.fd, fmode); |
| 1224 | + while( nci < n-1 ){ |
| 1225 | + DWORD nr; |
| 1226 | + if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break; |
| 1227 | + if( nr>0 && (!eatCR || cBuf[nci]!='\r') ) nci += nr; |
| 1228 | + } |
| 1229 | + if( nci < n ) cBuf[nci] = 0; |
| 1230 | + return (nci>0)? cBuf : 0; |
| 1231 | +} |
| 1232 | +# else |
| 1233 | +# define cfWrite(b,os,no,f) fwrite(b,os,no,f) |
| 1234 | +# define cfGets(b,n,f) fgets(b,n,f) |
| 1235 | +# endif |
| 1236 | + |
| 1149 | 1237 | # ifdef CONSIO_EPUTB |
| 1150 | 1238 | SQLITE_INTERNAL_LINKAGE int |
| 1151 | 1239 | ePutbUtf8(const char *cBuf, int nAccept){ |
| 1152 | 1240 | FILE *pfErr; |
| 1153 | 1241 | PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ |
| | @@ -1155,11 +1243,11 @@ |
| 1155 | 1243 | # if CIO_WIN_WC_XLATE |
| 1156 | 1244 | if( pstReachesConsole(ppst) ){ |
| 1157 | 1245 | return conZstrEmit(ppst, cBuf, nAccept); |
| 1158 | 1246 | }else { |
| 1159 | 1247 | # endif |
| 1160 | | - return (int)fwrite(cBuf, 1, nAccept, pfErr); |
| 1248 | + return (int)cfWrite(cBuf, 1, nAccept, pfErr); |
| 1161 | 1249 | # if CIO_WIN_WC_XLATE |
| 1162 | 1250 | } |
| 1163 | 1251 | # endif |
| 1164 | 1252 | } |
| 1165 | 1253 | # endif /* defined(CONSIO_EPUTB) */ |
| | @@ -1221,11 +1309,11 @@ |
| 1221 | 1309 | return cBuf; |
| 1222 | 1310 | }else return 0; |
| 1223 | 1311 | # endif |
| 1224 | 1312 | }else{ |
| 1225 | 1313 | # endif |
| 1226 | | - return fgets(cBuf, ncMax, pfIn); |
| 1314 | + return cfGets(cBuf, ncMax, pfIn); |
| 1227 | 1315 | # if CIO_WIN_WC_XLATE |
| 1228 | 1316 | } |
| 1229 | 1317 | # endif |
| 1230 | 1318 | } |
| 1231 | 1319 | #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ |
| | @@ -1265,15 +1353,16 @@ |
| 1265 | 1353 | # define oputz(z) oPutsUtf8(z) |
| 1266 | 1354 | # define oputf oPrintfUtf8 |
| 1267 | 1355 | # define eputz(z) ePutsUtf8(z) |
| 1268 | 1356 | # define eputf ePrintfUtf8 |
| 1269 | 1357 | # define oputb(buf,na) oPutbUtf8(buf,na) |
| 1358 | +# define fflush(s) fFlushBuffer(s); |
| 1270 | 1359 | |
| 1271 | 1360 | #else |
| 1272 | 1361 | /* For Fiddle, all console handling and emit redirection is omitted. */ |
| 1273 | 1362 | /* These next 3 macros are for emitting formatted output. When complaints |
| 1274 | | - * from the WASM build are issued for non-formatted output, (when a mere |
| 1363 | + * from the WASM build are issued for non-formatted output, when a mere |
| 1275 | 1364 | * string literal is to be emitted, the ?putz(z) forms should be used. |
| 1276 | 1365 | * (This permits compile-time checking of format string / argument mismatch.) |
| 1277 | 1366 | */ |
| 1278 | 1367 | # define oputf(fmt, ...) printf(fmt,__VA_ARGS__) |
| 1279 | 1368 | # define eputf(fmt, ...) fprintf(stderr,fmt,__VA_ARGS__) |
| | @@ -1281,10 +1370,11 @@ |
| 1281 | 1370 | /* These next 3 macros are for emitting simple string literals. */ |
| 1282 | 1371 | # define oputz(z) fputs(z,stdout) |
| 1283 | 1372 | # define eputz(z) fputs(z,stderr) |
| 1284 | 1373 | # define sputz(fp,z) fputs(z,fp) |
| 1285 | 1374 | # define oputb(buf,na) fwrite(buf,1,na,stdout) |
| 1375 | +# undef fflush |
| 1286 | 1376 | #endif |
| 1287 | 1377 | |
| 1288 | 1378 | /* True if the timer is enabled */ |
| 1289 | 1379 | static int enableTimer = 0; |
| 1290 | 1380 | |
| | @@ -4689,11 +4779,11 @@ |
| 4689 | 4779 | ** May you share freely, never taking more than you give. |
| 4690 | 4780 | ** |
| 4691 | 4781 | ****************************************************************************** |
| 4692 | 4782 | ** |
| 4693 | 4783 | ** This file contains code to implement the percentile(Y,P) SQL function |
| 4694 | | -** as described below: |
| 4784 | +** and similar as described below: |
| 4695 | 4785 | ** |
| 4696 | 4786 | ** (1) The percentile(Y,P) function is an aggregate function taking |
| 4697 | 4787 | ** exactly two arguments. |
| 4698 | 4788 | ** |
| 4699 | 4789 | ** (2) If the P argument to percentile(Y,P) is not the same for every |
| | @@ -4738,48 +4828,173 @@ |
| 4738 | 4828 | ** file that compiles into a shared-library or DLL that can be loaded |
| 4739 | 4829 | ** into SQLite using the sqlite3_load_extension() interface. |
| 4740 | 4830 | ** |
| 4741 | 4831 | ** (13) A separate median(Y) function is the equivalent percentile(Y,50). |
| 4742 | 4832 | ** |
| 4743 | | -** (14) A separate percentile_cond(Y,X) function is the equivalent of |
| 4744 | | -** percentile(Y,X*100.0). |
| 4833 | +** (14) A separate percentile_cont(Y,P) function is equivalent to |
| 4834 | +** percentile(Y,P/100.0). In other words, the fraction value in |
| 4835 | +** the second argument is in the range of 0 to 1 instead of 0 to 100. |
| 4836 | +** |
| 4837 | +** (15) A separate percentile_disc(Y,P) function is like |
| 4838 | +** percentile_cont(Y,P) except that instead of returning the weighted |
| 4839 | +** average of the nearest two input values, it returns the next lower |
| 4840 | +** value. So the percentile_disc(Y,P) will always return a value |
| 4841 | +** that was one of the inputs. |
| 4842 | +** |
| 4843 | +** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and |
| 4844 | +** percentile_disc(Y,P) can be used as window functions. |
| 4845 | +** |
| 4846 | +** Differences from standard SQL: |
| 4847 | +** |
| 4848 | +** * The percentile_cont(X,P) function is equivalent to the following in |
| 4849 | +** standard SQL: |
| 4850 | +** |
| 4851 | +** (percentile_cont(P) WITHIN GROUP (ORDER BY X)) |
| 4852 | +** |
| 4853 | +** The SQLite syntax is much more compact. The standard SQL syntax |
| 4854 | +** is also supported if SQLite is compiled with the |
| 4855 | +** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option. |
| 4856 | +** |
| 4857 | +** * No median(X) function exists in the SQL standard. App developers |
| 4858 | +** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)". |
| 4859 | +** |
| 4860 | +** * No percentile(Y,P) function exists in the SQL standard. Instead of |
| 4861 | +** percential(Y,P), developers must write this: |
| 4862 | +** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that |
| 4863 | +** the fraction parameter to percentile() goes from 0 to 100 whereas |
| 4864 | +** the fraction parameter in SQL standard percentile_cont() goes from |
| 4865 | +** 0 to 1. |
| 4866 | +** |
| 4867 | +** Implementation notes as of 2024-08-31: |
| 4868 | +** |
| 4869 | +** * The regular aggregate-function versions of these routines work |
| 4870 | +** by accumulating all values in an array of doubles, then sorting |
| 4871 | +** that array using quicksort before computing the answer. Thus |
| 4872 | +** the runtime is O(NlogN) where N is the number of rows of input. |
| 4873 | +** |
| 4874 | +** * For the window-function versions of these routines, the array of |
| 4875 | +** inputs is sorted as soon as the first value is computed. Thereafter, |
| 4876 | +** the array is kept in sorted order using an insert-sort. This |
| 4877 | +** results in O(N*K) performance where K is the size of the window. |
| 4878 | +** One can imagine alternative implementations that give O(N*logN*logK) |
| 4879 | +** performance, but they require more complex logic and data structures. |
| 4880 | +** The developers have elected to keep the asymptotically slower |
| 4881 | +** algorithm for now, for simplicity, under the theory that window |
| 4882 | +** functions are seldom used and when they are, the window size K is |
| 4883 | +** often small. The developers might revisit that decision later, |
| 4884 | +** should the need arise. |
| 4745 | 4885 | */ |
| 4746 | | -/* #include "sqlite3ext.h" */ |
| 4747 | | -SQLITE_EXTENSION_INIT1 |
| 4886 | +#if defined(SQLITE3_H) |
| 4887 | + /* no-op */ |
| 4888 | +#elif defined(SQLITE_STATIC_PERCENTILE) |
| 4889 | +/* # include "sqlite3.h" */ |
| 4890 | +#else |
| 4891 | +/* # include "sqlite3ext.h" */ |
| 4892 | + SQLITE_EXTENSION_INIT1 |
| 4893 | +#endif |
| 4748 | 4894 | #include <assert.h> |
| 4749 | 4895 | #include <string.h> |
| 4750 | 4896 | #include <stdlib.h> |
| 4751 | 4897 | |
| 4752 | | -/* The following object is the session context for a single percentile() |
| 4753 | | -** function. We have to remember all input Y values until the very end. |
| 4898 | +/* The following object is the group context for a single percentile() |
| 4899 | +** aggregate. Remember all input Y values until the very end. |
| 4754 | 4900 | ** Those values are accumulated in the Percentile.a[] array. |
| 4755 | 4901 | */ |
| 4756 | 4902 | typedef struct Percentile Percentile; |
| 4757 | 4903 | struct Percentile { |
| 4758 | 4904 | unsigned nAlloc; /* Number of slots allocated for a[] */ |
| 4759 | 4905 | unsigned nUsed; /* Number of slots actually used in a[] */ |
| 4760 | | - double rPct; /* 1.0 more than the value for P */ |
| 4906 | + char bSorted; /* True if a[] is already in sorted order */ |
| 4907 | + char bKeepSorted; /* True if advantageous to keep a[] sorted */ |
| 4908 | + char bPctValid; /* True if rPct is valid */ |
| 4909 | + double rPct; /* Fraction. 0.0 to 1.0 */ |
| 4761 | 4910 | double *a; /* Array of Y values */ |
| 4762 | 4911 | }; |
| 4912 | + |
| 4913 | +/* Details of each function in the percentile family */ |
| 4914 | +typedef struct PercentileFunc PercentileFunc; |
| 4915 | +struct PercentileFunc { |
| 4916 | + const char *zName; /* Function name */ |
| 4917 | + char nArg; /* Number of arguments */ |
| 4918 | + char mxFrac; /* Maximum value of the "fraction" input */ |
| 4919 | + char bDiscrete; /* True for percentile_disc() */ |
| 4920 | +}; |
| 4921 | +static const PercentileFunc aPercentFunc[] = { |
| 4922 | + { "median", 1, 1, 0 }, |
| 4923 | + { "percentile", 2, 100, 0 }, |
| 4924 | + { "percentile_cont", 2, 1, 0 }, |
| 4925 | + { "percentile_disc", 2, 1, 1 }, |
| 4926 | +}; |
| 4763 | 4927 | |
| 4764 | 4928 | /* |
| 4765 | 4929 | ** Return TRUE if the input floating-point number is an infinity. |
| 4766 | 4930 | */ |
| 4767 | | -static int isInfinity(double r){ |
| 4931 | +static int percentIsInfinity(double r){ |
| 4768 | 4932 | sqlite3_uint64 u; |
| 4769 | 4933 | assert( sizeof(u)==sizeof(r) ); |
| 4770 | 4934 | memcpy(&u, &r, sizeof(u)); |
| 4771 | 4935 | return ((u>>52)&0x7ff)==0x7ff; |
| 4772 | 4936 | } |
| 4773 | 4937 | |
| 4774 | 4938 | /* |
| 4775 | | -** Return TRUE if two doubles differ by 0.001 or less |
| 4939 | +** Return TRUE if two doubles differ by 0.001 or less. |
| 4776 | 4940 | */ |
| 4777 | | -static int sameValue(double a, double b){ |
| 4941 | +static int percentSameValue(double a, double b){ |
| 4778 | 4942 | a -= b; |
| 4779 | 4943 | return a>=-0.001 && a<=0.001; |
| 4780 | 4944 | } |
| 4945 | + |
| 4946 | +/* |
| 4947 | +** Search p (which must have p->bSorted) looking for an entry with |
| 4948 | +** value y. Return the index of that entry. |
| 4949 | +** |
| 4950 | +** If bExact is true, return -1 if the entry is not found. |
| 4951 | +** |
| 4952 | +** If bExact is false, return the index at which a new entry with |
| 4953 | +** value y should be insert in order to keep the values in sorted |
| 4954 | +** order. The smallest return value in this case will be 0, and |
| 4955 | +** the largest return value will be p->nUsed. |
| 4956 | +*/ |
| 4957 | +static int percentBinarySearch(Percentile *p, double y, int bExact){ |
| 4958 | + int iFirst = 0; /* First element of search range */ |
| 4959 | + int iLast = p->nUsed - 1; /* Last element of search range */ |
| 4960 | + while( iLast>=iFirst ){ |
| 4961 | + int iMid = (iFirst+iLast)/2; |
| 4962 | + double x = p->a[iMid]; |
| 4963 | + if( x<y ){ |
| 4964 | + iFirst = iMid + 1; |
| 4965 | + }else if( x>y ){ |
| 4966 | + iLast = iMid - 1; |
| 4967 | + }else{ |
| 4968 | + return iMid; |
| 4969 | + } |
| 4970 | + } |
| 4971 | + if( bExact ) return -1; |
| 4972 | + return iFirst; |
| 4973 | +} |
| 4974 | + |
| 4975 | +/* |
| 4976 | +** Generate an error for a percentile function. |
| 4977 | +** |
| 4978 | +** The error format string must have exactly one occurrance of "%%s()" |
| 4979 | +** (with two '%' characters). That substring will be replaced by the name |
| 4980 | +** of the function. |
| 4981 | +*/ |
| 4982 | +static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){ |
| 4983 | + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); |
| 4984 | + char *zMsg1; |
| 4985 | + char *zMsg2; |
| 4986 | + va_list ap; |
| 4987 | + |
| 4988 | + va_start(ap, zFormat); |
| 4989 | + zMsg1 = sqlite3_vmprintf(zFormat, ap); |
| 4990 | + va_end(ap); |
| 4991 | + zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0; |
| 4992 | + sqlite3_result_error(pCtx, zMsg2, -1); |
| 4993 | + sqlite3_free(zMsg1); |
| 4994 | + sqlite3_free(zMsg2); |
| 4995 | +} |
| 4781 | 4996 | |
| 4782 | 4997 | /* |
| 4783 | 4998 | ** The "step" function for percentile(Y,P) is called once for each |
| 4784 | 4999 | ** input row. |
| 4785 | 5000 | */ |
| | @@ -4790,45 +5005,38 @@ |
| 4790 | 5005 | double y; |
| 4791 | 5006 | assert( argc==2 || argc==1 ); |
| 4792 | 5007 | |
| 4793 | 5008 | if( argc==1 ){ |
| 4794 | 5009 | /* Requirement 13: median(Y) is the same as percentile(Y,50). */ |
| 4795 | | - rPct = 50.0; |
| 4796 | | - }else if( sqlite3_user_data(pCtx)==0 ){ |
| 4797 | | - /* Requirement 3: P must be a number between 0 and 100 */ |
| 4798 | | - eType = sqlite3_value_numeric_type(argv[1]); |
| 4799 | | - rPct = sqlite3_value_double(argv[1]); |
| 4800 | | - if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) |
| 4801 | | - || rPct<0.0 || rPct>100.0 ){ |
| 4802 | | - sqlite3_result_error(pCtx, "2nd argument to percentile() is not " |
| 4803 | | - "a number between 0.0 and 100.0", -1); |
| 4804 | | - return; |
| 4805 | | - } |
| 4806 | | - }else{ |
| 4807 | | - /* Requirement 3: P must be a number between 0 and 1 */ |
| 4808 | | - eType = sqlite3_value_numeric_type(argv[1]); |
| 4809 | | - rPct = sqlite3_value_double(argv[1]); |
| 4810 | | - if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) |
| 4811 | | - || rPct<0.0 || rPct>1.0 ){ |
| 4812 | | - sqlite3_result_error(pCtx, "2nd argument to percentile_cont() is not " |
| 4813 | | - "a number between 0.0 and 1.0", -1); |
| 4814 | | - return; |
| 4815 | | - } |
| 4816 | | - rPct *= 100.0; |
| 5010 | + rPct = 0.5; |
| 5011 | + }else{ |
| 5012 | + /* Requirement 3: P must be a number between 0 and 100 */ |
| 5013 | + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); |
| 5014 | + eType = sqlite3_value_numeric_type(argv[1]); |
| 5015 | + rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac; |
| 5016 | + if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) |
| 5017 | + || rPct<0.0 || rPct>1.0 |
| 5018 | + ){ |
| 5019 | + percentError(pCtx, "the fraction argument to %%s()" |
| 5020 | + " is not between 0.0 and %.1f", |
| 5021 | + (double)pFunc->mxFrac); |
| 5022 | + return; |
| 5023 | + } |
| 4817 | 5024 | } |
| 4818 | 5025 | |
| 4819 | 5026 | /* Allocate the session context. */ |
| 4820 | 5027 | p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); |
| 4821 | 5028 | if( p==0 ) return; |
| 4822 | 5029 | |
| 4823 | 5030 | /* Remember the P value. Throw an error if the P value is different |
| 4824 | 5031 | ** from any prior row, per Requirement (2). */ |
| 4825 | | - if( p->rPct==0.0 ){ |
| 4826 | | - p->rPct = rPct+1.0; |
| 4827 | | - }else if( !sameValue(p->rPct,rPct+1.0) ){ |
| 4828 | | - sqlite3_result_error(pCtx, "2nd argument to percentile() is not the " |
| 4829 | | - "same for all input rows", -1); |
| 5032 | + if( !p->bPctValid ){ |
| 5033 | + p->rPct = rPct; |
| 5034 | + p->bPctValid = 1; |
| 5035 | + }else if( !percentSameValue(p->rPct,rPct) ){ |
| 5036 | + percentError(pCtx, "the fraction argument to %%s()" |
| 5037 | + " is not the same for all input rows"); |
| 4830 | 5038 | return; |
| 4831 | 5039 | } |
| 4832 | 5040 | |
| 4833 | 5041 | /* Ignore rows for which Y is NULL */ |
| 4834 | 5042 | eType = sqlite3_value_type(argv[0]); |
| | @@ -4835,19 +5043,18 @@ |
| 4835 | 5043 | if( eType==SQLITE_NULL ) return; |
| 4836 | 5044 | |
| 4837 | 5045 | /* If not NULL, then Y must be numeric. Otherwise throw an error. |
| 4838 | 5046 | ** Requirement 4 */ |
| 4839 | 5047 | if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ |
| 4840 | | - sqlite3_result_error(pCtx, "1st argument to percentile() is not " |
| 4841 | | - "numeric", -1); |
| 5048 | + percentError(pCtx, "input to %%s() is not numeric"); |
| 4842 | 5049 | return; |
| 4843 | 5050 | } |
| 4844 | 5051 | |
| 4845 | 5052 | /* Throw an error if the Y value is infinity or NaN */ |
| 4846 | 5053 | y = sqlite3_value_double(argv[0]); |
| 4847 | | - if( isInfinity(y) ){ |
| 4848 | | - sqlite3_result_error(pCtx, "Inf input to percentile()", -1); |
| 5054 | + if( percentIsInfinity(y) ){ |
| 5055 | + percentError(pCtx, "Inf input to %%s()"); |
| 4849 | 5056 | return; |
| 4850 | 5057 | } |
| 4851 | 5058 | |
| 4852 | 5059 | /* Allocate and store the Y */ |
| 4853 | 5060 | if( p->nUsed>=p->nAlloc ){ |
| | @@ -4860,112 +5067,209 @@ |
| 4860 | 5067 | return; |
| 4861 | 5068 | } |
| 4862 | 5069 | p->nAlloc = n; |
| 4863 | 5070 | p->a = a; |
| 4864 | 5071 | } |
| 4865 | | - p->a[p->nUsed++] = y; |
| 5072 | + if( p->nUsed==0 ){ |
| 5073 | + p->a[p->nUsed++] = y; |
| 5074 | + p->bSorted = 1; |
| 5075 | + }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ |
| 5076 | + p->a[p->nUsed++] = y; |
| 5077 | + }else if( p->bKeepSorted ){ |
| 5078 | + int i; |
| 5079 | + i = percentBinarySearch(p, y, 0); |
| 5080 | + if( i<p->nUsed ){ |
| 5081 | + memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); |
| 5082 | + } |
| 5083 | + p->a[i] = y; |
| 5084 | + p->nUsed++; |
| 5085 | + }else{ |
| 5086 | + p->a[p->nUsed++] = y; |
| 5087 | + p->bSorted = 0; |
| 5088 | + } |
| 4866 | 5089 | } |
| 4867 | 5090 | |
| 5091 | +/* |
| 5092 | +** Interchange two doubles. |
| 5093 | +*/ |
| 5094 | +#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;} |
| 5095 | + |
| 4868 | 5096 | /* |
| 4869 | 5097 | ** Sort an array of doubles. |
| 5098 | +** |
| 5099 | +** Algorithm: quicksort |
| 5100 | +** |
| 5101 | +** This is implemented separately rather than using the qsort() routine |
| 5102 | +** from the standard library because: |
| 5103 | +** |
| 5104 | +** (1) To avoid a dependency on qsort() |
| 5105 | +** (2) To avoid the function call to the comparison routine for each |
| 5106 | +** comparison. |
| 4870 | 5107 | */ |
| 4871 | | -static void sortDoubles(double *a, int n){ |
| 4872 | | - int iLt; /* Entries with index less than iLt are less than rPivot */ |
| 4873 | | - int iGt; /* Entries with index iGt or more are greater than rPivot */ |
| 5108 | +static void percentSort(double *a, unsigned int n){ |
| 5109 | + int iLt; /* Entries before a[iLt] are less than rPivot */ |
| 5110 | + int iGt; /* Entries at or after a[iGt] are greater than rPivot */ |
| 4874 | 5111 | int i; /* Loop counter */ |
| 4875 | 5112 | double rPivot; /* The pivot value */ |
| 4876 | | - double rTmp; /* Temporary used to swap two values */ |
| 4877 | | - |
| 4878 | | - if( n<2 ) return; |
| 4879 | | - if( n>5 ){ |
| 4880 | | - rPivot = (a[0] + a[n/2] + a[n-1])/3.0; |
| 4881 | | - }else{ |
| 4882 | | - rPivot = a[n/2]; |
| 4883 | | - } |
| 4884 | | - iLt = i = 0; |
| 4885 | | - iGt = n; |
| 4886 | | - while( i<iGt ){ |
| 5113 | + |
| 5114 | + assert( n>=2 ); |
| 5115 | + if( a[0]>a[n-1] ){ |
| 5116 | + SWAP_DOUBLE(a[0],a[n-1]) |
| 5117 | + } |
| 5118 | + if( n==2 ) return; |
| 5119 | + iGt = n-1; |
| 5120 | + i = n/2; |
| 5121 | + if( a[0]>a[i] ){ |
| 5122 | + SWAP_DOUBLE(a[0],a[i]) |
| 5123 | + }else if( a[i]>a[iGt] ){ |
| 5124 | + SWAP_DOUBLE(a[i],a[iGt]) |
| 5125 | + } |
| 5126 | + if( n==3 ) return; |
| 5127 | + rPivot = a[i]; |
| 5128 | + iLt = i = 1; |
| 5129 | + do{ |
| 4887 | 5130 | if( a[i]<rPivot ){ |
| 4888 | | - if( i>iLt ){ |
| 4889 | | - rTmp = a[i]; |
| 4890 | | - a[i] = a[iLt]; |
| 4891 | | - a[iLt] = rTmp; |
| 4892 | | - } |
| 5131 | + if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt]) |
| 4893 | 5132 | iLt++; |
| 4894 | 5133 | i++; |
| 4895 | 5134 | }else if( a[i]>rPivot ){ |
| 4896 | 5135 | do{ |
| 4897 | 5136 | iGt--; |
| 4898 | 5137 | }while( iGt>i && a[iGt]>rPivot ); |
| 4899 | | - rTmp = a[i]; |
| 4900 | | - a[i] = a[iGt]; |
| 4901 | | - a[iGt] = rTmp; |
| 5138 | + SWAP_DOUBLE(a[i],a[iGt]) |
| 4902 | 5139 | }else{ |
| 4903 | 5140 | i++; |
| 4904 | 5141 | } |
| 4905 | | - } |
| 4906 | | - if( iLt>=2 ) sortDoubles(a, iLt); |
| 4907 | | - if( n-iGt>=2 ) sortDoubles(a+iGt, n-iGt); |
| 4908 | | - |
| 5142 | + }while( i<iGt ); |
| 5143 | + if( iLt>=2 ) percentSort(a, iLt); |
| 5144 | + if( n-iGt>=2 ) percentSort(a+iGt, n-iGt); |
| 5145 | + |
| 4909 | 5146 | /* Uncomment for testing */ |
| 4910 | 5147 | #if 0 |
| 4911 | 5148 | for(i=0; i<n-1; i++){ |
| 4912 | 5149 | assert( a[i]<=a[i+1] ); |
| 4913 | 5150 | } |
| 4914 | 5151 | #endif |
| 4915 | 5152 | } |
| 5153 | + |
| 4916 | 5154 | |
| 4917 | 5155 | /* |
| 4918 | | -** Called to compute the final output of percentile() and to clean |
| 4919 | | -** up all allocated memory. |
| 5156 | +** The "inverse" function for percentile(Y,P) is called to remove a |
| 5157 | +** row that was previously inserted by "step". |
| 4920 | 5158 | */ |
| 4921 | | -static void percentFinal(sqlite3_context *pCtx){ |
| 5159 | +static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){ |
| 5160 | + Percentile *p; |
| 5161 | + int eType; |
| 5162 | + double y; |
| 5163 | + int i; |
| 5164 | + assert( argc==2 || argc==1 ); |
| 5165 | + |
| 5166 | + /* Allocate the session context. */ |
| 5167 | + p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); |
| 5168 | + assert( p!=0 ); |
| 5169 | + |
| 5170 | + /* Ignore rows for which Y is NULL */ |
| 5171 | + eType = sqlite3_value_type(argv[0]); |
| 5172 | + if( eType==SQLITE_NULL ) return; |
| 5173 | + |
| 5174 | + /* If not NULL, then Y must be numeric. Otherwise throw an error. |
| 5175 | + ** Requirement 4 */ |
| 5176 | + if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ |
| 5177 | + return; |
| 5178 | + } |
| 5179 | + |
| 5180 | + /* Ignore the Y value if it is infinity or NaN */ |
| 5181 | + y = sqlite3_value_double(argv[0]); |
| 5182 | + if( percentIsInfinity(y) ){ |
| 5183 | + return; |
| 5184 | + } |
| 5185 | + if( p->bSorted==0 ){ |
| 5186 | + assert( p->nUsed>1 ); |
| 5187 | + percentSort(p->a, p->nUsed); |
| 5188 | + p->bSorted = 1; |
| 5189 | + } |
| 5190 | + p->bKeepSorted = 1; |
| 5191 | + |
| 5192 | + /* Find and remove the row */ |
| 5193 | + i = percentBinarySearch(p, y, 1); |
| 5194 | + if( i>=0 ){ |
| 5195 | + p->nUsed--; |
| 5196 | + if( i<p->nUsed ){ |
| 5197 | + memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0])); |
| 5198 | + } |
| 5199 | + } |
| 5200 | +} |
| 5201 | + |
| 5202 | +/* |
| 5203 | +** Compute the final output of percentile(). Clean up all allocated |
| 5204 | +** memory if and only if bIsFinal is true. |
| 5205 | +*/ |
| 5206 | +static void percentCompute(sqlite3_context *pCtx, int bIsFinal){ |
| 4922 | 5207 | Percentile *p; |
| 5208 | + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); |
| 4923 | 5209 | unsigned i1, i2; |
| 4924 | 5210 | double v1, v2; |
| 4925 | 5211 | double ix, vx; |
| 4926 | 5212 | p = (Percentile*)sqlite3_aggregate_context(pCtx, 0); |
| 4927 | 5213 | if( p==0 ) return; |
| 4928 | 5214 | if( p->a==0 ) return; |
| 4929 | 5215 | if( p->nUsed ){ |
| 4930 | | - sortDoubles(p->a, p->nUsed); |
| 4931 | | - ix = (p->rPct-1.0)*(p->nUsed-1)*0.01; |
| 5216 | + if( p->bSorted==0 ){ |
| 5217 | + assert( p->nUsed>1 ); |
| 5218 | + percentSort(p->a, p->nUsed); |
| 5219 | + p->bSorted = 1; |
| 5220 | + } |
| 5221 | + ix = p->rPct*(p->nUsed-1); |
| 4932 | 5222 | i1 = (unsigned)ix; |
| 4933 | | - i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; |
| 4934 | | - v1 = p->a[i1]; |
| 4935 | | - v2 = p->a[i2]; |
| 4936 | | - vx = v1 + (v2-v1)*(ix-i1); |
| 5223 | + if( pFunc->bDiscrete ){ |
| 5224 | + vx = p->a[i1]; |
| 5225 | + }else{ |
| 5226 | + i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; |
| 5227 | + v1 = p->a[i1]; |
| 5228 | + v2 = p->a[i2]; |
| 5229 | + vx = v1 + (v2-v1)*(ix-i1); |
| 5230 | + } |
| 4937 | 5231 | sqlite3_result_double(pCtx, vx); |
| 4938 | 5232 | } |
| 4939 | | - sqlite3_free(p->a); |
| 4940 | | - memset(p, 0, sizeof(*p)); |
| 5233 | + if( bIsFinal ){ |
| 5234 | + sqlite3_free(p->a); |
| 5235 | + memset(p, 0, sizeof(*p)); |
| 5236 | + }else{ |
| 5237 | + p->bKeepSorted = 1; |
| 5238 | + } |
| 5239 | +} |
| 5240 | +static void percentFinal(sqlite3_context *pCtx){ |
| 5241 | + percentCompute(pCtx, 1); |
| 5242 | +} |
| 5243 | +static void percentValue(sqlite3_context *pCtx){ |
| 5244 | + percentCompute(pCtx, 0); |
| 4941 | 5245 | } |
| 4942 | 5246 | |
| 4943 | | - |
| 4944 | | -#ifdef _WIN32 |
| 5247 | +#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE) |
| 4945 | 5248 | |
| 4946 | 5249 | #endif |
| 4947 | 5250 | int sqlite3_percentile_init( |
| 4948 | 5251 | sqlite3 *db, |
| 4949 | 5252 | char **pzErrMsg, |
| 4950 | 5253 | const sqlite3_api_routines *pApi |
| 4951 | 5254 | ){ |
| 4952 | 5255 | int rc = SQLITE_OK; |
| 5256 | + int i; |
| 5257 | +#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE) |
| 5258 | + (void)pApi; /* Unused parameter */ |
| 5259 | +#else |
| 4953 | 5260 | SQLITE_EXTENSION_INIT2(pApi); |
| 5261 | +#endif |
| 4954 | 5262 | (void)pzErrMsg; /* Unused parameter */ |
| 4955 | | - rc = sqlite3_create_function(db, "percentile", 2, |
| 4956 | | - SQLITE_UTF8|SQLITE_INNOCUOUS, 0, |
| 4957 | | - 0, percentStep, percentFinal); |
| 4958 | | - if( rc==SQLITE_OK ){ |
| 4959 | | - rc = sqlite3_create_function(db, "median", 1, |
| 4960 | | - SQLITE_UTF8|SQLITE_INNOCUOUS, 0, |
| 4961 | | - 0, percentStep, percentFinal); |
| 4962 | | - } |
| 4963 | | - if( rc==SQLITE_OK ){ |
| 4964 | | - rc = sqlite3_create_function(db, "percentile_cont", 2, |
| 4965 | | - SQLITE_UTF8|SQLITE_INNOCUOUS, &percentStep, |
| 4966 | | - 0, percentStep, percentFinal); |
| 5263 | + for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){ |
| 5264 | + rc = sqlite3_create_window_function(db, |
| 5265 | + aPercentFunc[i].zName, |
| 5266 | + aPercentFunc[i].nArg, |
| 5267 | + SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_SELFORDER1, |
| 5268 | + (void*)&aPercentFunc[i], |
| 5269 | + percentStep, percentFinal, percentValue, percentInverse, 0); |
| 5270 | + if( rc ) break; |
| 4967 | 5271 | } |
| 4968 | 5272 | return rc; |
| 4969 | 5273 | } |
| 4970 | 5274 | |
| 4971 | 5275 | /************************* End ../ext/misc/percentile.c ********************/ |
| | @@ -22375,14 +22679,15 @@ |
| 22375 | 22679 | sqlite3_bind_double(pStmt, i, INFINITY); |
| 22376 | 22680 | #endif |
| 22377 | 22681 | }else if( strncmp(zVar, "$int_", 5)==0 ){ |
| 22378 | 22682 | sqlite3_bind_int(pStmt, i, atoi(&zVar[5])); |
| 22379 | 22683 | }else if( strncmp(zVar, "$text_", 6)==0 ){ |
| 22380 | | - char *zBuf = sqlite3_malloc64( strlen(zVar)-5 ); |
| 22684 | + size_t szVar = strlen(zVar); |
| 22685 | + char *zBuf = sqlite3_malloc64( szVar-5 ); |
| 22381 | 22686 | if( zBuf ){ |
| 22382 | | - memcpy(zBuf, &zVar[6], strlen(zVar)-5); |
| 22383 | | - sqlite3_bind_text64(pStmt, i, zBuf, -1, sqlite3_free, SQLITE_UTF8); |
| 22687 | + memcpy(zBuf, &zVar[6], szVar-5); |
| 22688 | + sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8); |
| 22384 | 22689 | } |
| 22385 | 22690 | }else{ |
| 22386 | 22691 | sqlite3_bind_null(pStmt, i); |
| 22387 | 22692 | } |
| 22388 | 22693 | sqlite3_reset(pQ); |
| | @@ -29871,11 +30176,11 @@ |
| 29871 | 30176 | sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt); |
| 29872 | 30177 | newOpt = curOpt; |
| 29873 | 30178 | for(ii=2; ii<nArg; ii++){ |
| 29874 | 30179 | const char *z = azArg[ii]; |
| 29875 | 30180 | int useLabel = 0; |
| 29876 | | - const char *zLabel; |
| 30181 | + const char *zLabel = 0; |
| 29877 | 30182 | if( (z[0]=='+'|| z[0]=='-') && !IsDigit(z[1]) ){ |
| 29878 | 30183 | useLabel = z[0]; |
| 29879 | 30184 | zLabel = &z[1]; |
| 29880 | 30185 | }else if( !IsDigit(z[0]) && z[0]!=0 && !IsDigit(z[1]) ){ |
| 29881 | 30186 | useLabel = '+'; |
| | @@ -29888,15 +30193,15 @@ |
| 29888 | 30193 | for(jj=0; jj<ArraySize(aLabel); jj++){ |
| 29889 | 30194 | if( sqlite3_stricmp(zLabel, aLabel[jj].zLabel)==0 ) break; |
| 29890 | 30195 | } |
| 29891 | 30196 | if( jj>=ArraySize(aLabel) ){ |
| 29892 | 30197 | eputf("Error: no such optimization: \"%s\"\n", zLabel); |
| 29893 | | - eputf("Should be one of:"); |
| 30198 | + eputz("Should be one of:"); |
| 29894 | 30199 | for(jj=0; jj<ArraySize(aLabel); jj++){ |
| 29895 | 30200 | eputf(" %s", aLabel[jj].zLabel); |
| 29896 | 30201 | } |
| 29897 | | - eputf("\n"); |
| 30202 | + eputz("\n"); |
| 29898 | 30203 | rc = 1; |
| 29899 | 30204 | goto meta_command_exit; |
| 29900 | 30205 | } |
| 29901 | 30206 | if( useLabel=='+' ){ |
| 29902 | 30207 | newOpt &= ~aLabel[jj].mask; |
| | @@ -29909,13 +30214,13 @@ |
| 29909 | 30214 | sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,p->db,newOpt); |
| 29910 | 30215 | }else if( nArg<3 ){ |
| 29911 | 30216 | curOpt = ~newOpt; |
| 29912 | 30217 | } |
| 29913 | 30218 | if( newOpt==0 ){ |
| 29914 | | - oputf("+All\n"); |
| 30219 | + oputz("+All\n"); |
| 29915 | 30220 | }else if( newOpt==0xffffffff ){ |
| 29916 | | - oputf("-All\n"); |
| 30221 | + oputz("-All\n"); |
| 29917 | 30222 | }else{ |
| 29918 | 30223 | int jj; |
| 29919 | 30224 | for(jj=0; jj<ArraySize(aLabel); jj++){ |
| 29920 | 30225 | unsigned int m = aLabel[jj].mask; |
| 29921 | 30226 | if( !aLabel[jj].bDsply ) continue; |
| 29922 | 30227 | |