Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update with fixes and enhancements from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | value-dup |
Files: | files | file ages | folders |
SHA1: |
9605d008f5c763137e9734d033fe4510 |
User & Date: | drh 2015-05-22 18:40:48.061 |
Context
2015-05-22
| ||
19:55 | Fix minor issues with the sqlite3_value_dup() interface. (check-in: 95edcf5010 user: drh tags: value-dup) | |
18:40 | Update with fixes and enhancements from trunk. (check-in: 9605d008f5 user: drh tags: value-dup) | |
17:29 | The SRT_Table type for the SelectDest object is now just an SRT_EphemTab for which the ephemeral table has already been allocated. (check-in: b9727e6bbf user: drh tags: trunk) | |
2015-05-20
| ||
21:28 | Add the sqlite3_value_dup() and sqlite3_value_free() interfaces. Use these interfaces to enhance R-Tree to add the sqlite3_rtree_query_info.apSqlParam field. (check-in: a7ee40c4fc user: drh tags: value-dup) | |
Changes
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | ** to which the constraint applies. The leftmost coordinate column ** is 'a', the second from the left 'b' etc. */ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ Rtree *pRtree = (Rtree*)tab; int rc = SQLITE_OK; int ii; i64 nRow; /* Estimated rows returned by this scan */ int iIdx = 0; char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; memset(zIdxStr, 0, sizeof(zIdxStr)); assert( pIdxInfo->idxStr==0 ); for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; | > > > > > > > > > > > > | > | 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 | ** to which the constraint applies. The leftmost coordinate column ** is 'a', the second from the left 'b' etc. */ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ Rtree *pRtree = (Rtree*)tab; int rc = SQLITE_OK; int ii; int bMatch = 0; /* True if there exists a MATCH constraint */ i64 nRow; /* Estimated rows returned by this scan */ int iIdx = 0; char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; memset(zIdxStr, 0, sizeof(zIdxStr)); /* Check if there exists a MATCH constraint - even an unusable one. If there ** is, do not consider the lookup-by-rowid plan as using such a plan would ** require the VDBE to evaluate the MATCH constraint, which is not currently ** possible. */ for(ii=0; ii<pIdxInfo->nConstraint; ii++){ if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ bMatch = 1; } } assert( pIdxInfo->idxStr==0 ); for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; if( bMatch==0 && p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ /* We have an equality constraint on the rowid. Use strategy 1. */ int jj; for(jj=0; jj<ii; jj++){ pIdxInfo->aConstraintUsage[jj].argvIndex = 0; pIdxInfo->aConstraintUsage[jj].omit = 0; } pIdxInfo->idxNum = 1; |
︙ | ︙ |
Changes to ext/rtree/rtreeE.test.
︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 | SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Exclude odd rowids on a breadth-first search. do_execsql_test rtreeE-1.6 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Construct a large 2-D RTree with thousands of random entries. # do_test rtreeE-2.1 { db eval { CREATE TABLE t2(id,x0,x1,y0,y1); CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); | > > > > > > > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Exclude odd rowids on a breadth-first search. do_execsql_test rtreeE-1.6 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Test that rtree prefers MATCH to lookup-by-rowid. # do_execsql_test rtreeE-1.7 { SELECT id FROM rt1 WHERE id=18 AND id MATCH Qcircle(0,0,1000,5) } {18} # Construct a large 2-D RTree with thousands of random entries. # do_test rtreeE-2.1 { db eval { CREATE TABLE t2(id,x0,x1,y0,y1); CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); |
︙ | ︙ | |||
124 125 126 127 128 129 130 131 132 | do_execsql_test rtreeE-2.3 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id } $ans set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}] do_execsql_test rtreeE-2.4 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id } $ans finish_test | > | 131 132 133 134 135 136 137 138 139 140 | do_execsql_test rtreeE-2.3 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id } $ans set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}] do_execsql_test rtreeE-2.4 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id } $ans finish_test |
Changes to src/btree.c.
︙ | ︙ | |||
7856 7857 7858 7859 7860 7861 7862 | /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } | | > | 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 | /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } assert( pgnoRoot>=3 || CORRUPT_DB ); testcase( pgnoRoot<3 ); /* Allocate a page. The page that currently resides at pgnoRoot will ** be moved to the allocated page (unless the allocated page happens ** to reside at pgnoRoot). */ rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
8006 8007 8008 8009 8010 8011 8012 | rc = clearCell(pPage, pCell, &szCell); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; }else if( pnChange ){ | | > | 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 | rc = clearCell(pPage, pCell, &szCell); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; }else if( pnChange ){ assert( pPage->intKey || CORRUPT_DB ); testcase( !pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ freePage(pPage, &rc); }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF); } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
38 39 40 41 42 43 44 | (opcode==OP_OpenWrite)?1:0, pTab->zName); if( HasRowid(pTab) ){ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol); VdbeComment((v, "%s", pTab->zName)); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); | | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | (opcode==OP_OpenWrite)?1:0, pTab->zName); if( HasRowid(pTab) ){ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol); VdbeComment((v, "%s", pTab->zName)); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); assert( pPk->tnum==pTab->tnum ); sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pPk); VdbeComment((v, "%s", pTab->zName)); } } /* |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
812 813 814 815 816 817 818 819 820 821 822 823 824 825 | case SRT_Fifo: case SRT_DistFifo: case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open ** on an ephemeral index. If the current row is already present ** in the index, do not write it to the output. If not, add the ** current row to the index and proceed with writing it to the | > > | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | case SRT_Fifo: case SRT_DistFifo: case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open ** on an ephemeral index. If the current row is already present ** in the index, do not write it to the output. If not, add the ** current row to the index and proceed with writing it to the |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | bSeq = 1; } for(i=0; i<nSortData; i++){ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i); VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } switch( eDest ){ | < < < | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 | bSeq = 1; } for(i=0; i<nSortData; i++){ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i); VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } switch( eDest ){ case SRT_EphemTab: { sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { |
︙ | ︙ | |||
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 | } if( pParse->db->mallocFailed ) return 0; /* Suppress the first OFFSET entries if there is an OFFSET clause */ codeOffset(v, p->iOffset, iContinue); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ | > > < < < | 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 | } if( pParse->db->mallocFailed ) return 0; /* Suppress the first OFFSET entries if there is an OFFSET clause */ codeOffset(v, p->iOffset, iContinue); assert( pDest->eDest!=SRT_Exists ); assert( pDest->eDest!=SRT_Table ); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; |
︙ | ︙ | |||
2615 2616 2617 2618 2619 2620 2621 | sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } | < < < < < < < < < < | 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 | sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
739 740 741 742 743 744 745 | pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); /* Create the ephemeral table into which the update results will ** be stored. */ assert( v ); ephemTab = pParse->nTab++; | < < | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); /* Create the ephemeral table into which the update results will ** be stored. */ assert( v ); ephemTab = pParse->nTab++; /* fill the ephemeral table */ sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab); sqlite3Select(pParse, pSelect, &dest); /* Generate code to scan the ephemeral table and call VUpdate. */ iReg = ++pParse->nMem; pParse->nMem += pTab->nCol+1; addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); |
︙ | ︙ |
Changes to tool/fuzzershell.c.
︙ | ︙ | |||
317 318 319 320 321 322 323 324 325 326 327 328 329 330 | static void showHelp(void){ printf("Usage: %s [options] ?FILE...?\n", g.zArgv0); printf( "Read SQL text from FILE... (or from standard input if FILE... is omitted)\n" "and then evaluate each block of SQL contained therein.\n" "Options:\n" " --autovacuum Enable AUTOVACUUM mode\n" " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" " --help Show this help text\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --oom Run each test multiple times in a simulated OOM loop\n" " --pagesize N Set the page size to N\n" " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" " -q Reduced output\n" | > | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | static void showHelp(void){ printf("Usage: %s [options] ?FILE...?\n", g.zArgv0); printf( "Read SQL text from FILE... (or from standard input if FILE... is omitted)\n" "and then evaluate each block of SQL contained therein.\n" "Options:\n" " --autovacuum Enable AUTOVACUUM mode\n" " --database FILE Use database FILE instead of an in-memory database\n" " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" " --help Show this help text\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --oom Run each test multiple times in a simulated OOM loop\n" " --pagesize N Set the page size to N\n" " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" " -q Reduced output\n" |
︙ | ︙ | |||
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | const char *zFailCode; /* Value of the TEST_FAILURE environment var */ const char *zPrompt; /* Initial prompt when large-file fuzzing */ int nInFile = 0; /* Number of input files to read */ char **azInFile = 0; /* Array of input file names */ int jj; /* Loop counter for azInFile[] */ sqlite3_int64 iBegin; /* Start time for the whole program */ sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */ iBegin = timeOfDay(); zFailCode = getenv("TEST_FAILURE"); g.zArgv0 = argv[0]; zPrompt = "<stdin>"; for(i=1; i<argc; i++){ const char *z = argv[i]; if( z[0]=='-' ){ z++; if( z[0]=='-' ) z++; if( strcmp(z,"autovacuum")==0 ){ doAutovac = 1; }else if( strcmp(z, "f")==0 && i+1<argc ){ i++; goto addNewInFile; }else if( strcmp(z,"heap")==0 ){ if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]); | > > > > > > | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | const char *zFailCode; /* Value of the TEST_FAILURE environment var */ const char *zPrompt; /* Initial prompt when large-file fuzzing */ int nInFile = 0; /* Number of input files to read */ char **azInFile = 0; /* Array of input file names */ int jj; /* Loop counter for azInFile[] */ sqlite3_int64 iBegin; /* Start time for the whole program */ sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */ const char *zDbName; /* Name of an on-disk database file to open */ iBegin = timeOfDay(); zFailCode = getenv("TEST_FAILURE"); g.zArgv0 = argv[0]; zPrompt = "<stdin>"; for(i=1; i<argc; i++){ const char *z = argv[i]; if( z[0]=='-' ){ z++; if( z[0]=='-' ) z++; if( strcmp(z,"autovacuum")==0 ){ doAutovac = 1; }else if( strcmp(z,"database")==0 ){ if( i>=argc-1 ) abendError("missing argument on %s\n", argv[i]); zDbName = argv[i+1]; i += 1; }else if( strcmp(z, "f")==0 && i+1<argc ){ i++; goto addNewInFile; }else if( strcmp(z,"heap")==0 ){ if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]); |
︙ | ︙ | |||
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | printf("Once.%d\n", oomCnt); fflush(stdout); } }else{ oomCnt = 0; } do{ rc = sqlite3_open_v2( "main.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); if( rc!=SQLITE_OK ){ abendError("Unable to open the in-memory database"); } if( pLook ){ rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc); } | > > > > | 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 | printf("Once.%d\n", oomCnt); fflush(stdout); } }else{ oomCnt = 0; } do{ if( zDbName ){ rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0); }else{ rc = sqlite3_open_v2( "main.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); } if( rc!=SQLITE_OK ){ abendError("Unable to open the in-memory database"); } if( pLook ){ rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc); } |
︙ | ︙ |