){
Rtree *pRtree = (Rtree *)pVtab;
int rc = SQLITE_OK;
- RtreeCell cell; /* New cell to insert if nData>1 */
- int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
+ RtreeCell cell; /* New cell to insert if nData>1 */
+ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
+ int bRtreeInsert = 0; /* True if rtree data is to be inserted */
+ int nCoord; /* Number of coordinate columns */
+ int ii; /* Loop counter */
if( pRtree->nNodeRef ){
/* Unable to write to the btree while another cursor is reading from it,
cell.iRowid = 0; /* Used only to suppress a compiler warning */
+ /* Set bRtreeInsert if this is an INSERT statement, or if it is an
+ ** UPDATE statement that changes the rowid or one of the coordinates.
+ ** Leave bRtreeInsert at zero if this is a DELETE or if this is an
+ ** UPDATE that only changes auxiliary columns.
+ */
+ if( nData>1 ){
+ nCoord = pRtree->nDim2;
+
+ /* NB: nData can only be less than nDim2+3 if the rtree is mis-declared
+ ** with "column" that are interpreted as table constraints.
+ ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
+ ** This problem was discovered after years of use, so we silently ignore
+ ** these kinds of misdeclared tables to avoid breaking any legacy.
+ */
+ if( nCoord > nData-3 ) nCoord = nData - 3;
+
+ if( sqlite3_value_type(aData[0])==SQLITE_NULL ){
+ bRtreeInsert = 1; /* This is an INSERT statement */
+ }else{
+ /* This is an UPDATE statement. Check to see if the rowid (aData[2])
+ ** or any coordinate column (aData[3] through aData[nCoord+2])
+ ** has changed. */
+ for(ii=nCoord+2; ii>=2; ii--){
+ if( !sqlite3_value_nochange(aData[ii]) ) break;
+ }
+ bRtreeInsert = ii>=2;
+ }
+ }
+
/* Constraint handling. A write operation on an r-tree table may return
** SQLITE_CONSTRAINT for two reasons:
**
** case, SQLITE_CONSTRAINT must be returned regardless of the
** conflict-handling mode specified by the user.
*/
- if( nData>1 ){
- int ii;
- int nn = nData - 4;
-
- if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
- /* Populate the cell.aCoord[] array. The first coordinate is aData[3].
- **
- ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
- ** with "column" that are interpreted as table constraints.
- ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
- ** This problem was discovered after years of use, so we silently ignore
- ** these kinds of misdeclared tables to avoid breaking any legacy.
- */
-
+ if( bRtreeInsert ){
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- for(ii=0; ii<nn; ii+=2){
+ for(ii=0; ii<nCoord; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
}else
#endif
{
- for(ii=0; ii<nn; ii+=2){
+ for(ii=0; ii<nCoord; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
** record to delete from the r-tree table. The following block does
** just that.
*/
- if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
+ if( sqlite3_value_type(aData[0])!=SQLITE_NULL
+ && (bRtreeInsert || nData==1)
+ ){
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
}
** (aData[2]..aData[argc-1]) contain a new record to insert into
** the r-tree structure.
*/
- if( rc==SQLITE_OK && nData>1 ){
+ if( rc==SQLITE_OK && bRtreeInsert ){
/* Insert the new record into the r-tree */
RtreeNode *pLeaf = 0;
/* Figure out the rowid of the new row. */
if( bHaveRowid==0 ){
rc = newRowid(pRtree, &cell.iRowid);
+ bHaveRowid = 1;
}
*pRowid = cell.iRowid;
rc = rc2;
}
}
- if( pRtree->nAux ){
+ }
+
+ /* Handle INSERT and UPDATE of auxiliary column data */
+ if( rc==SQLITE_OK && nData>1 && pRtree->nAux ){
+ if( sqlite3_value_type(aData[0])==SQLITE_NULL ){
+ /* This is an INSERT statement. Check to see if any
+ ** auxiliary column is non-NULL and hence needs to be set */
+ for(ii=pRtree->nAux+pRtree->nDim2+3; ii<nData; ii++){
+ if( sqlite3_value_type(aData[ii])!=SQLITE_NULL ) break;
+ }
+ }else{
+ /* This is an UPDATE statement. Check to see if any
+ ** auxiliary column value has changed. */
+ for(ii=pRtree->nAux+pRtree->nDim2+3; ii<nData; ii++){
+ if( sqlite3_value_nochange(aData[ii])==0 ) break;
+ }
+ }
+ if( ii<nData ){
sqlite3_stmt *pUp = pRtree->pWriteAux;
int jj;
- sqlite3_bind_int64(pUp, 1, *pRowid);
+ if( bHaveRowid ){
+ sqlite3_bind_int64(pUp, 1, cell.iRowid);
+ }else{
+ sqlite3_bind_int64(pUp, 1, sqlite3_value_int64(aData[1]));
+ }
for(jj=0; jj<pRtree->nAux; jj++){
sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
}
-C When\sdoing\sa\sone-pass\sUPDATE\sor\sDELETE\son\svirtual\stables,\sclose\sthe\scursor\nprior\sto\srunning\sVUpdate.\s\sThis\sallows\sone-pass\sto\swork\son\svirtual\stables\nthat\sdo\snot\sallow\sconcurrent\sreads\sand\swrites.\s\sEnhance\srtree\sto\stake\nadvantage\sof\sthis\snew\scapability.
-D 2018-05-24T23:51:57.743
+C This\sis\san\suntested\sproof-of-concept\sfor\senhancements\sto\sRTree\sthat\sattempt\nto\suse\ssqlite3_value_nochange()\sto\sreduce\sthe\samount\sof\swork\sassociated\swith\nUPDATE\soperations\sin\scases\swhere\seither\sthe\scoordinates\sor\sthe\sauxiliary\sdata\nis\sunchanged.
+D 2018-05-25T14:39:24.456
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
+F ext/rtree/rtree.c 1a11f26cbcccc31391fe45e10804b07e64dabc4fb4803fb3d075bfe13360d8b8
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83
-R 52623d992549c096857f92f7f6ff2464
+P b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
+R d13a5739b07f5c3bc2f350a7fd438bb4
+T *branch * rtree-update-optimization
+T *sym-rtree-update-optimization *
+T -sym-trunk *
U drh
-Z 92fa856c89ee79b753ba76005690f976
+Z 339f042021a37adf237173fa2c6b25c7