| | @@ -657,11 +657,11 @@ |
| 657 | 657 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 658 | 658 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 659 | 659 | */ |
| 660 | 660 | #define SQLITE_VERSION "3.7.12" |
| 661 | 661 | #define SQLITE_VERSION_NUMBER 3007012 |
| 662 | | -#define SQLITE_SOURCE_ID "2012-03-31 19:12:23 af602d87736b52802a4e760ffeeaa28112b99d9a" |
| 662 | +#define SQLITE_SOURCE_ID "2012-04-17 09:09:33 8e2363ad76446e863d03ead91fd621e59d5cb495" |
| 663 | 663 | |
| 664 | 664 | /* |
| 665 | 665 | ** CAPI3REF: Run-Time Library Version Numbers |
| 666 | 666 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 667 | 667 | ** |
| | @@ -2095,11 +2095,11 @@ |
| 2095 | 2095 | ** database connection is opened. By default, URI handling is globally |
| 2096 | 2096 | ** disabled. The default value may be changed by compiling with the |
| 2097 | 2097 | ** [SQLITE_USE_URI] symbol defined. |
| 2098 | 2098 | ** |
| 2099 | 2099 | ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] |
| 2100 | | -** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE |
| 2100 | +** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE |
| 2101 | 2101 | ** <dd> These options are obsolete and should not be used by new code. |
| 2102 | 2102 | ** They are retained for backwards compatibility but are now no-ops. |
| 2103 | 2103 | ** </dl> |
| 2104 | 2104 | */ |
| 2105 | 2105 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| | @@ -7533,11 +7533,15 @@ |
| 7533 | 7533 | ** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) |
| 7534 | 7534 | */ |
| 7535 | 7535 | SQLITE_API int sqlite3_rtree_geometry_callback( |
| 7536 | 7536 | sqlite3 *db, |
| 7537 | 7537 | const char *zGeom, |
| 7538 | | - int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), |
| 7538 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 7539 | + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), |
| 7540 | +#else |
| 7541 | + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), |
| 7542 | +#endif |
| 7539 | 7543 | void *pContext |
| 7540 | 7544 | ); |
| 7541 | 7545 | |
| 7542 | 7546 | |
| 7543 | 7547 | /* |
| | @@ -10933,11 +10937,10 @@ |
| 10933 | 10937 | int nRef; /* Number of names resolved by this context */ |
| 10934 | 10938 | int nErr; /* Number of errors encountered while resolving names */ |
| 10935 | 10939 | u8 allowAgg; /* Aggregate functions allowed here */ |
| 10936 | 10940 | u8 hasAgg; /* True if aggregates are seen */ |
| 10937 | 10941 | u8 isCheck; /* True if resolving names in a CHECK constraint */ |
| 10938 | | - int nDepth; /* Depth of subquery recursion. 1 for no recursion */ |
| 10939 | 10942 | AggInfo *pAggInfo; /* Information about aggregates at this level */ |
| 10940 | 10943 | NameContext *pNext; /* Next outer name context. NULL for outermost */ |
| 10941 | 10944 | }; |
| 10942 | 10945 | |
| 10943 | 10946 | /* |
| | @@ -11399,10 +11402,11 @@ |
| 11399 | 11402 | int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ |
| 11400 | 11403 | Parse *pParse; /* Parser context. */ |
| 11401 | 11404 | union { /* Extra data for callback */ |
| 11402 | 11405 | NameContext *pNC; /* Naming context */ |
| 11403 | 11406 | int i; /* Integer value */ |
| 11407 | + SrcList *pSrcList; /* FROM clause */ |
| 11404 | 11408 | } u; |
| 11405 | 11409 | }; |
| 11406 | 11410 | |
| 11407 | 11411 | /* Forward declarations */ |
| 11408 | 11412 | SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*); |
| | @@ -11767,11 +11771,11 @@ |
| 11767 | 11771 | SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); |
| 11768 | 11772 | SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); |
| 11769 | 11773 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); |
| 11770 | 11774 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); |
| 11771 | 11775 | SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); |
| 11772 | | -SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); |
| 11776 | +SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); |
| 11773 | 11777 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); |
| 11774 | 11778 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 11775 | 11779 | SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); |
| 11776 | 11780 | SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); |
| 11777 | 11781 | SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| | @@ -24995,12 +24999,12 @@ |
| 24995 | 24999 | #ifndef SQLITE_DEFAULT_FILE_PERMISSIONS |
| 24996 | 25000 | # define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 |
| 24997 | 25001 | #endif |
| 24998 | 25002 | |
| 24999 | 25003 | /* |
| 25000 | | - ** Default permissions when creating auto proxy dir |
| 25001 | | - */ |
| 25004 | +** Default permissions when creating auto proxy dir |
| 25005 | +*/ |
| 25002 | 25006 | #ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS |
| 25003 | 25007 | # define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 |
| 25004 | 25008 | #endif |
| 25005 | 25009 | |
| 25006 | 25010 | /* |
| | @@ -25550,11 +25554,11 @@ |
| 25550 | 25554 | return 0; |
| 25551 | 25555 | } |
| 25552 | 25556 | |
| 25553 | 25557 | /* |
| 25554 | 25558 | ** Invoke open(). Do so multiple times, until it either succeeds or |
| 25555 | | -** files for some reason other than EINTR. |
| 25559 | +** fails for some reason other than EINTR. |
| 25556 | 25560 | ** |
| 25557 | 25561 | ** If the file creation mode "m" is 0 then set it to the default for |
| 25558 | 25562 | ** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally |
| 25559 | 25563 | ** 0644) as modified by the system umask. If m is not 0, then |
| 25560 | 25564 | ** make the file creation mode be exactly m ignoring the umask. |
| | @@ -25566,24 +25570,33 @@ |
| 25566 | 25570 | ** transaction crashes and leaves behind hot journals, then any |
| 25567 | 25571 | ** process that is able to write to the database will also be able to |
| 25568 | 25572 | ** recover the hot journals. |
| 25569 | 25573 | */ |
| 25570 | 25574 | static int robust_open(const char *z, int f, mode_t m){ |
| 25571 | | - int rc; |
| 25575 | + int fd; |
| 25572 | 25576 | mode_t m2; |
| 25573 | 25577 | mode_t origM = 0; |
| 25574 | 25578 | if( m==0 ){ |
| 25575 | 25579 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 25576 | 25580 | }else{ |
| 25577 | 25581 | m2 = m; |
| 25578 | 25582 | origM = osUmask(0); |
| 25579 | 25583 | } |
| 25580 | | - do{ rc = osOpen(z,f,m2); }while( rc<0 && errno==EINTR ); |
| 25584 | + do{ |
| 25585 | +#if defined(O_CLOEXEC) |
| 25586 | + fd = osOpen(z,f|O_CLOEXEC,m2); |
| 25587 | +#else |
| 25588 | + fd = osOpen(z,f,m2); |
| 25589 | +#endif |
| 25590 | + }while( fd<0 && errno==EINTR ); |
| 25581 | 25591 | if( m ){ |
| 25582 | 25592 | osUmask(origM); |
| 25583 | 25593 | } |
| 25584 | | - return rc; |
| 25594 | +#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 25595 | + if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 25596 | +#endif |
| 25597 | + return fd; |
| 25585 | 25598 | } |
| 25586 | 25599 | |
| 25587 | 25600 | /* |
| 25588 | 25601 | ** Helper functions to obtain and relinquish the global mutex. The |
| 25589 | 25602 | ** global mutex is used to protect the unixInodeInfo and |
| | @@ -28374,13 +28387,10 @@ |
| 28374 | 28387 | for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); |
| 28375 | 28388 | if( ii>0 ){ |
| 28376 | 28389 | zDirname[ii] = '\0'; |
| 28377 | 28390 | fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); |
| 28378 | 28391 | if( fd>=0 ){ |
| 28379 | | -#ifdef FD_CLOEXEC |
| 28380 | | - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 28381 | | -#endif |
| 28382 | 28392 | OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); |
| 28383 | 28393 | } |
| 28384 | 28394 | } |
| 28385 | 28395 | *pFd = fd; |
| 28386 | 28396 | return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); |
| | @@ -28459,11 +28469,11 @@ |
| 28459 | 28469 | /* If the user has configured a chunk-size for this file, truncate the |
| 28460 | 28470 | ** file so that it consists of an integer number of chunks (i.e. the |
| 28461 | 28471 | ** actual file size after the operation may be larger than the requested |
| 28462 | 28472 | ** size). |
| 28463 | 28473 | */ |
| 28464 | | - if( pFile->szChunk ){ |
| 28474 | + if( pFile->szChunk>0 ){ |
| 28465 | 28475 | nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; |
| 28466 | 28476 | } |
| 28467 | 28477 | |
| 28468 | 28478 | rc = robust_ftruncate(pFile->h, (off_t)nByte); |
| 28469 | 28479 | if( rc ){ |
| | @@ -30221,14 +30231,10 @@ |
| 30221 | 30231 | else{ |
| 30222 | 30232 | p->openFlags = openFlags; |
| 30223 | 30233 | } |
| 30224 | 30234 | #endif |
| 30225 | 30235 | |
| 30226 | | -#ifdef FD_CLOEXEC |
| 30227 | | - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 30228 | | -#endif |
| 30229 | | - |
| 30230 | 30236 | noLock = eType!=SQLITE_OPEN_MAIN_DB; |
| 30231 | 30237 | |
| 30232 | 30238 | |
| 30233 | 30239 | #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE |
| 30234 | 30240 | if( fstatfs(fd, &fsInfo) == -1 ){ |
| | @@ -38001,10 +38007,15 @@ |
| 38001 | 38007 | #define ROWSET_ENTRY_PER_CHUNK \ |
| 38002 | 38008 | ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) |
| 38003 | 38009 | |
| 38004 | 38010 | /* |
| 38005 | 38011 | ** Each entry in a RowSet is an instance of the following object. |
| 38012 | +** |
| 38013 | +** This same object is reused to store a linked list of trees of RowSetEntry |
| 38014 | +** objects. In that alternative use, pRight points to the next entry |
| 38015 | +** in the list, pLeft points to the tree, and v is unused. The |
| 38016 | +** RowSet.pForest value points to the head of this forest list. |
| 38006 | 38017 | */ |
| 38007 | 38018 | struct RowSetEntry { |
| 38008 | 38019 | i64 v; /* ROWID value for this entry */ |
| 38009 | 38020 | struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ |
| 38010 | 38021 | struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ |
| | @@ -38030,16 +38041,22 @@ |
| 38030 | 38041 | struct RowSetChunk *pChunk; /* List of all chunk allocations */ |
| 38031 | 38042 | sqlite3 *db; /* The database connection */ |
| 38032 | 38043 | struct RowSetEntry *pEntry; /* List of entries using pRight */ |
| 38033 | 38044 | struct RowSetEntry *pLast; /* Last entry on the pEntry list */ |
| 38034 | 38045 | struct RowSetEntry *pFresh; /* Source of new entry objects */ |
| 38035 | | - struct RowSetEntry *pTree; /* Binary tree of entries */ |
| 38046 | + struct RowSetEntry *pForest; /* List of binary trees of entries */ |
| 38036 | 38047 | u16 nFresh; /* Number of objects on pFresh */ |
| 38037 | | - u8 isSorted; /* True if pEntry is sorted */ |
| 38048 | + u8 rsFlags; /* Various flags */ |
| 38038 | 38049 | u8 iBatch; /* Current insert batch */ |
| 38039 | 38050 | }; |
| 38040 | 38051 | |
| 38052 | +/* |
| 38053 | +** Allowed values for RowSet.rsFlags |
| 38054 | +*/ |
| 38055 | +#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ |
| 38056 | +#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ |
| 38057 | + |
| 38041 | 38058 | /* |
| 38042 | 38059 | ** Turn bulk memory into a RowSet object. N bytes of memory |
| 38043 | 38060 | ** are available at pSpace. The db pointer is used as a memory context |
| 38044 | 38061 | ** for any subsequent allocations that need to occur. |
| 38045 | 38062 | ** Return a pointer to the new RowSet object. |
| | @@ -38056,14 +38073,14 @@ |
| 38056 | 38073 | p = pSpace; |
| 38057 | 38074 | p->pChunk = 0; |
| 38058 | 38075 | p->db = db; |
| 38059 | 38076 | p->pEntry = 0; |
| 38060 | 38077 | p->pLast = 0; |
| 38061 | | - p->pTree = 0; |
| 38078 | + p->pForest = 0; |
| 38062 | 38079 | p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); |
| 38063 | 38080 | p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); |
| 38064 | | - p->isSorted = 1; |
| 38081 | + p->rsFlags = ROWSET_SORTED; |
| 38065 | 38082 | p->iBatch = 0; |
| 38066 | 38083 | return p; |
| 38067 | 38084 | } |
| 38068 | 38085 | |
| 38069 | 38086 | /* |
| | @@ -38079,12 +38096,37 @@ |
| 38079 | 38096 | } |
| 38080 | 38097 | p->pChunk = 0; |
| 38081 | 38098 | p->nFresh = 0; |
| 38082 | 38099 | p->pEntry = 0; |
| 38083 | 38100 | p->pLast = 0; |
| 38084 | | - p->pTree = 0; |
| 38085 | | - p->isSorted = 1; |
| 38101 | + p->pForest = 0; |
| 38102 | + p->rsFlags = ROWSET_SORTED; |
| 38103 | +} |
| 38104 | + |
| 38105 | +/* |
| 38106 | +** Allocate a new RowSetEntry object that is associated with the |
| 38107 | +** given RowSet. Return a pointer to the new and completely uninitialized |
| 38108 | +** objected. |
| 38109 | +** |
| 38110 | +** In an OOM situation, the RowSet.db->mallocFailed flag is set and this |
| 38111 | +** routine returns NULL. |
| 38112 | +*/ |
| 38113 | +static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ |
| 38114 | + assert( p!=0 ); |
| 38115 | + if( p->nFresh==0 ){ |
| 38116 | + struct RowSetChunk *pNew; |
| 38117 | + pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); |
| 38118 | + if( pNew==0 ){ |
| 38119 | + return 0; |
| 38120 | + } |
| 38121 | + pNew->pNextChunk = p->pChunk; |
| 38122 | + p->pChunk = pNew; |
| 38123 | + p->pFresh = pNew->aEntry; |
| 38124 | + p->nFresh = ROWSET_ENTRY_PER_CHUNK; |
| 38125 | + } |
| 38126 | + p->nFresh--; |
| 38127 | + return p->pFresh++; |
| 38086 | 38128 | } |
| 38087 | 38129 | |
| 38088 | 38130 | /* |
| 38089 | 38131 | ** Insert a new value into a RowSet. |
| 38090 | 38132 | ** |
| | @@ -38092,34 +38134,25 @@ |
| 38092 | 38134 | ** memory allocation fails. |
| 38093 | 38135 | */ |
| 38094 | 38136 | SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ |
| 38095 | 38137 | struct RowSetEntry *pEntry; /* The new entry */ |
| 38096 | 38138 | struct RowSetEntry *pLast; /* The last prior entry */ |
| 38097 | | - assert( p!=0 ); |
| 38098 | | - if( p->nFresh==0 ){ |
| 38099 | | - struct RowSetChunk *pNew; |
| 38100 | | - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); |
| 38101 | | - if( pNew==0 ){ |
| 38102 | | - return; |
| 38103 | | - } |
| 38104 | | - pNew->pNextChunk = p->pChunk; |
| 38105 | | - p->pChunk = pNew; |
| 38106 | | - p->pFresh = pNew->aEntry; |
| 38107 | | - p->nFresh = ROWSET_ENTRY_PER_CHUNK; |
| 38108 | | - } |
| 38109 | | - pEntry = p->pFresh++; |
| 38110 | | - p->nFresh--; |
| 38139 | + |
| 38140 | + /* This routine is never called after sqlite3RowSetNext() */ |
| 38141 | + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); |
| 38142 | + |
| 38143 | + pEntry = rowSetEntryAlloc(p); |
| 38144 | + if( pEntry==0 ) return; |
| 38111 | 38145 | pEntry->v = rowid; |
| 38112 | 38146 | pEntry->pRight = 0; |
| 38113 | 38147 | pLast = p->pLast; |
| 38114 | 38148 | if( pLast ){ |
| 38115 | | - if( p->isSorted && rowid<=pLast->v ){ |
| 38116 | | - p->isSorted = 0; |
| 38149 | + if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ |
| 38150 | + p->rsFlags &= ~ROWSET_SORTED; |
| 38117 | 38151 | } |
| 38118 | 38152 | pLast->pRight = pEntry; |
| 38119 | 38153 | }else{ |
| 38120 | | - assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */ |
| 38121 | 38154 | p->pEntry = pEntry; |
| 38122 | 38155 | } |
| 38123 | 38156 | p->pLast = pEntry; |
| 38124 | 38157 | } |
| 38125 | 38158 | |
| | @@ -38127,11 +38160,11 @@ |
| 38127 | 38160 | ** Merge two lists of RowSetEntry objects. Remove duplicates. |
| 38128 | 38161 | ** |
| 38129 | 38162 | ** The input lists are connected via pRight pointers and are |
| 38130 | 38163 | ** assumed to each already be in sorted order. |
| 38131 | 38164 | */ |
| 38132 | | -static struct RowSetEntry *rowSetMerge( |
| 38165 | +static struct RowSetEntry *rowSetEntryMerge( |
| 38133 | 38166 | struct RowSetEntry *pA, /* First sorted list to be merged */ |
| 38134 | 38167 | struct RowSetEntry *pB /* Second sorted list to be merged */ |
| 38135 | 38168 | ){ |
| 38136 | 38169 | struct RowSetEntry head; |
| 38137 | 38170 | struct RowSetEntry *pTail; |
| | @@ -38161,36 +38194,33 @@ |
| 38161 | 38194 | } |
| 38162 | 38195 | return head.pRight; |
| 38163 | 38196 | } |
| 38164 | 38197 | |
| 38165 | 38198 | /* |
| 38166 | | -** Sort all elements on the pEntry list of the RowSet into ascending order. |
| 38199 | +** Sort all elements on the list of RowSetEntry objects into order of |
| 38200 | +** increasing v. |
| 38167 | 38201 | */ |
| 38168 | | -static void rowSetSort(RowSet *p){ |
| 38202 | +static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ |
| 38169 | 38203 | unsigned int i; |
| 38170 | | - struct RowSetEntry *pEntry; |
| 38171 | | - struct RowSetEntry *aBucket[40]; |
| 38204 | + struct RowSetEntry *pNext, *aBucket[40]; |
| 38172 | 38205 | |
| 38173 | | - assert( p->isSorted==0 ); |
| 38174 | 38206 | memset(aBucket, 0, sizeof(aBucket)); |
| 38175 | | - while( p->pEntry ){ |
| 38176 | | - pEntry = p->pEntry; |
| 38177 | | - p->pEntry = pEntry->pRight; |
| 38178 | | - pEntry->pRight = 0; |
| 38207 | + while( pIn ){ |
| 38208 | + pNext = pIn->pRight; |
| 38209 | + pIn->pRight = 0; |
| 38179 | 38210 | for(i=0; aBucket[i]; i++){ |
| 38180 | | - pEntry = rowSetMerge(aBucket[i], pEntry); |
| 38211 | + pIn = rowSetEntryMerge(aBucket[i], pIn); |
| 38181 | 38212 | aBucket[i] = 0; |
| 38182 | 38213 | } |
| 38183 | | - aBucket[i] = pEntry; |
| 38214 | + aBucket[i] = pIn; |
| 38215 | + pIn = pNext; |
| 38184 | 38216 | } |
| 38185 | | - pEntry = 0; |
| 38217 | + pIn = 0; |
| 38186 | 38218 | for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){ |
| 38187 | | - pEntry = rowSetMerge(pEntry, aBucket[i]); |
| 38219 | + pIn = rowSetEntryMerge(pIn, aBucket[i]); |
| 38188 | 38220 | } |
| 38189 | | - p->pEntry = pEntry; |
| 38190 | | - p->pLast = 0; |
| 38191 | | - p->isSorted = 1; |
| 38221 | + return pIn; |
| 38192 | 38222 | } |
| 38193 | 38223 | |
| 38194 | 38224 | |
| 38195 | 38225 | /* |
| 38196 | 38226 | ** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects. |
| | @@ -38280,24 +38310,41 @@ |
| 38280 | 38310 | } |
| 38281 | 38311 | return p; |
| 38282 | 38312 | } |
| 38283 | 38313 | |
| 38284 | 38314 | /* |
| 38285 | | -** Convert the list in p->pEntry into a sorted list if it is not |
| 38286 | | -** sorted already. If there is a binary tree on p->pTree, then |
| 38287 | | -** convert it into a list too and merge it into the p->pEntry list. |
| 38315 | +** Take all the entries on p->pEntry and on the trees in p->pForest and |
| 38316 | +** sort them all together into one big ordered list on p->pEntry. |
| 38317 | +** |
| 38318 | +** This routine should only be called once in the life of a RowSet. |
| 38288 | 38319 | */ |
| 38289 | 38320 | static void rowSetToList(RowSet *p){ |
| 38290 | | - if( !p->isSorted ){ |
| 38291 | | - rowSetSort(p); |
| 38292 | | - } |
| 38293 | | - if( p->pTree ){ |
| 38294 | | - struct RowSetEntry *pHead, *pTail; |
| 38295 | | - rowSetTreeToList(p->pTree, &pHead, &pTail); |
| 38296 | | - p->pTree = 0; |
| 38297 | | - p->pEntry = rowSetMerge(p->pEntry, pHead); |
| 38298 | | - } |
| 38321 | + |
| 38322 | + /* This routine is called only once */ |
| 38323 | + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); |
| 38324 | + |
| 38325 | + if( (p->rsFlags & ROWSET_SORTED)==0 ){ |
| 38326 | + p->pEntry = rowSetEntrySort(p->pEntry); |
| 38327 | + } |
| 38328 | + |
| 38329 | + /* While this module could theoretically support it, sqlite3RowSetNext() |
| 38330 | + ** is never called after sqlite3RowSetText() for the same RowSet. So |
| 38331 | + ** there is never a forest to deal with. Should this change, simply |
| 38332 | + ** remove the assert() and the #if 0. */ |
| 38333 | + assert( p->pForest==0 ); |
| 38334 | +#if 0 |
| 38335 | + while( p->pForest ){ |
| 38336 | + struct RowSetEntry *pTree = p->pForest->pLeft; |
| 38337 | + if( pTree ){ |
| 38338 | + struct RowSetEntry *pHead, *pTail; |
| 38339 | + rowSetTreeToList(pTree, &pHead, &pTail); |
| 38340 | + p->pEntry = rowSetEntryMerge(p->pEntry, pHead); |
| 38341 | + } |
| 38342 | + p->pForest = p->pForest->pRight; |
| 38343 | + } |
| 38344 | +#endif |
| 38345 | + p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ |
| 38299 | 38346 | } |
| 38300 | 38347 | |
| 38301 | 38348 | /* |
| 38302 | 38349 | ** Extract the smallest element from the RowSet. |
| 38303 | 38350 | ** Write the element into *pRowid. Return 1 on success. Return |
| | @@ -38305,11 +38352,16 @@ |
| 38305 | 38352 | ** |
| 38306 | 38353 | ** After this routine has been called, the sqlite3RowSetInsert() |
| 38307 | 38354 | ** routine may not be called again. |
| 38308 | 38355 | */ |
| 38309 | 38356 | SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ |
| 38310 | | - rowSetToList(p); |
| 38357 | + assert( p!=0 ); |
| 38358 | + |
| 38359 | + /* Merge the forest into a single sorted list on first call */ |
| 38360 | + if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); |
| 38361 | + |
| 38362 | + /* Return the next entry on the list */ |
| 38311 | 38363 | if( p->pEntry ){ |
| 38312 | 38364 | *pRowid = p->pEntry->v; |
| 38313 | 38365 | p->pEntry = p->pEntry->pRight; |
| 38314 | 38366 | if( p->pEntry==0 ){ |
| 38315 | 38367 | sqlite3RowSetClear(p); |
| | @@ -38321,30 +38373,70 @@ |
| 38321 | 38373 | } |
| 38322 | 38374 | |
| 38323 | 38375 | /* |
| 38324 | 38376 | ** Check to see if element iRowid was inserted into the the rowset as |
| 38325 | 38377 | ** part of any insert batch prior to iBatch. Return 1 or 0. |
| 38378 | +** |
| 38379 | +** If this is the first test of a new batch and if there exist entires |
| 38380 | +** on pRowSet->pEntry, then sort those entires into the forest at |
| 38381 | +** pRowSet->pForest so that they can be tested. |
| 38326 | 38382 | */ |
| 38327 | 38383 | SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ |
| 38328 | | - struct RowSetEntry *p; |
| 38384 | + struct RowSetEntry *p, *pTree; |
| 38385 | + |
| 38386 | + /* This routine is never called after sqlite3RowSetNext() */ |
| 38387 | + assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); |
| 38388 | + |
| 38389 | + /* Sort entries into the forest on the first test of a new batch |
| 38390 | + */ |
| 38329 | 38391 | if( iBatch!=pRowSet->iBatch ){ |
| 38330 | | - if( pRowSet->pEntry ){ |
| 38331 | | - rowSetToList(pRowSet); |
| 38332 | | - pRowSet->pTree = rowSetListToTree(pRowSet->pEntry); |
| 38392 | + p = pRowSet->pEntry; |
| 38393 | + if( p ){ |
| 38394 | + struct RowSetEntry **ppPrevTree = &pRowSet->pForest; |
| 38395 | + if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ |
| 38396 | + p = rowSetEntrySort(p); |
| 38397 | + } |
| 38398 | + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ |
| 38399 | + ppPrevTree = &pTree->pRight; |
| 38400 | + if( pTree->pLeft==0 ){ |
| 38401 | + pTree->pLeft = rowSetListToTree(p); |
| 38402 | + break; |
| 38403 | + }else{ |
| 38404 | + struct RowSetEntry *pAux, *pTail; |
| 38405 | + rowSetTreeToList(pTree->pLeft, &pAux, &pTail); |
| 38406 | + pTree->pLeft = 0; |
| 38407 | + p = rowSetEntryMerge(pAux, p); |
| 38408 | + } |
| 38409 | + } |
| 38410 | + if( pTree==0 ){ |
| 38411 | + *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); |
| 38412 | + if( pTree ){ |
| 38413 | + pTree->v = 0; |
| 38414 | + pTree->pRight = 0; |
| 38415 | + pTree->pLeft = rowSetListToTree(p); |
| 38416 | + } |
| 38417 | + } |
| 38333 | 38418 | pRowSet->pEntry = 0; |
| 38334 | 38419 | pRowSet->pLast = 0; |
| 38420 | + pRowSet->rsFlags |= ROWSET_SORTED; |
| 38335 | 38421 | } |
| 38336 | 38422 | pRowSet->iBatch = iBatch; |
| 38337 | 38423 | } |
| 38338 | | - p = pRowSet->pTree; |
| 38339 | | - while( p ){ |
| 38340 | | - if( p->v<iRowid ){ |
| 38341 | | - p = p->pRight; |
| 38342 | | - }else if( p->v>iRowid ){ |
| 38343 | | - p = p->pLeft; |
| 38344 | | - }else{ |
| 38345 | | - return 1; |
| 38424 | + |
| 38425 | + /* Test to see if the iRowid value appears anywhere in the forest. |
| 38426 | + ** Return 1 if it does and 0 if not. |
| 38427 | + */ |
| 38428 | + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ |
| 38429 | + p = pTree->pLeft; |
| 38430 | + while( p ){ |
| 38431 | + if( p->v<iRowid ){ |
| 38432 | + p = p->pRight; |
| 38433 | + }else if( p->v>iRowid ){ |
| 38434 | + p = p->pLeft; |
| 38435 | + }else{ |
| 38436 | + return 1; |
| 38437 | + } |
| 38346 | 38438 | } |
| 38347 | 38439 | } |
| 38348 | 38440 | return 0; |
| 38349 | 38441 | } |
| 38350 | 38442 | |
| | @@ -49148,16 +49240,22 @@ |
| 49148 | 49240 | |
| 49149 | 49241 | |
| 49150 | 49242 | /* |
| 49151 | 49243 | ** This structure is passed around through all the sanity checking routines |
| 49152 | 49244 | ** in order to keep track of some global state information. |
| 49245 | +** |
| 49246 | +** The aRef[] array is allocated so that there is 1 bit for each page in |
| 49247 | +** the database. As the integrity-check proceeds, for each page used in |
| 49248 | +** the database the corresponding bit is set. This allows integrity-check to |
| 49249 | +** detect pages that are used twice and orphaned pages (both of which |
| 49250 | +** indicate corruption). |
| 49153 | 49251 | */ |
| 49154 | 49252 | typedef struct IntegrityCk IntegrityCk; |
| 49155 | 49253 | struct IntegrityCk { |
| 49156 | 49254 | BtShared *pBt; /* The tree being checked out */ |
| 49157 | 49255 | Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ |
| 49158 | | - int *anRef; /* Number of times each page is referenced */ |
| 49256 | + u8 *aPgRef; /* 1 bit per page in the db (see above) */ |
| 49159 | 49257 | Pgno nPage; /* Number of pages in the database */ |
| 49160 | 49258 | int mxErr; /* Stop accumulating errors when this reaches zero */ |
| 49161 | 49259 | int nErr; /* Number of messages written to zErrMsg so far */ |
| 49162 | 49260 | int mallocFailed; /* A memory allocation error has occurred */ |
| 49163 | 49261 | StrAccum errMsg; /* Accumulate the error message text here */ |
| | @@ -56998,10 +57096,29 @@ |
| 56998 | 57096 | } |
| 56999 | 57097 | } |
| 57000 | 57098 | #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ |
| 57001 | 57099 | |
| 57002 | 57100 | #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
| 57101 | + |
| 57102 | +/* |
| 57103 | +** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that |
| 57104 | +** corresponds to page iPg is already set. |
| 57105 | +*/ |
| 57106 | +static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ |
| 57107 | + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); |
| 57108 | + return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); |
| 57109 | +} |
| 57110 | + |
| 57111 | +/* |
| 57112 | +** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. |
| 57113 | +*/ |
| 57114 | +static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ |
| 57115 | + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); |
| 57116 | + pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); |
| 57117 | +} |
| 57118 | + |
| 57119 | + |
| 57003 | 57120 | /* |
| 57004 | 57121 | ** Add 1 to the reference count for page iPage. If this is the second |
| 57005 | 57122 | ** reference to the page, add an error message to pCheck->zErrMsg. |
| 57006 | 57123 | ** Return 1 if there are 2 ore more references to the page and 0 if |
| 57007 | 57124 | ** if this is the first reference to the page. |
| | @@ -57012,15 +57129,16 @@ |
| 57012 | 57129 | if( iPage==0 ) return 1; |
| 57013 | 57130 | if( iPage>pCheck->nPage ){ |
| 57014 | 57131 | checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); |
| 57015 | 57132 | return 1; |
| 57016 | 57133 | } |
| 57017 | | - if( pCheck->anRef[iPage]==1 ){ |
| 57134 | + if( getPageReferenced(pCheck, iPage) ){ |
| 57018 | 57135 | checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); |
| 57019 | 57136 | return 1; |
| 57020 | 57137 | } |
| 57021 | | - return (pCheck->anRef[iPage]++)>1; |
| 57138 | + setPageReferenced(pCheck, iPage); |
| 57139 | + return 0; |
| 57022 | 57140 | } |
| 57023 | 57141 | |
| 57024 | 57142 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 57025 | 57143 | /* |
| 57026 | 57144 | ** Check that the entry in the pointer-map for page iChild maps to |
| | @@ -57392,21 +57510,19 @@ |
| 57392 | 57510 | *pnErr = 0; |
| 57393 | 57511 | if( sCheck.nPage==0 ){ |
| 57394 | 57512 | sqlite3BtreeLeave(p); |
| 57395 | 57513 | return 0; |
| 57396 | 57514 | } |
| 57397 | | - sCheck.anRef = sqlite3Malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); |
| 57398 | | - if( !sCheck.anRef ){ |
| 57515 | + |
| 57516 | + sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); |
| 57517 | + if( !sCheck.aPgRef ){ |
| 57399 | 57518 | *pnErr = 1; |
| 57400 | 57519 | sqlite3BtreeLeave(p); |
| 57401 | 57520 | return 0; |
| 57402 | 57521 | } |
| 57403 | | - for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } |
| 57404 | 57522 | i = PENDING_BYTE_PAGE(pBt); |
| 57405 | | - if( i<=sCheck.nPage ){ |
| 57406 | | - sCheck.anRef[i] = 1; |
| 57407 | | - } |
| 57523 | + if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 57408 | 57524 | sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); |
| 57409 | 57525 | sCheck.errMsg.useMalloc = 2; |
| 57410 | 57526 | |
| 57411 | 57527 | /* Check the integrity of the freelist |
| 57412 | 57528 | */ |
| | @@ -57427,22 +57543,22 @@ |
| 57427 | 57543 | |
| 57428 | 57544 | /* Make sure every page in the file is referenced |
| 57429 | 57545 | */ |
| 57430 | 57546 | for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ |
| 57431 | 57547 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 57432 | | - if( sCheck.anRef[i]==0 ){ |
| 57548 | + if( getPageReferenced(&sCheck, i)==0 ){ |
| 57433 | 57549 | checkAppendMsg(&sCheck, 0, "Page %d is never used", i); |
| 57434 | 57550 | } |
| 57435 | 57551 | #else |
| 57436 | 57552 | /* If the database supports auto-vacuum, make sure no tables contain |
| 57437 | 57553 | ** references to pointer-map pages. |
| 57438 | 57554 | */ |
| 57439 | | - if( sCheck.anRef[i]==0 && |
| 57555 | + if( getPageReferenced(&sCheck, i)==0 && |
| 57440 | 57556 | (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ |
| 57441 | 57557 | checkAppendMsg(&sCheck, 0, "Page %d is never used", i); |
| 57442 | 57558 | } |
| 57443 | | - if( sCheck.anRef[i]!=0 && |
| 57559 | + if( getPageReferenced(&sCheck, i)!=0 && |
| 57444 | 57560 | (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ |
| 57445 | 57561 | checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); |
| 57446 | 57562 | } |
| 57447 | 57563 | #endif |
| 57448 | 57564 | } |
| | @@ -57459,11 +57575,11 @@ |
| 57459 | 57575 | } |
| 57460 | 57576 | |
| 57461 | 57577 | /* Clean up and report errors. |
| 57462 | 57578 | */ |
| 57463 | 57579 | sqlite3BtreeLeave(p); |
| 57464 | | - sqlite3_free(sCheck.anRef); |
| 57580 | + sqlite3_free(sCheck.aPgRef); |
| 57465 | 57581 | if( sCheck.mallocFailed ){ |
| 57466 | 57582 | sqlite3StrAccumReset(&sCheck.errMsg); |
| 57467 | 57583 | *pnErr = sCheck.nErr+1; |
| 57468 | 57584 | return 0; |
| 57469 | 57585 | } |
| | @@ -73807,11 +73923,11 @@ |
| 73807 | 73923 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73808 | 73924 | zId = pExpr->u.zToken; |
| 73809 | 73925 | nId = sqlite3Strlen30(zId); |
| 73810 | 73926 | pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); |
| 73811 | 73927 | if( pDef==0 ){ |
| 73812 | | - pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); |
| 73928 | + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); |
| 73813 | 73929 | if( pDef==0 ){ |
| 73814 | 73930 | no_such_func = 1; |
| 73815 | 73931 | }else{ |
| 73816 | 73932 | wrong_num_args = 1; |
| 73817 | 73933 | } |
| | @@ -78277,11 +78393,11 @@ |
| 78277 | 78393 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 78278 | 78394 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| 78279 | 78395 | if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ |
| 78280 | 78396 | return 2; |
| 78281 | 78397 | } |
| 78282 | | - }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ |
| 78398 | + }else if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ |
| 78283 | 78399 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 78284 | 78400 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 78285 | 78401 | return 2; |
| 78286 | 78402 | } |
| 78287 | 78403 | } |
| | @@ -78313,10 +78429,45 @@ |
| 78313 | 78429 | if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; |
| 78314 | 78430 | if( sqlite3ExprCompare(pExprA, pExprB) ) return 1; |
| 78315 | 78431 | } |
| 78316 | 78432 | return 0; |
| 78317 | 78433 | } |
| 78434 | + |
| 78435 | +/* |
| 78436 | +** This is the expression callback for sqlite3FunctionUsesOtherSrc(). |
| 78437 | +** |
| 78438 | +** Determine if an expression references any table other than one of the |
| 78439 | +** tables in pWalker->u.pSrcList and abort if it does. |
| 78440 | +*/ |
| 78441 | +static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ |
| 78442 | + if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ |
| 78443 | + int i; |
| 78444 | + SrcList *pSrc = pWalker->u.pSrcList; |
| 78445 | + for(i=0; i<pSrc->nSrc; i++){ |
| 78446 | + if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue; |
| 78447 | + } |
| 78448 | + return WRC_Abort; |
| 78449 | + }else{ |
| 78450 | + return WRC_Continue; |
| 78451 | + } |
| 78452 | +} |
| 78453 | + |
| 78454 | +/* |
| 78455 | +** Determine if any of the arguments to the pExpr Function references |
| 78456 | +** any SrcList other than pSrcList. Return true if they do. Return |
| 78457 | +** false if pExpr has no argument or has only constant arguments or |
| 78458 | +** only references tables named in pSrcList. |
| 78459 | +*/ |
| 78460 | +static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){ |
| 78461 | + Walker w; |
| 78462 | + assert( pExpr->op==TK_AGG_FUNCTION ); |
| 78463 | + memset(&w, 0, sizeof(w)); |
| 78464 | + w.xExprCallback = exprUsesOtherSrc; |
| 78465 | + w.u.pSrcList = pSrcList; |
| 78466 | + if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1; |
| 78467 | + return 0; |
| 78468 | +} |
| 78318 | 78469 | |
| 78319 | 78470 | /* |
| 78320 | 78471 | ** Add a new element to the pAggInfo->aCol[] array. Return the index of |
| 78321 | 78472 | ** the new element. Return a negative number if malloc fails. |
| 78322 | 78473 | */ |
| | @@ -78429,13 +78580,11 @@ |
| 78429 | 78580 | } /* end loop over pSrcList */ |
| 78430 | 78581 | } |
| 78431 | 78582 | return WRC_Prune; |
| 78432 | 78583 | } |
| 78433 | 78584 | case TK_AGG_FUNCTION: { |
| 78434 | | - /* The pNC->nDepth==0 test causes aggregate functions in subqueries |
| 78435 | | - ** to be ignored */ |
| 78436 | | - if( pNC->nDepth==0 ){ |
| 78585 | + if( !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) ){ |
| 78437 | 78586 | /* Check to see if pExpr is a duplicate of another aggregate |
| 78438 | 78587 | ** function that is already in the pAggInfo structure |
| 78439 | 78588 | */ |
| 78440 | 78589 | struct AggInfo_func *pItem = pAggInfo->aFunc; |
| 78441 | 78590 | for(i=0; i<pAggInfo->nFunc; i++, pItem++){ |
| | @@ -78475,19 +78624,11 @@ |
| 78475 | 78624 | } |
| 78476 | 78625 | } |
| 78477 | 78626 | return WRC_Continue; |
| 78478 | 78627 | } |
| 78479 | 78628 | static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ |
| 78480 | | - NameContext *pNC = pWalker->u.pNC; |
| 78481 | | - if( pNC->nDepth==0 ){ |
| 78482 | | - pNC->nDepth++; |
| 78483 | | - sqlite3WalkSelect(pWalker, pSelect); |
| 78484 | | - pNC->nDepth--; |
| 78485 | | - return WRC_Prune; |
| 78486 | | - }else{ |
| 78487 | | - return WRC_Continue; |
| 78488 | | - } |
| 78629 | + return WRC_Continue; |
| 78489 | 78630 | } |
| 78490 | 78631 | |
| 78491 | 78632 | /* |
| 78492 | 78633 | ** Analyze the given expression looking for aggregate functions and |
| 78493 | 78634 | ** for variables that need to be added to the pParse->aAgg[] array. |
| | @@ -78496,10 +78637,11 @@ |
| 78496 | 78637 | ** This routine should only be called after the expression has been |
| 78497 | 78638 | ** analyzed by sqlite3ResolveExprNames(). |
| 78498 | 78639 | */ |
| 78499 | 78640 | SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ |
| 78500 | 78641 | Walker w; |
| 78642 | + memset(&w, 0, sizeof(w)); |
| 78501 | 78643 | w.xExprCallback = analyzeAggregate; |
| 78502 | 78644 | w.xSelectCallback = analyzeAggregatesInSelect; |
| 78503 | 78645 | w.u.pNC = pNC; |
| 78504 | 78646 | assert( pNC->pSrcList!=0 ); |
| 78505 | 78647 | sqlite3WalkExpr(&w, pExpr); |
| | @@ -85399,43 +85541,62 @@ |
| 85399 | 85541 | /* During the search for the best function definition, this procedure |
| 85400 | 85542 | ** is called to test how well the function passed as the first argument |
| 85401 | 85543 | ** matches the request for a function with nArg arguments in a system |
| 85402 | 85544 | ** that uses encoding enc. The value returned indicates how well the |
| 85403 | 85545 | ** request is matched. A higher value indicates a better match. |
| 85546 | +** |
| 85547 | +** If nArg is -1 that means to only return a match (non-zero) if p->nArg |
| 85548 | +** is also -1. In other words, we are searching for a function that |
| 85549 | +** takes a variable number of arguments. |
| 85550 | +** |
| 85551 | +** If nArg is -2 that means that we are searching for any function |
| 85552 | +** regardless of the number of arguments it uses, so return a positive |
| 85553 | +** match score for any |
| 85404 | 85554 | ** |
| 85405 | 85555 | ** The returned value is always between 0 and 6, as follows: |
| 85406 | 85556 | ** |
| 85407 | | -** 0: Not a match, or if nArg<0 and the function is has no implementation. |
| 85408 | | -** 1: A variable arguments function that prefers UTF-8 when a UTF-16 |
| 85409 | | -** encoding is requested, or vice versa. |
| 85410 | | -** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is |
| 85411 | | -** requested, or vice versa. |
| 85412 | | -** 3: A variable arguments function using the same text encoding. |
| 85413 | | -** 4: A function with the exact number of arguments requested that |
| 85414 | | -** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. |
| 85415 | | -** 5: A function with the exact number of arguments requested that |
| 85416 | | -** prefers UTF-16LE when UTF-16BE is requested, or vice versa. |
| 85417 | | -** 6: An exact match. |
| 85557 | +** 0: Not a match. |
| 85558 | +** 1: UTF8/16 conversion required and function takes any number of arguments. |
| 85559 | +** 2: UTF16 byte order change required and function takes any number of args. |
| 85560 | +** 3: encoding matches and function takes any number of arguments |
| 85561 | +** 4: UTF8/16 conversion required - argument count matches exactly |
| 85562 | +** 5: UTF16 byte order conversion required - argument count matches exactly |
| 85563 | +** 6: Perfect match: encoding and argument count match exactly. |
| 85418 | 85564 | ** |
| 85565 | +** If nArg==(-2) then any function with a non-null xStep or xFunc is |
| 85566 | +** a perfect match and any function with both xStep and xFunc NULL is |
| 85567 | +** a non-match. |
| 85419 | 85568 | */ |
| 85420 | | -static int matchQuality(FuncDef *p, int nArg, u8 enc){ |
| 85421 | | - int match = 0; |
| 85422 | | - if( p->nArg==-1 || p->nArg==nArg |
| 85423 | | - || (nArg==-1 && (p->xFunc!=0 || p->xStep!=0)) |
| 85424 | | - ){ |
| 85569 | +#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ |
| 85570 | +static int matchQuality( |
| 85571 | + FuncDef *p, /* The function we are evaluating for match quality */ |
| 85572 | + int nArg, /* Desired number of arguments. (-1)==any */ |
| 85573 | + u8 enc /* Desired text encoding */ |
| 85574 | +){ |
| 85575 | + int match; |
| 85576 | + |
| 85577 | + /* nArg of -2 is a special case */ |
| 85578 | + if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH; |
| 85579 | + |
| 85580 | + /* Wrong number of arguments means "no match" */ |
| 85581 | + if( p->nArg!=nArg && p->nArg>=0 ) return 0; |
| 85582 | + |
| 85583 | + /* Give a better score to a function with a specific number of arguments |
| 85584 | + ** than to function that accepts any number of arguments. */ |
| 85585 | + if( p->nArg==nArg ){ |
| 85586 | + match = 4; |
| 85587 | + }else{ |
| 85425 | 85588 | match = 1; |
| 85426 | | - if( p->nArg==nArg || nArg==-1 ){ |
| 85427 | | - match = 4; |
| 85428 | | - } |
| 85429 | | - if( enc==p->iPrefEnc ){ |
| 85430 | | - match += 2; |
| 85431 | | - } |
| 85432 | | - else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || |
| 85433 | | - (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ |
| 85434 | | - match += 1; |
| 85435 | | - } |
| 85436 | | - } |
| 85589 | + } |
| 85590 | + |
| 85591 | + /* Bonus points if the text encoding matches */ |
| 85592 | + if( enc==p->iPrefEnc ){ |
| 85593 | + match += 2; /* Exact encoding match */ |
| 85594 | + }else if( (enc & p->iPrefEnc & 2)!=0 ){ |
| 85595 | + match += 1; /* Both are UTF16, but with different byte orders */ |
| 85596 | + } |
| 85597 | + |
| 85437 | 85598 | return match; |
| 85438 | 85599 | } |
| 85439 | 85600 | |
| 85440 | 85601 | /* |
| 85441 | 85602 | ** Search a FuncDefHash for a function with the given name. Return |
| | @@ -85487,17 +85648,16 @@ |
| 85487 | 85648 | ** pointer to the FuncDef structure that defines that function, or return |
| 85488 | 85649 | ** NULL if the function does not exist. |
| 85489 | 85650 | ** |
| 85490 | 85651 | ** If the createFlag argument is true, then a new (blank) FuncDef |
| 85491 | 85652 | ** structure is created and liked into the "db" structure if a |
| 85492 | | -** no matching function previously existed. When createFlag is true |
| 85493 | | -** and the nArg parameter is -1, then only a function that accepts |
| 85494 | | -** any number of arguments will be returned. |
| 85653 | +** no matching function previously existed. |
| 85495 | 85654 | ** |
| 85496 | | -** If createFlag is false and nArg is -1, then the first valid |
| 85497 | | -** function found is returned. A function is valid if either xFunc |
| 85498 | | -** or xStep is non-zero. |
| 85655 | +** If nArg is -2, then the first valid function found is returned. A |
| 85656 | +** function is valid if either xFunc or xStep is non-zero. The nArg==(-2) |
| 85657 | +** case is used to see if zName is a valid function name for some number |
| 85658 | +** of arguments. If nArg is -2, then createFlag must be 0. |
| 85499 | 85659 | ** |
| 85500 | 85660 | ** If createFlag is false, then a function with the required name and |
| 85501 | 85661 | ** number of arguments may be returned even if the eTextRep flag does not |
| 85502 | 85662 | ** match that requested. |
| 85503 | 85663 | */ |
| | @@ -85505,18 +85665,19 @@ |
| 85505 | 85665 | sqlite3 *db, /* An open database */ |
| 85506 | 85666 | const char *zName, /* Name of the function. Not null-terminated */ |
| 85507 | 85667 | int nName, /* Number of characters in the name */ |
| 85508 | 85668 | int nArg, /* Number of arguments. -1 means any number */ |
| 85509 | 85669 | u8 enc, /* Preferred text encoding */ |
| 85510 | | - int createFlag /* Create new entry if true and does not otherwise exist */ |
| 85670 | + u8 createFlag /* Create new entry if true and does not otherwise exist */ |
| 85511 | 85671 | ){ |
| 85512 | 85672 | FuncDef *p; /* Iterator variable */ |
| 85513 | 85673 | FuncDef *pBest = 0; /* Best match found so far */ |
| 85514 | 85674 | int bestScore = 0; /* Score of best match */ |
| 85515 | 85675 | int h; /* Hash value */ |
| 85516 | 85676 | |
| 85517 | | - |
| 85677 | + assert( nArg>=(-2) ); |
| 85678 | + assert( nArg>=(-1) || createFlag==0 ); |
| 85518 | 85679 | assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); |
| 85519 | 85680 | h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); |
| 85520 | 85681 | |
| 85521 | 85682 | /* First search for a match amongst the application-defined functions. |
| 85522 | 85683 | */ |
| | @@ -85558,11 +85719,11 @@ |
| 85558 | 85719 | |
| 85559 | 85720 | /* If the createFlag parameter is true and the search did not reveal an |
| 85560 | 85721 | ** exact match for the name, number of arguments and encoding, then add a |
| 85561 | 85722 | ** new entry to the hash table and return it. |
| 85562 | 85723 | */ |
| 85563 | | - if( createFlag && (bestScore<6 || pBest->nArg!=nArg) && |
| 85724 | + if( createFlag && bestScore<FUNC_PERFECT_MATCH && |
| 85564 | 85725 | (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ |
| 85565 | 85726 | pBest->zName = (char *)&pBest[1]; |
| 85566 | 85727 | pBest->nArg = (u16)nArg; |
| 85567 | 85728 | pBest->iPrefEnc = enc; |
| 85568 | 85729 | memcpy(pBest->zName, zName, nName); |
| | @@ -97526,11 +97687,12 @@ |
| 97526 | 97687 | |
| 97527 | 97688 | /***** If we reach this point, flattening is permitted. *****/ |
| 97528 | 97689 | |
| 97529 | 97690 | /* Authorize the subquery */ |
| 97530 | 97691 | pParse->zAuthContext = pSubitem->zName; |
| 97531 | | - sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); |
| 97692 | + TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); |
| 97693 | + testcase( i==SQLITE_DENY ); |
| 97532 | 97694 | pParse->zAuthContext = zSavedAuthContext; |
| 97533 | 97695 | |
| 97534 | 97696 | /* If the sub-query is a compound SELECT statement, then (by restrictions |
| 97535 | 97697 | ** 17 and 18 above) it must be a UNION ALL and the parent query must |
| 97536 | 97698 | ** be of the form: |
| | @@ -129049,11 +129211,10 @@ |
| 129049 | 129211 | /* Advance to the next output block */ |
| 129050 | 129212 | pLeaf->iBlock++; |
| 129051 | 129213 | pLeaf->key.n = 0; |
| 129052 | 129214 | pLeaf->block.n = 0; |
| 129053 | 129215 | |
| 129054 | | - nPrefix = 0; |
| 129055 | 129216 | nSuffix = nTerm; |
| 129056 | 129217 | nSpace = 1; |
| 129057 | 129218 | nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; |
| 129058 | 129219 | nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; |
| 129059 | 129220 | } |
| | @@ -132384,10 +132545,23 @@ |
| 132384 | 132545 | |
| 132385 | 132546 | /* Possible values for eCoordType: */ |
| 132386 | 132547 | #define RTREE_COORD_REAL32 0 |
| 132387 | 132548 | #define RTREE_COORD_INT32 1 |
| 132388 | 132549 | |
| 132550 | +/* |
| 132551 | +** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will |
| 132552 | +** only deal with integer coordinates. No floating point operations |
| 132553 | +** will be done. |
| 132554 | +*/ |
| 132555 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 132556 | + typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ |
| 132557 | + typedef int RtreeValue; /* Low accuracy coordinate */ |
| 132558 | +#else |
| 132559 | + typedef double RtreeDValue; /* High accuracy coordinate */ |
| 132560 | + typedef float RtreeValue; /* Low accuracy coordinate */ |
| 132561 | +#endif |
| 132562 | + |
| 132389 | 132563 | /* |
| 132390 | 132564 | ** The minimum number of cells allowed for a node is a third of the |
| 132391 | 132565 | ** maximum. In Gutman's notation: |
| 132392 | 132566 | ** |
| 132393 | 132567 | ** m = M/3 |
| | @@ -132419,33 +132593,38 @@ |
| 132419 | 132593 | int nConstraint; /* Number of entries in aConstraint */ |
| 132420 | 132594 | RtreeConstraint *aConstraint; /* Search constraints. */ |
| 132421 | 132595 | }; |
| 132422 | 132596 | |
| 132423 | 132597 | union RtreeCoord { |
| 132424 | | - float f; |
| 132598 | + RtreeValue f; |
| 132425 | 132599 | int i; |
| 132426 | 132600 | }; |
| 132427 | 132601 | |
| 132428 | 132602 | /* |
| 132429 | 132603 | ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord |
| 132430 | | -** formatted as a double. This macro assumes that local variable pRtree points |
| 132431 | | -** to the Rtree structure associated with the RtreeCoord. |
| 132604 | +** formatted as a RtreeDValue (double or int64). This macro assumes that local |
| 132605 | +** variable pRtree points to the Rtree structure associated with the |
| 132606 | +** RtreeCoord. |
| 132432 | 132607 | */ |
| 132433 | | -#define DCOORD(coord) ( \ |
| 132434 | | - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ |
| 132435 | | - ((double)coord.f) : \ |
| 132436 | | - ((double)coord.i) \ |
| 132437 | | -) |
| 132608 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 132609 | +# define DCOORD(coord) ((RtreeDValue)coord.i) |
| 132610 | +#else |
| 132611 | +# define DCOORD(coord) ( \ |
| 132612 | + (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ |
| 132613 | + ((double)coord.f) : \ |
| 132614 | + ((double)coord.i) \ |
| 132615 | + ) |
| 132616 | +#endif |
| 132438 | 132617 | |
| 132439 | 132618 | /* |
| 132440 | 132619 | ** A search constraint. |
| 132441 | 132620 | */ |
| 132442 | 132621 | struct RtreeConstraint { |
| 132443 | 132622 | int iCoord; /* Index of constrained coordinate */ |
| 132444 | 132623 | int op; /* Constraining operation */ |
| 132445 | | - double rValue; /* Constraint value. */ |
| 132446 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 132624 | + RtreeDValue rValue; /* Constraint value. */ |
| 132625 | + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); |
| 132447 | 132626 | sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ |
| 132448 | 132627 | }; |
| 132449 | 132628 | |
| 132450 | 132629 | /* Possible values for RtreeConstraint.op */ |
| 132451 | 132630 | #define RTREE_EQ 0x41 |
| | @@ -132489,14 +132668,14 @@ |
| 132489 | 132668 | ** the right-hand-side of an SQL MATCH operator used to constrain an |
| 132490 | 132669 | ** r-tree query. |
| 132491 | 132670 | */ |
| 132492 | 132671 | struct RtreeMatchArg { |
| 132493 | 132672 | u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ |
| 132494 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 132673 | + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); |
| 132495 | 132674 | void *pContext; |
| 132496 | 132675 | int nParam; |
| 132497 | | - double aParam[1]; |
| 132676 | + RtreeDValue aParam[1]; |
| 132498 | 132677 | }; |
| 132499 | 132678 | |
| 132500 | 132679 | /* |
| 132501 | 132680 | ** When a geometry callback is created (see sqlite3_rtree_geometry_callback), |
| 132502 | 132681 | ** a single instance of the following structure is allocated. It is used |
| | @@ -132504,11 +132683,11 @@ |
| 132504 | 132683 | ** is eventually deleted by the destructor mechanism provided by |
| 132505 | 132684 | ** sqlite3_create_function_v2() (which is called by s_r_g_c() to create |
| 132506 | 132685 | ** the geometry callback function). |
| 132507 | 132686 | */ |
| 132508 | 132687 | struct RtreeGeomCallback { |
| 132509 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 132688 | + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); |
| 132510 | 132689 | void *pContext; |
| 132511 | 132690 | }; |
| 132512 | 132691 | |
| 132513 | 132692 | #ifndef MAX |
| 132514 | 132693 | # define MAX(x,y) ((x) < (y) ? (y) : (x)) |
| | @@ -133070,11 +133249,11 @@ |
| 133070 | 133249 | RtreeConstraint *pConstraint, /* MATCH constraint to test */ |
| 133071 | 133250 | RtreeCell *pCell, /* Cell to test */ |
| 133072 | 133251 | int *pbRes /* OUT: Test result */ |
| 133073 | 133252 | ){ |
| 133074 | 133253 | int i; |
| 133075 | | - double aCoord[RTREE_MAX_DIMENSIONS*2]; |
| 133254 | + RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; |
| 133076 | 133255 | int nCoord = pRtree->nDim*2; |
| 133077 | 133256 | |
| 133078 | 133257 | assert( pConstraint->op==RTREE_MATCH ); |
| 133079 | 133258 | assert( pConstraint->pGeom ); |
| 133080 | 133259 | |
| | @@ -133100,12 +133279,12 @@ |
| 133100 | 133279 | int rc = SQLITE_OK; |
| 133101 | 133280 | |
| 133102 | 133281 | nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
| 133103 | 133282 | for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ |
| 133104 | 133283 | RtreeConstraint *p = &pCursor->aConstraint[ii]; |
| 133105 | | - double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); |
| 133106 | | - double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); |
| 133284 | + RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); |
| 133285 | + RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); |
| 133107 | 133286 | |
| 133108 | 133287 | assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 133109 | 133288 | || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
| 133110 | 133289 | ); |
| 133111 | 133290 | |
| | @@ -133153,11 +133332,11 @@ |
| 133153 | 133332 | *pbEof = 0; |
| 133154 | 133333 | |
| 133155 | 133334 | nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
| 133156 | 133335 | for(ii=0; ii<pCursor->nConstraint; ii++){ |
| 133157 | 133336 | RtreeConstraint *p = &pCursor->aConstraint[ii]; |
| 133158 | | - double coord = DCOORD(cell.aCoord[p->iCoord]); |
| 133337 | + RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); |
| 133159 | 133338 | int res; |
| 133160 | 133339 | assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 133161 | 133340 | || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
| 133162 | 133341 | ); |
| 133163 | 133342 | switch( p->op ){ |
| | @@ -133351,13 +133530,16 @@ |
| 133351 | 133530 | i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); |
| 133352 | 133531 | sqlite3_result_int64(ctx, iRowid); |
| 133353 | 133532 | }else{ |
| 133354 | 133533 | RtreeCoord c; |
| 133355 | 133534 | nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); |
| 133535 | +#ifndef SQLITE_RTREE_INT_ONLY |
| 133356 | 133536 | if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ |
| 133357 | 133537 | sqlite3_result_double(ctx, c.f); |
| 133358 | | - }else{ |
| 133538 | + }else |
| 133539 | +#endif |
| 133540 | + { |
| 133359 | 133541 | assert( pRtree->eCoordType==RTREE_COORD_INT32 ); |
| 133360 | 133542 | sqlite3_result_int(ctx, c.i); |
| 133361 | 133543 | } |
| 133362 | 133544 | } |
| 133363 | 133545 | |
| | @@ -133400,11 +133582,11 @@ |
| 133400 | 133582 | if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; |
| 133401 | 133583 | |
| 133402 | 133584 | /* Check that the blob is roughly the right size. */ |
| 133403 | 133585 | nBlob = sqlite3_value_bytes(pValue); |
| 133404 | 133586 | if( nBlob<(int)sizeof(RtreeMatchArg) |
| 133405 | | - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 |
| 133587 | + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 |
| 133406 | 133588 | ){ |
| 133407 | 133589 | return SQLITE_ERROR; |
| 133408 | 133590 | } |
| 133409 | 133591 | |
| 133410 | 133592 | pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( |
| | @@ -133414,11 +133596,11 @@ |
| 133414 | 133596 | memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 133415 | 133597 | p = (RtreeMatchArg *)&pGeom[1]; |
| 133416 | 133598 | |
| 133417 | 133599 | memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 133418 | 133600 | if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 133419 | | - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) |
| 133601 | + || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) |
| 133420 | 133602 | ){ |
| 133421 | 133603 | sqlite3_free(pGeom); |
| 133422 | 133604 | return SQLITE_ERROR; |
| 133423 | 133605 | } |
| 133424 | 133606 | |
| | @@ -133486,11 +133668,15 @@ |
| 133486 | 133668 | rc = deserializeGeometry(argv[ii], p); |
| 133487 | 133669 | if( rc!=SQLITE_OK ){ |
| 133488 | 133670 | break; |
| 133489 | 133671 | } |
| 133490 | 133672 | }else{ |
| 133673 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 133674 | + p->rValue = sqlite3_value_int64(argv[ii]); |
| 133675 | +#else |
| 133491 | 133676 | p->rValue = sqlite3_value_double(argv[ii]); |
| 133677 | +#endif |
| 133492 | 133678 | } |
| 133493 | 133679 | } |
| 133494 | 133680 | } |
| 133495 | 133681 | } |
| 133496 | 133682 | |
| | @@ -133620,28 +133806,28 @@ |
| 133620 | 133806 | } |
| 133621 | 133807 | |
| 133622 | 133808 | /* |
| 133623 | 133809 | ** Return the N-dimensional volumn of the cell stored in *p. |
| 133624 | 133810 | */ |
| 133625 | | -static float cellArea(Rtree *pRtree, RtreeCell *p){ |
| 133626 | | - float area = 1.0; |
| 133811 | +static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ |
| 133812 | + RtreeDValue area = (RtreeDValue)1; |
| 133627 | 133813 | int ii; |
| 133628 | 133814 | for(ii=0; ii<(pRtree->nDim*2); ii+=2){ |
| 133629 | | - area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); |
| 133815 | + area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); |
| 133630 | 133816 | } |
| 133631 | 133817 | return area; |
| 133632 | 133818 | } |
| 133633 | 133819 | |
| 133634 | 133820 | /* |
| 133635 | 133821 | ** Return the margin length of cell p. The margin length is the sum |
| 133636 | 133822 | ** of the objects size in each dimension. |
| 133637 | 133823 | */ |
| 133638 | | -static float cellMargin(Rtree *pRtree, RtreeCell *p){ |
| 133639 | | - float margin = 0.0; |
| 133824 | +static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ |
| 133825 | + RtreeDValue margin = (RtreeDValue)0; |
| 133640 | 133826 | int ii; |
| 133641 | 133827 | for(ii=0; ii<(pRtree->nDim*2); ii+=2){ |
| 133642 | | - margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); |
| 133828 | + margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); |
| 133643 | 133829 | } |
| 133644 | 133830 | return margin; |
| 133645 | 133831 | } |
| 133646 | 133832 | |
| 133647 | 133833 | /* |
| | @@ -133682,51 +133868,50 @@ |
| 133682 | 133868 | } |
| 133683 | 133869 | |
| 133684 | 133870 | /* |
| 133685 | 133871 | ** Return the amount cell p would grow by if it were unioned with pCell. |
| 133686 | 133872 | */ |
| 133687 | | -static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ |
| 133688 | | - float area; |
| 133873 | +static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ |
| 133874 | + RtreeDValue area; |
| 133689 | 133875 | RtreeCell cell; |
| 133690 | 133876 | memcpy(&cell, p, sizeof(RtreeCell)); |
| 133691 | 133877 | area = cellArea(pRtree, &cell); |
| 133692 | 133878 | cellUnion(pRtree, &cell, pCell); |
| 133693 | 133879 | return (cellArea(pRtree, &cell)-area); |
| 133694 | 133880 | } |
| 133695 | 133881 | |
| 133696 | 133882 | #if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT |
| 133697 | | -static float cellOverlap( |
| 133883 | +static RtreeDValue cellOverlap( |
| 133698 | 133884 | Rtree *pRtree, |
| 133699 | 133885 | RtreeCell *p, |
| 133700 | 133886 | RtreeCell *aCell, |
| 133701 | 133887 | int nCell, |
| 133702 | 133888 | int iExclude |
| 133703 | 133889 | ){ |
| 133704 | 133890 | int ii; |
| 133705 | | - float overlap = 0.0; |
| 133891 | + RtreeDValue overlap = 0.0; |
| 133706 | 133892 | for(ii=0; ii<nCell; ii++){ |
| 133707 | 133893 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 133708 | 133894 | if( ii!=iExclude ) |
| 133709 | 133895 | #else |
| 133710 | 133896 | assert( iExclude==-1 ); |
| 133711 | 133897 | UNUSED_PARAMETER(iExclude); |
| 133712 | 133898 | #endif |
| 133713 | 133899 | { |
| 133714 | 133900 | int jj; |
| 133715 | | - float o = 1.0; |
| 133901 | + RtreeDValue o = (RtreeDValue)1; |
| 133716 | 133902 | for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| 133717 | | - double x1; |
| 133718 | | - double x2; |
| 133903 | + RtreeDValue x1, x2; |
| 133719 | 133904 | |
| 133720 | 133905 | x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); |
| 133721 | 133906 | x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); |
| 133722 | 133907 | |
| 133723 | 133908 | if( x2<x1 ){ |
| 133724 | 133909 | o = 0.0; |
| 133725 | 133910 | break; |
| 133726 | 133911 | }else{ |
| 133727 | | - o = o * (float)(x2-x1); |
| 133912 | + o = o * (x2-x1); |
| 133728 | 133913 | } |
| 133729 | 133914 | } |
| 133730 | 133915 | overlap += o; |
| 133731 | 133916 | } |
| 133732 | 133917 | } |
| | @@ -133733,24 +133918,23 @@ |
| 133733 | 133918 | return overlap; |
| 133734 | 133919 | } |
| 133735 | 133920 | #endif |
| 133736 | 133921 | |
| 133737 | 133922 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 133738 | | -static float cellOverlapEnlargement( |
| 133923 | +static RtreeDValue cellOverlapEnlargement( |
| 133739 | 133924 | Rtree *pRtree, |
| 133740 | 133925 | RtreeCell *p, |
| 133741 | 133926 | RtreeCell *pInsert, |
| 133742 | 133927 | RtreeCell *aCell, |
| 133743 | 133928 | int nCell, |
| 133744 | 133929 | int iExclude |
| 133745 | 133930 | ){ |
| 133746 | | - double before; |
| 133747 | | - double after; |
| 133931 | + RtreeDValue before, after; |
| 133748 | 133932 | before = cellOverlap(pRtree, p, aCell, nCell, iExclude); |
| 133749 | 133933 | cellUnion(pRtree, p, pInsert); |
| 133750 | 133934 | after = cellOverlap(pRtree, p, aCell, nCell, iExclude); |
| 133751 | | - return (float)(after-before); |
| 133935 | + return (after-before); |
| 133752 | 133936 | } |
| 133753 | 133937 | #endif |
| 133754 | 133938 | |
| 133755 | 133939 | |
| 133756 | 133940 | /* |
| | @@ -133770,15 +133954,15 @@ |
| 133770 | 133954 | |
| 133771 | 133955 | for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ |
| 133772 | 133956 | int iCell; |
| 133773 | 133957 | sqlite3_int64 iBest = 0; |
| 133774 | 133958 | |
| 133775 | | - float fMinGrowth = 0.0; |
| 133776 | | - float fMinArea = 0.0; |
| 133959 | + RtreeDValue fMinGrowth = 0.0; |
| 133960 | + RtreeDValue fMinArea = 0.0; |
| 133777 | 133961 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 133778 | | - float fMinOverlap = 0.0; |
| 133779 | | - float overlap; |
| 133962 | + RtreeDValue fMinOverlap = 0.0; |
| 133963 | + RtreeDValue overlap; |
| 133780 | 133964 | #endif |
| 133781 | 133965 | |
| 133782 | 133966 | int nCell = NCELL(pNode); |
| 133783 | 133967 | RtreeCell cell; |
| 133784 | 133968 | RtreeNode *pChild; |
| | @@ -133805,12 +133989,12 @@ |
| 133805 | 133989 | ** is inserted into it. Resolve ties by choosing the entry with |
| 133806 | 133990 | ** the smallest area. |
| 133807 | 133991 | */ |
| 133808 | 133992 | for(iCell=0; iCell<nCell; iCell++){ |
| 133809 | 133993 | int bBest = 0; |
| 133810 | | - float growth; |
| 133811 | | - float area; |
| 133994 | + RtreeDValue growth; |
| 133995 | + RtreeDValue area; |
| 133812 | 133996 | nodeGetCell(pRtree, pNode, iCell, &cell); |
| 133813 | 133997 | growth = cellGrowth(pRtree, &cell, pCell); |
| 133814 | 133998 | area = cellArea(pRtree, &cell); |
| 133815 | 133999 | |
| 133816 | 134000 | #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| | @@ -133933,30 +134117,30 @@ |
| 133933 | 134117 | int *piRightSeed |
| 133934 | 134118 | ){ |
| 133935 | 134119 | int i; |
| 133936 | 134120 | int iLeftSeed = 0; |
| 133937 | 134121 | int iRightSeed = 1; |
| 133938 | | - float maxNormalInnerWidth = 0.0; |
| 134122 | + RtreeDValue maxNormalInnerWidth = (RtreeDValue)0; |
| 133939 | 134123 | |
| 133940 | 134124 | /* Pick two "seed" cells from the array of cells. The algorithm used |
| 133941 | 134125 | ** here is the LinearPickSeeds algorithm from Gutman[1984]. The |
| 133942 | 134126 | ** indices of the two seed cells in the array are stored in local |
| 133943 | 134127 | ** variables iLeftSeek and iRightSeed. |
| 133944 | 134128 | */ |
| 133945 | 134129 | for(i=0; i<pRtree->nDim; i++){ |
| 133946 | | - float x1 = DCOORD(aCell[0].aCoord[i*2]); |
| 133947 | | - float x2 = DCOORD(aCell[0].aCoord[i*2+1]); |
| 133948 | | - float x3 = x1; |
| 133949 | | - float x4 = x2; |
| 134130 | + RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); |
| 134131 | + RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); |
| 134132 | + RtreeDValue x3 = x1; |
| 134133 | + RtreeDValue x4 = x2; |
| 133950 | 134134 | int jj; |
| 133951 | 134135 | |
| 133952 | 134136 | int iCellLeft = 0; |
| 133953 | 134137 | int iCellRight = 0; |
| 133954 | 134138 | |
| 133955 | 134139 | for(jj=1; jj<nCell; jj++){ |
| 133956 | | - float left = DCOORD(aCell[jj].aCoord[i*2]); |
| 133957 | | - float right = DCOORD(aCell[jj].aCoord[i*2+1]); |
| 134140 | + RtreeDValue left = DCOORD(aCell[jj].aCoord[i*2]); |
| 134141 | + RtreeDValue right = DCOORD(aCell[jj].aCoord[i*2+1]); |
| 133958 | 134142 | |
| 133959 | 134143 | if( left<x1 ) x1 = left; |
| 133960 | 134144 | if( right>x4 ) x4 = right; |
| 133961 | 134145 | if( left>x3 ){ |
| 133962 | 134146 | x3 = left; |
| | @@ -133967,11 +134151,11 @@ |
| 133967 | 134151 | iCellLeft = jj; |
| 133968 | 134152 | } |
| 133969 | 134153 | } |
| 133970 | 134154 | |
| 133971 | 134155 | if( x4!=x1 ){ |
| 133972 | | - float normalwidth = (x3 - x2) / (x4 - x1); |
| 134156 | + RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); |
| 133973 | 134157 | if( normalwidth>maxNormalInnerWidth ){ |
| 133974 | 134158 | iLeftSeed = iCellLeft; |
| 133975 | 134159 | iRightSeed = iCellRight; |
| 133976 | 134160 | } |
| 133977 | 134161 | } |
| | @@ -133996,17 +134180,17 @@ |
| 133996 | 134180 | int *aiUsed |
| 133997 | 134181 | ){ |
| 133998 | 134182 | #define FABS(a) ((a)<0.0?-1.0*(a):(a)) |
| 133999 | 134183 | |
| 134000 | 134184 | int iSelect = -1; |
| 134001 | | - float fDiff; |
| 134185 | + RtreeDValue fDiff; |
| 134002 | 134186 | int ii; |
| 134003 | 134187 | for(ii=0; ii<nCell; ii++){ |
| 134004 | 134188 | if( aiUsed[ii]==0 ){ |
| 134005 | | - float left = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 134006 | | - float right = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 134007 | | - float diff = FABS(right-left); |
| 134189 | + RtreeDValue left = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 134190 | + RtreeDValue right = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 134191 | + RtreeDValue diff = FABS(right-left); |
| 134008 | 134192 | if( iSelect<0 || diff>fDiff ){ |
| 134009 | 134193 | fDiff = diff; |
| 134010 | 134194 | iSelect = ii; |
| 134011 | 134195 | } |
| 134012 | 134196 | } |
| | @@ -134029,17 +134213,17 @@ |
| 134029 | 134213 | int ii; |
| 134030 | 134214 | int jj; |
| 134031 | 134215 | |
| 134032 | 134216 | int iLeftSeed = 0; |
| 134033 | 134217 | int iRightSeed = 1; |
| 134034 | | - float fWaste = 0.0; |
| 134218 | + RtreeDValue fWaste = 0.0; |
| 134035 | 134219 | |
| 134036 | 134220 | for(ii=0; ii<nCell; ii++){ |
| 134037 | 134221 | for(jj=ii+1; jj<nCell; jj++){ |
| 134038 | | - float right = cellArea(pRtree, &aCell[jj]); |
| 134039 | | - float growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]); |
| 134040 | | - float waste = growth - right; |
| 134222 | + RtreeDValue right = cellArea(pRtree, &aCell[jj]); |
| 134223 | + RtreeDValue growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]); |
| 134224 | + RtreeDValue waste = growth - right; |
| 134041 | 134225 | |
| 134042 | 134226 | if( waste>fWaste ){ |
| 134043 | 134227 | iLeftSeed = ii; |
| 134044 | 134228 | iRightSeed = jj; |
| 134045 | 134229 | fWaste = waste; |
| | @@ -134070,11 +134254,11 @@ |
| 134070 | 134254 | ** sorting algorithm. |
| 134071 | 134255 | */ |
| 134072 | 134256 | static void SortByDistance( |
| 134073 | 134257 | int *aIdx, |
| 134074 | 134258 | int nIdx, |
| 134075 | | - float *aDistance, |
| 134259 | + RtreeDValue *aDistance, |
| 134076 | 134260 | int *aSpare |
| 134077 | 134261 | ){ |
| 134078 | 134262 | if( nIdx>1 ){ |
| 134079 | 134263 | int iLeft = 0; |
| 134080 | 134264 | int iRight = 0; |
| | @@ -134096,12 +134280,12 @@ |
| 134096 | 134280 | iRight++; |
| 134097 | 134281 | }else if( iRight==nRight ){ |
| 134098 | 134282 | aIdx[iLeft+iRight] = aLeft[iLeft]; |
| 134099 | 134283 | iLeft++; |
| 134100 | 134284 | }else{ |
| 134101 | | - float fLeft = aDistance[aLeft[iLeft]]; |
| 134102 | | - float fRight = aDistance[aRight[iRight]]; |
| 134285 | + RtreeDValue fLeft = aDistance[aLeft[iLeft]]; |
| 134286 | + RtreeDValue fRight = aDistance[aRight[iRight]]; |
| 134103 | 134287 | if( fLeft<fRight ){ |
| 134104 | 134288 | aIdx[iLeft+iRight] = aLeft[iLeft]; |
| 134105 | 134289 | iLeft++; |
| 134106 | 134290 | }else{ |
| 134107 | 134291 | aIdx[iLeft+iRight] = aRight[iRight]; |
| | @@ -134113,12 +134297,12 @@ |
| 134113 | 134297 | #if 0 |
| 134114 | 134298 | /* Check that the sort worked */ |
| 134115 | 134299 | { |
| 134116 | 134300 | int jj; |
| 134117 | 134301 | for(jj=1; jj<nIdx; jj++){ |
| 134118 | | - float left = aDistance[aIdx[jj-1]]; |
| 134119 | | - float right = aDistance[aIdx[jj]]; |
| 134302 | + RtreeDValue left = aDistance[aIdx[jj-1]]; |
| 134303 | + RtreeDValue right = aDistance[aIdx[jj]]; |
| 134120 | 134304 | assert( left<=right ); |
| 134121 | 134305 | } |
| 134122 | 134306 | } |
| 134123 | 134307 | #endif |
| 134124 | 134308 | } |
| | @@ -134157,14 +134341,14 @@ |
| 134157 | 134341 | SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare); |
| 134158 | 134342 | |
| 134159 | 134343 | memcpy(aSpare, aLeft, sizeof(int)*nLeft); |
| 134160 | 134344 | aLeft = aSpare; |
| 134161 | 134345 | while( iLeft<nLeft || iRight<nRight ){ |
| 134162 | | - double xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]); |
| 134163 | | - double xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]); |
| 134164 | | - double xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]); |
| 134165 | | - double xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]); |
| 134346 | + RtreeDValue xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]); |
| 134347 | + RtreeDValue xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]); |
| 134348 | + RtreeDValue xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]); |
| 134349 | + RtreeDValue xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]); |
| 134166 | 134350 | if( (iLeft!=nLeft) && ((iRight==nRight) |
| 134167 | 134351 | || (xleft1<xright1) |
| 134168 | 134352 | || (xleft1==xright1 && xleft2<xright2) |
| 134169 | 134353 | )){ |
| 134170 | 134354 | aIdx[iLeft+iRight] = aLeft[iLeft]; |
| | @@ -134178,14 +134362,14 @@ |
| 134178 | 134362 | #if 0 |
| 134179 | 134363 | /* Check that the sort worked */ |
| 134180 | 134364 | { |
| 134181 | 134365 | int jj; |
| 134182 | 134366 | for(jj=1; jj<nIdx; jj++){ |
| 134183 | | - float xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2]; |
| 134184 | | - float xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1]; |
| 134185 | | - float xright1 = aCell[aIdx[jj]].aCoord[iDim*2]; |
| 134186 | | - float xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1]; |
| 134367 | + RtreeDValue xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2]; |
| 134368 | + RtreeDValue xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1]; |
| 134369 | + RtreeDValue xright1 = aCell[aIdx[jj]].aCoord[iDim*2]; |
| 134370 | + RtreeDValue xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1]; |
| 134187 | 134371 | assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) ); |
| 134188 | 134372 | } |
| 134189 | 134373 | } |
| 134190 | 134374 | #endif |
| 134191 | 134375 | } |
| | @@ -134208,11 +134392,11 @@ |
| 134208 | 134392 | int *aSpare; |
| 134209 | 134393 | int ii; |
| 134210 | 134394 | |
| 134211 | 134395 | int iBestDim = 0; |
| 134212 | 134396 | int iBestSplit = 0; |
| 134213 | | - float fBestMargin = 0.0; |
| 134397 | + RtreeDValue fBestMargin = 0.0; |
| 134214 | 134398 | |
| 134215 | 134399 | int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int)); |
| 134216 | 134400 | |
| 134217 | 134401 | aaSorted = (int **)sqlite3_malloc(nByte); |
| 134218 | 134402 | if( !aaSorted ){ |
| | @@ -134229,13 +134413,13 @@ |
| 134229 | 134413 | } |
| 134230 | 134414 | SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare); |
| 134231 | 134415 | } |
| 134232 | 134416 | |
| 134233 | 134417 | for(ii=0; ii<pRtree->nDim; ii++){ |
| 134234 | | - float margin = 0.0; |
| 134235 | | - float fBestOverlap = 0.0; |
| 134236 | | - float fBestArea = 0.0; |
| 134418 | + RtreeDValue margin = 0.0; |
| 134419 | + RtreeDValue fBestOverlap = 0.0; |
| 134420 | + RtreeDValue fBestArea = 0.0; |
| 134237 | 134421 | int iBestLeft = 0; |
| 134238 | 134422 | int nLeft; |
| 134239 | 134423 | |
| 134240 | 134424 | for( |
| 134241 | 134425 | nLeft=RTREE_MINCELLS(pRtree); |
| | @@ -134243,12 +134427,12 @@ |
| 134243 | 134427 | nLeft++ |
| 134244 | 134428 | ){ |
| 134245 | 134429 | RtreeCell left; |
| 134246 | 134430 | RtreeCell right; |
| 134247 | 134431 | int kk; |
| 134248 | | - float overlap; |
| 134249 | | - float area; |
| 134432 | + RtreeDValue overlap; |
| 134433 | + RtreeDValue area; |
| 134250 | 134434 | |
| 134251 | 134435 | memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); |
| 134252 | 134436 | memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); |
| 134253 | 134437 | for(kk=1; kk<(nCell-1); kk++){ |
| 134254 | 134438 | if( kk<nLeft ){ |
| | @@ -134327,11 +134511,11 @@ |
| 134327 | 134511 | aiUsed[iRightSeed] = 1; |
| 134328 | 134512 | |
| 134329 | 134513 | for(i=nCell-2; i>0; i--){ |
| 134330 | 134514 | RtreeCell *pNext; |
| 134331 | 134515 | pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); |
| 134332 | | - float diff = |
| 134516 | + RtreeDValue diff = |
| 134333 | 134517 | cellGrowth(pRtree, pBboxLeft, pNext) - |
| 134334 | 134518 | cellGrowth(pRtree, pBboxRight, pNext) |
| 134335 | 134519 | ; |
| 134336 | 134520 | if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i) |
| 134337 | 134521 | || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i)) |
| | @@ -134660,58 +134844,60 @@ |
| 134660 | 134844 | int iHeight |
| 134661 | 134845 | ){ |
| 134662 | 134846 | int *aOrder; |
| 134663 | 134847 | int *aSpare; |
| 134664 | 134848 | RtreeCell *aCell; |
| 134665 | | - float *aDistance; |
| 134849 | + RtreeDValue *aDistance; |
| 134666 | 134850 | int nCell; |
| 134667 | | - float aCenterCoord[RTREE_MAX_DIMENSIONS]; |
| 134851 | + RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS]; |
| 134668 | 134852 | int iDim; |
| 134669 | 134853 | int ii; |
| 134670 | 134854 | int rc = SQLITE_OK; |
| 134855 | + int n; |
| 134671 | 134856 | |
| 134672 | | - memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS); |
| 134857 | + memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS); |
| 134673 | 134858 | |
| 134674 | 134859 | nCell = NCELL(pNode)+1; |
| 134860 | + n = (nCell+1)&(~1); |
| 134675 | 134861 | |
| 134676 | 134862 | /* Allocate the buffers used by this operation. The allocation is |
| 134677 | 134863 | ** relinquished before this function returns. |
| 134678 | 134864 | */ |
| 134679 | | - aCell = (RtreeCell *)sqlite3_malloc(nCell * ( |
| 134680 | | - sizeof(RtreeCell) + /* aCell array */ |
| 134681 | | - sizeof(int) + /* aOrder array */ |
| 134682 | | - sizeof(int) + /* aSpare array */ |
| 134683 | | - sizeof(float) /* aDistance array */ |
| 134865 | + aCell = (RtreeCell *)sqlite3_malloc(n * ( |
| 134866 | + sizeof(RtreeCell) + /* aCell array */ |
| 134867 | + sizeof(int) + /* aOrder array */ |
| 134868 | + sizeof(int) + /* aSpare array */ |
| 134869 | + sizeof(RtreeDValue) /* aDistance array */ |
| 134684 | 134870 | )); |
| 134685 | 134871 | if( !aCell ){ |
| 134686 | 134872 | return SQLITE_NOMEM; |
| 134687 | 134873 | } |
| 134688 | | - aOrder = (int *)&aCell[nCell]; |
| 134689 | | - aSpare = (int *)&aOrder[nCell]; |
| 134690 | | - aDistance = (float *)&aSpare[nCell]; |
| 134874 | + aOrder = (int *)&aCell[n]; |
| 134875 | + aSpare = (int *)&aOrder[n]; |
| 134876 | + aDistance = (RtreeDValue *)&aSpare[n]; |
| 134691 | 134877 | |
| 134692 | 134878 | for(ii=0; ii<nCell; ii++){ |
| 134693 | 134879 | if( ii==(nCell-1) ){ |
| 134694 | 134880 | memcpy(&aCell[ii], pCell, sizeof(RtreeCell)); |
| 134695 | 134881 | }else{ |
| 134696 | 134882 | nodeGetCell(pRtree, pNode, ii, &aCell[ii]); |
| 134697 | 134883 | } |
| 134698 | 134884 | aOrder[ii] = ii; |
| 134699 | 134885 | for(iDim=0; iDim<pRtree->nDim; iDim++){ |
| 134700 | | - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]); |
| 134701 | | - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]); |
| 134886 | + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); |
| 134887 | + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); |
| 134702 | 134888 | } |
| 134703 | 134889 | } |
| 134704 | 134890 | for(iDim=0; iDim<pRtree->nDim; iDim++){ |
| 134705 | | - aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0)); |
| 134891 | + aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); |
| 134706 | 134892 | } |
| 134707 | 134893 | |
| 134708 | 134894 | for(ii=0; ii<nCell; ii++){ |
| 134709 | 134895 | aDistance[ii] = 0.0; |
| 134710 | 134896 | for(iDim=0; iDim<pRtree->nDim; iDim++){ |
| 134711 | | - float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) - |
| 134712 | | - DCOORD(aCell[ii].aCoord[iDim*2])); |
| 134897 | + RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - |
| 134898 | + DCOORD(aCell[ii].aCoord[iDim*2])); |
| 134713 | 134899 | aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); |
| 134714 | 134900 | } |
| 134715 | 134901 | } |
| 134716 | 134902 | |
| 134717 | 134903 | SortByDistance(aOrder, nCell, aDistance, aSpare); |
| | @@ -134949,20 +135135,23 @@ |
| 134949 | 135135 | if( nData>1 ){ |
| 134950 | 135136 | int ii; |
| 134951 | 135137 | |
| 134952 | 135138 | /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ |
| 134953 | 135139 | assert( nData==(pRtree->nDim*2 + 3) ); |
| 135140 | +#ifndef SQLITE_RTREE_INT_ONLY |
| 134954 | 135141 | if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ |
| 134955 | 135142 | for(ii=0; ii<(pRtree->nDim*2); ii+=2){ |
| 134956 | | - cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]); |
| 134957 | | - cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]); |
| 135143 | + cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]); |
| 135144 | + cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]); |
| 134958 | 135145 | if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ |
| 134959 | 135146 | rc = SQLITE_CONSTRAINT; |
| 134960 | 135147 | goto constraint; |
| 134961 | 135148 | } |
| 134962 | 135149 | } |
| 134963 | | - }else{ |
| 135150 | + }else |
| 135151 | +#endif |
| 135152 | + { |
| 134964 | 135153 | for(ii=0; ii<(pRtree->nDim*2); ii+=2){ |
| 134965 | 135154 | cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); |
| 134966 | 135155 | cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); |
| 134967 | 135156 | if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ |
| 134968 | 135157 | rc = SQLITE_CONSTRAINT; |
| | @@ -135356,11 +135545,17 @@ |
| 135356 | 135545 | |
| 135357 | 135546 | nodeGetCell(&tree, &node, ii, &cell); |
| 135358 | 135547 | sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); |
| 135359 | 135548 | nCell = (int)strlen(zCell); |
| 135360 | 135549 | for(jj=0; jj<tree.nDim*2; jj++){ |
| 135361 | | - sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f); |
| 135550 | +#ifndef SQLITE_RTREE_INT_ONLY |
| 135551 | + sqlite3_snprintf(512-nCell,&zCell[nCell], " %f", |
| 135552 | + (double)cell.aCoord[jj].f); |
| 135553 | +#else |
| 135554 | + sqlite3_snprintf(512-nCell,&zCell[nCell], " %d", |
| 135555 | + cell.aCoord[jj].i); |
| 135556 | +#endif |
| 135362 | 135557 | nCell = (int)strlen(zCell); |
| 135363 | 135558 | } |
| 135364 | 135559 | |
| 135365 | 135560 | if( zText ){ |
| 135366 | 135561 | char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell); |
| | @@ -135398,11 +135593,15 @@ |
| 135398 | 135593 | rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); |
| 135399 | 135594 | if( rc==SQLITE_OK ){ |
| 135400 | 135595 | rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); |
| 135401 | 135596 | } |
| 135402 | 135597 | if( rc==SQLITE_OK ){ |
| 135598 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 135599 | + void *c = (void *)RTREE_COORD_INT32; |
| 135600 | +#else |
| 135403 | 135601 | void *c = (void *)RTREE_COORD_REAL32; |
| 135602 | +#endif |
| 135404 | 135603 | rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); |
| 135405 | 135604 | } |
| 135406 | 135605 | if( rc==SQLITE_OK ){ |
| 135407 | 135606 | void *c = (void *)RTREE_COORD_INT32; |
| 135408 | 135607 | rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); |
| | @@ -135432,11 +135631,11 @@ |
| 135432 | 135631 | static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ |
| 135433 | 135632 | RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); |
| 135434 | 135633 | RtreeMatchArg *pBlob; |
| 135435 | 135634 | int nBlob; |
| 135436 | 135635 | |
| 135437 | | - nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(double); |
| 135636 | + nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue); |
| 135438 | 135637 | pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); |
| 135439 | 135638 | if( !pBlob ){ |
| 135440 | 135639 | sqlite3_result_error_nomem(ctx); |
| 135441 | 135640 | }else{ |
| 135442 | 135641 | int i; |
| | @@ -135443,11 +135642,15 @@ |
| 135443 | 135642 | pBlob->magic = RTREE_GEOMETRY_MAGIC; |
| 135444 | 135643 | pBlob->xGeom = pGeomCtx->xGeom; |
| 135445 | 135644 | pBlob->pContext = pGeomCtx->pContext; |
| 135446 | 135645 | pBlob->nParam = nArg; |
| 135447 | 135646 | for(i=0; i<nArg; i++){ |
| 135647 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 135648 | + pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); |
| 135649 | +#else |
| 135448 | 135650 | pBlob->aParam[i] = sqlite3_value_double(aArg[i]); |
| 135651 | +#endif |
| 135449 | 135652 | } |
| 135450 | 135653 | sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); |
| 135451 | 135654 | } |
| 135452 | 135655 | } |
| 135453 | 135656 | |
| | @@ -135455,11 +135658,11 @@ |
| 135455 | 135658 | ** Register a new geometry function for use with the r-tree MATCH operator. |
| 135456 | 135659 | */ |
| 135457 | 135660 | SQLITE_API int sqlite3_rtree_geometry_callback( |
| 135458 | 135661 | sqlite3 *db, |
| 135459 | 135662 | const char *zGeom, |
| 135460 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), |
| 135663 | + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), |
| 135461 | 135664 | void *pContext |
| 135462 | 135665 | ){ |
| 135463 | 135666 | RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ |
| 135464 | 135667 | |
| 135465 | 135668 | /* Allocate and populate the context object. */ |
| 135466 | 135669 | |