/ Check-in [9605d008]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update with fixes and enhancements from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | value-dup
Files: files | file ages | folders
SHA1: 9605d008f5c763137e9734d033fe4510ca316858
User & Date: drh 2015-05-22 18:40:48
Context
2015-05-22
19:55
Fix minor issues with the sqlite3_value_dup() interface. check-in: 95edcf50 user: drh tags: value-dup
18:40
Update with fixes and enhancements from trunk. check-in: 9605d008 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: b9727e6b 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: a7ee40c4 user: drh tags: value-dup
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/rtree/rtree.c.

  1668   1668   ** to which the constraint applies. The leftmost coordinate column
  1669   1669   ** is 'a', the second from the left 'b' etc.
  1670   1670   */
  1671   1671   static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  1672   1672     Rtree *pRtree = (Rtree*)tab;
  1673   1673     int rc = SQLITE_OK;
  1674   1674     int ii;
         1675  +  int bMatch = 0;                 /* True if there exists a MATCH constraint */
  1675   1676     i64 nRow;                       /* Estimated rows returned by this scan */
  1676   1677   
  1677   1678     int iIdx = 0;
  1678   1679     char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
  1679   1680     memset(zIdxStr, 0, sizeof(zIdxStr));
         1681  +
         1682  +  /* Check if there exists a MATCH constraint - even an unusable one. If there
         1683  +  ** is, do not consider the lookup-by-rowid plan as using such a plan would
         1684  +  ** require the VDBE to evaluate the MATCH constraint, which is not currently
         1685  +  ** possible. */
         1686  +  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
         1687  +    if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){
         1688  +      bMatch = 1;
         1689  +    }
         1690  +  }
  1680   1691   
  1681   1692     assert( pIdxInfo->idxStr==0 );
  1682   1693     for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
  1683   1694       struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
  1684   1695   
  1685         -    if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         1696  +    if( bMatch==0 && p->usable 
         1697  +     && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ 
         1698  +    ){
  1686   1699         /* We have an equality constraint on the rowid. Use strategy 1. */
  1687   1700         int jj;
  1688   1701         for(jj=0; jj<ii; jj++){
  1689   1702           pIdxInfo->aConstraintUsage[jj].argvIndex = 0;
  1690   1703           pIdxInfo->aConstraintUsage[jj].omit = 0;
  1691   1704         }
  1692   1705         pIdxInfo->idxNum = 1;

Changes to ext/rtree/rtreeE.test.

    75     75     SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id
    76     76   } {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}
    77     77   
    78     78   # Exclude odd rowids on a breadth-first search.
    79     79   do_execsql_test rtreeE-1.6 {
    80     80     SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id
    81     81   } {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}
           82  +
           83  +# Test that rtree prefers MATCH to lookup-by-rowid.
           84  +#
           85  +do_execsql_test rtreeE-1.7 {
           86  +  SELECT id FROM rt1 WHERE id=18 AND id MATCH Qcircle(0,0,1000,5)
           87  +} {18}
           88  +
    82     89   
    83     90   # Construct a large 2-D RTree with thousands of random entries.
    84     91   #
    85     92   do_test rtreeE-2.1 {
    86     93     db eval {
    87     94       CREATE TABLE t2(id,x0,x1,y0,y1);
    88     95       CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1);
................................................................................
   124    131   do_execsql_test rtreeE-2.3 {
   125    132     SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id
   126    133   } $ans
   127    134   set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}]
   128    135   do_execsql_test rtreeE-2.4 {
   129    136     SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id
   130    137   } $ans
          138  +
   131    139   
   132    140   finish_test

Changes to src/btree.c.

  7856   7856       /* The new root-page may not be allocated on a pointer-map page, or the
  7857   7857       ** PENDING_BYTE page.
  7858   7858       */
  7859   7859       while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) ||
  7860   7860           pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
  7861   7861         pgnoRoot++;
  7862   7862       }
  7863         -    assert( pgnoRoot>=3 );
         7863  +    assert( pgnoRoot>=3 || CORRUPT_DB );
         7864  +    testcase( pgnoRoot<3 );
  7864   7865   
  7865   7866       /* Allocate a page. The page that currently resides at pgnoRoot will
  7866   7867       ** be moved to the allocated page (unless the allocated page happens
  7867   7868       ** to reside at pgnoRoot).
  7868   7869       */
  7869   7870       rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
  7870   7871       if( rc!=SQLITE_OK ){
................................................................................
  8006   8007       rc = clearCell(pPage, pCell, &szCell);
  8007   8008       if( rc ) goto cleardatabasepage_out;
  8008   8009     }
  8009   8010     if( !pPage->leaf ){
  8010   8011       rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
  8011   8012       if( rc ) goto cleardatabasepage_out;
  8012   8013     }else if( pnChange ){
  8013         -    assert( pPage->intKey );
         8014  +    assert( pPage->intKey || CORRUPT_DB );
         8015  +    testcase( !pPage->intKey );
  8014   8016       *pnChange += pPage->nCell;
  8015   8017     }
  8016   8018     if( freePageFlag ){
  8017   8019       freePage(pPage, &rc);
  8018   8020     }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
  8019   8021       zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
  8020   8022     }

