Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for [e9a9fde1f4]. When opening an existing rtree, determine the node size by inspecting the root node of the r-tree structure (instead of assuming it is a function of the page-size). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ebc9433fddf78ef7b4237686951d8d79 |
User & Date: | dan 2010-02-16 10:59:41.000 |
References
2017-08-17
| ||
02:25 | • New ticket [be436a7f45] Use-after-free on schema change where RTREE is used inside of a trigger. (artifact: 580eefd3a1 user: drh) | |
Context
2010-02-16
| ||
12:18 | Change a C++ style comment in os_unix.c to use normal C style commenting. (check-in: 7a1933097f user: dan tags: trunk) | |
10:59 | Fix for [e9a9fde1f4]. When opening an existing rtree, determine the node size by inspecting the root node of the r-tree structure (instead of assuming it is a function of the page-size). (check-in: ebc9433fdd user: dan tags: trunk) | |
2010-02-15
| ||
18:03 | Fix the ALTER TABLE RENAME command so that it converts FOREIGN KEY constraints in ATTACH-ed and in TEMP tables as well as in the main database. Ticket [13336e9c3c8c3f]. (check-in: ab197d0aaf user: drh tags: trunk) | |
Changes
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
419 420 421 422 423 424 425 426 427 428 429 430 431 432 | pNode->isDirty = 0; pNode->pNext = 0; sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); rc = sqlite3_step(pRtree->pReadNode); if( rc==SQLITE_ROW ){ const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); memcpy(pNode->zData, zBlob, pRtree->iNodeSize); nodeReference(pParent); }else{ sqlite3_free(pNode); pNode = 0; } | > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | pNode->isDirty = 0; pNode->pNext = 0; sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); rc = sqlite3_step(pRtree->pReadNode); if( rc==SQLITE_ROW ){ const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize ); memcpy(pNode->zData, zBlob, pRtree->iNodeSize); nodeReference(pParent); }else{ sqlite3_free(pNode); pNode = 0; } |
︙ | ︙ | |||
2615 2616 2617 2618 2619 2620 2621 | sqlite3_free(zSql); } return rc; } /* | | > | | | | | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > | | > > > > > > > | < | < < < < < < | 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 | sqlite3_free(zSql); } return rc; } /* ** The second argument to this function contains the text of an SQL statement ** that returns a single integer value. The statement is compiled and executed ** using database connection db. If successful, the integer value returned ** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error ** code is returned and the value of *piVal after returning is not defined. */ static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ int rc = SQLITE_NOMEM; if( zSql ){ sqlite3_stmt *pStmt = 0; rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pStmt) ){ *piVal = sqlite3_column_int(pStmt, 0); } rc = sqlite3_finalize(pStmt); } } return rc; } /* ** This function is called from within the xConnect() or xCreate() method to ** determine the node-size used by the rtree table being created or connected ** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. ** Otherwise, an SQLite error code is returned. ** ** If this function is being called as part of an xConnect(), then the rtree ** table already exists. In this case the node-size is determined by inspecting ** the root node of the tree. ** ** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. ** This ensures that each node is stored on a single database page. If the ** database page-size is so large that more than RTREE_MAXCELLS entries ** would fit in a single node, use a smaller node-size. */ static int getNodeSize( sqlite3 *db, /* Database handle */ Rtree *pRtree, /* Rtree handle */ int isCreate /* True for xCreate, false for xConnect */ ){ int rc; char *zSql; if( isCreate ){ int iPageSize; zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); rc = getIntFromStmt(db, zSql, &iPageSize); if( rc==SQLITE_OK ){ pRtree->iNodeSize = iPageSize-64; if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; } } }else{ zSql = sqlite3_mprintf( "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", pRtree->zDb, pRtree->zName ); rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); } sqlite3_free(zSql); return rc; } /* ** This function is the implementation of both the xConnect and xCreate ** methods of the r-tree virtual table. ** ** argv[0] -> module name |
︙ | ︙ | |||
2679 2680 2681 2682 2683 2684 2685 | int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; if( aErrMsg[iErr] ){ *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); return SQLITE_ERROR; } | < < < < < | < < < < < < | < < | < > | | | | | | | | | | | | | | | | | | | | | | > | 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 | int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; if( aErrMsg[iErr] ){ *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); return SQLITE_ERROR; } /* Allocate the sqlite3_vtab structure */ nDb = strlen(argv[1]); nName = strlen(argv[2]); pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); if( !pRtree ){ return SQLITE_NOMEM; } memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); pRtree->nBusy = 1; pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; pRtree->nDim = (argc-4)/2; pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; pRtree->eCoordType = eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); /* Figure out the node size to use. */ rc = getNodeSize(db, pRtree, isCreate); /* Create/Connect to the underlying relational database schema. If ** that is successful, call sqlite3_declare_vtab() to configure ** the r-tree table schema. */ if( rc==SQLITE_OK ){ if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); }else{ char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); char *zTmp; int ii; for(ii=4; zSql && ii<argc; ii++){ zTmp = zSql; zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); sqlite3_free(zTmp); } if( zSql ){ zTmp = zSql; zSql = sqlite3_mprintf("%s);", zTmp); sqlite3_free(zTmp); } if( !zSql ){ rc = SQLITE_NOMEM; }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } sqlite3_free(zSql); } } if( rc==SQLITE_OK ){ *ppVtab = (sqlite3_vtab *)pRtree; }else{ rtreeRelease(pRtree); } |
︙ | ︙ |
Added ext/rtree/rtree7.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # 2010 February 16 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test that nothing goes wrong if an rtree table is created, then the # database page-size is modified. At one point (3.6.22), this was causing # malfunctions. # if {![info exists testdir]} { set testdir [file join [file dirname $argv0] .. .. test] } source $testdir/tester.tcl ifcapable !rtree||!vacuum { finish_test return } do_test rtree7-1.1 { execsql { PRAGMA page_size = 1024; CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2); INSERT INTO rt VALUES(1, 1, 2, 3, 4); } } {} do_test rtree7-1.2 { execsql { SELECT * FROM rt } } {1 1.0 2.0 3.0 4.0} do_test rtree7-1.3 { execsql { PRAGMA page_size = 2048; VACUUM; SELECT * FROM rt; } } {1 1.0 2.0 3.0 4.0} do_test rtree7-1.4 { for {set i 2} {$i <= 51} {incr i} { execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) } } execsql { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } } {51.0 102.0 153.0 204.0} do_test rtree7-1.5 { execsql { PRAGMA page_size = 512; VACUUM; SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } } {51.0 102.0 153.0 204.0} finish_test |