Changes to src/insert.c.

    38     38                      (opcode==OP_OpenWrite)?1:0, pTab->zName);
    39     39     if( HasRowid(pTab) ){
    40     40       sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
    41     41       VdbeComment((v, "%s", pTab->zName));
    42     42     }else{
    43     43       Index *pPk = sqlite3PrimaryKeyIndex(pTab);
    44     44       assert( pPk!=0 );
    45         -    assert( pPk->tnum=pTab->tnum );
           45  +    assert( pPk->tnum==pTab->tnum );
    46     46       sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
    47     47       sqlite3VdbeSetP4KeyInfo(pParse, pPk);
    48     48       VdbeComment((v, "%s", pTab->zName));
    49     49     }
    50     50   }
    51     51   
    52     52   /*

Changes to src/select.c.

   812    812       case SRT_Fifo:
   813    813       case SRT_DistFifo:
   814    814       case SRT_Table:
   815    815       case SRT_EphemTab: {
   816    816         int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
   817    817         testcase( eDest==SRT_Table );
   818    818         testcase( eDest==SRT_EphemTab );
          819  +      testcase( eDest==SRT_Fifo );
          820  +      testcase( eDest==SRT_DistFifo );
   819    821         sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
   820    822   #ifndef SQLITE_OMIT_CTE
   821    823         if( eDest==SRT_DistFifo ){
   822    824           /* If the destination is DistFifo, then cursor (iParm+1) is open
   823    825           ** on an ephemeral index. If the current row is already present
   824    826           ** in the index, do not write it to the output. If not, add the
   825    827           ** current row to the index and proceed with writing it to the
................................................................................
  1227   1229       bSeq = 1;
  1228   1230     }
  1229   1231     for(i=0; i<nSortData; i++){
  1230   1232       sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
  1231   1233       VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
  1232   1234     }
  1233   1235     switch( eDest ){
  1234         -    case SRT_Table:
  1235   1236       case SRT_EphemTab: {
  1236         -      testcase( eDest==SRT_Table );
  1237         -      testcase( eDest==SRT_EphemTab );
  1238   1237         sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
  1239   1238         sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
  1240   1239         sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
  1241   1240         break;
  1242   1241       }
  1243   1242   #ifndef SQLITE_OMIT_SUBQUERY
  1244   1243       case SRT_Set: {
................................................................................
  2579   2578     }
  2580   2579     if( pParse->db->mallocFailed ) return 0;
  2581   2580   
  2582   2581     /* Suppress the first OFFSET entries if there is an OFFSET clause
  2583   2582     */
  2584   2583     codeOffset(v, p->iOffset, iContinue);
  2585   2584   
         2585  +  assert( pDest->eDest!=SRT_Exists );
         2586  +  assert( pDest->eDest!=SRT_Table );
  2586   2587     switch( pDest->eDest ){
  2587   2588       /* Store the result as data using a unique key.
  2588   2589       */
  2589         -    case SRT_Table:
  2590   2590       case SRT_EphemTab: {
  2591   2591         int r1 = sqlite3GetTempReg(pParse);
  2592   2592         int r2 = sqlite3GetTempReg(pParse);
  2593         -      testcase( pDest->eDest==SRT_Table );
  2594         -      testcase( pDest->eDest==SRT_EphemTab );
  2595   2593         sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
  2596   2594         sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2);
  2597   2595         sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2);
  2598   2596         sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
  2599   2597         sqlite3ReleaseTempReg(pParse, r2);
  2600   2598         sqlite3ReleaseTempReg(pParse, r1);
  2601   2599         break;
................................................................................
  2615   2613         sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
  2616   2614         sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
  2617   2615         sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
  2618   2616         sqlite3ReleaseTempReg(pParse, r1);
  2619   2617         break;
  2620   2618       }
  2621   2619   
  2622         -#if 0  /* Never occurs on an ORDER BY query */
  2623         -    /* If any row exist in the result set, record that fact and abort.
  2624         -    */
  2625         -    case SRT_Exists: {
  2626         -      sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
  2627         -      /* The LIMIT clause will terminate the loop for us */
  2628         -      break;
  2629         -    }
  2630         -#endif
  2631         -
  2632   2620       /* If this is a scalar select that is part of an expression, then
  2633   2621       ** store the results in the appropriate memory cell and break out
  2634   2622       ** of the scan loop.
  2635   2623       */
  2636   2624       case SRT_Mem: {
  2637   2625         assert( pIn->nSdst==1 || pParse->nErr>0 );  testcase( pIn->nSdst!=1 );
  2638   2626         sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);

Changes to src/update.c.

   739    739     pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
   740    740     
   741    741     /* Create the ephemeral table into which the update results will
   742    742     ** be stored.
   743    743     */
   744    744     assert( v );
   745    745     ephemTab = pParse->nTab++;
   746         -  sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
   747         -  sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
   748    746   
   749    747     /* fill the ephemeral table 
   750    748     */
   751         -  sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
          749  +  sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab);
   752    750     sqlite3Select(pParse, pSelect, &dest);
   753    751   
   754    752     /* Generate code to scan the ephemeral table and call VUpdate. */
   755    753     iReg = ++pParse->nMem;
   756    754     pParse->nMem += pTab->nCol+1;
   757    755     addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v);
   758    756     sqlite3VdbeAddOp3(v, OP_Column,  ephemTab, 0, iReg);

Changes to tool/fuzzershell.c.

   317    317   static void showHelp(void){
   318    318     printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
   319    319     printf(
   320    320   "Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
   321    321   "and then evaluate each block of SQL contained therein.\n"
   322    322   "Options:\n"
   323    323   "  --autovacuum          Enable AUTOVACUUM mode\n"
          324  +"  --database FILE       Use database FILE instead of an in-memory database\n"
   324    325   "  --heap SZ MIN         Memory allocator uses SZ bytes & min allocation MIN\n"
   325    326   "  --help                Show this help text\n"    
   326    327   "  --lookaside N SZ      Configure lookaside for N slots of SZ bytes each\n"
   327    328   "  --oom                 Run each test multiple times in a simulated OOM loop\n"
   328    329   "  --pagesize N          Set the page size to N\n"
   329    330   "  --pcache N SZ         Configure N pages of pagecache each of size SZ bytes\n"
   330    331   "  -q                    Reduced output\n"
................................................................................
   449    450     const char *zFailCode;        /* Value of the TEST_FAILURE environment var */
   450    451     const char *zPrompt;          /* Initial prompt when large-file fuzzing */
   451    452     int nInFile = 0;              /* Number of input files to read */
   452    453     char **azInFile = 0;          /* Array of input file names */
   453    454     int jj;                       /* Loop counter for azInFile[] */
   454    455     sqlite3_int64 iBegin;         /* Start time for the whole program */
   455    456     sqlite3_int64 iStart, iEnd;   /* Start and end-times for a test case */
          457  +  const char *zDbName;          /* Name of an on-disk database file to open */
   456    458   
   457    459     iBegin = timeOfDay();
   458    460     zFailCode = getenv("TEST_FAILURE");
   459    461     g.zArgv0 = argv[0];
   460    462     zPrompt = "<stdin>";
   461    463     for(i=1; i<argc; i++){
   462    464       const char *z = argv[i];
   463    465       if( z[0]=='-' ){
   464    466         z++;
   465    467         if( z[0]=='-' ) z++;
   466    468         if( strcmp(z,"autovacuum")==0 ){
   467    469           doAutovac = 1;
          470  +      }else
          471  +      if( strcmp(z,"database")==0 ){
          472  +        if( i>=argc-1 ) abendError("missing argument on %s\n", argv[i]);
          473  +        zDbName = argv[i+1];
          474  +        i += 1;
   468    475         }else
   469    476         if( strcmp(z, "f")==0 && i+1<argc ){
   470    477           i++;
   471    478           goto addNewInFile;
   472    479         }else
   473    480         if( strcmp(z,"heap")==0 ){
   474    481           if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
................................................................................
   688    695             printf("Once.%d\n", oomCnt);
   689    696             fflush(stdout);
   690    697           }
   691    698         }else{
   692    699           oomCnt = 0;
   693    700         }
   694    701         do{
   695         -        rc = sqlite3_open_v2(
   696         -          "main.db", &db,
   697         -          SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
   698         -          0);
          702  +        if( zDbName ){
          703  +          rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0);
          704  +        }else{
          705  +          rc = sqlite3_open_v2(
          706  +            "main.db", &db,
          707  +            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
          708  +            0);
          709  +        }
   699    710           if( rc!=SQLITE_OK ){
   700    711             abendError("Unable to open the in-memory database");
   701    712           }
   702    713           if( pLook ){
   703    714             rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
   704    715             if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
   705    716           }