/ Check-in [f4ac1bf2]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Use xFetch() to access temporary files in vdbesort.c. Use a single large allocation instead of many small allocations when accumulating records in vdbesort.c. This is an interim commit - it allocates a buffer the size of the page-cache every time data is sorted.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | orderby-planning
Files: files | file ages | folders
SHA1: f4ac1bf28c4ba395ccab8f1c9df72614a61095a7
User & Date: dan 2014-03-27 17:23:41
Context
2014-03-27
19:25
Instead of allocating a single large buffer at the beginning of each sort operation, start with a small buffer and extend it using realloc() as required. check-in: 81987c8c user: dan tags: orderby-planning
17:23
Use xFetch() to access temporary files in vdbesort.c. Use a single large allocation instead of many small allocations when accumulating records in vdbesort.c. This is an interim commit - it allocates a buffer the size of the page-cache every time data is sorted. check-in: f4ac1bf2 user: dan tags: orderby-planning
00:09
Merge the latest trunk changes and the fix for the crash on a corrupt database. check-in: 0b35346c user: drh tags: orderby-planning
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbesort.c.

   101    101     int mnPmaSize;                  /* Minimum PMA size, in bytes */
   102    102     int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
   103    103     VdbeSorterIter *aIter;          /* Array of iterators to merge */
   104    104     int *aTree;                     /* Current state of incremental merge */
   105    105     sqlite3_file *pTemp1;           /* PMA file 1 */
   106    106     SorterRecord *pRecord;          /* Head of in-memory record list */
   107    107     UnpackedRecord *pUnpacked;      /* Used to unpack keys */
          108  +  u8* aMemory;                    /* Block to allocate records from */
          109  +  int iMemory;                    /* Offset of free space in aMemory */
   108    110   };
   109    111   
   110    112   /*
   111    113   ** The following type is an iterator for a PMA. It caches the current key in 
   112    114   ** variables nKey/aKey. If the iterator is at EOF, pFile==0.
   113    115   */
   114    116   struct VdbeSorterIter {
................................................................................
   117    119     int nAlloc;                     /* Bytes of space at aAlloc */
   118    120     int nKey;                       /* Number of bytes in key */
   119    121     sqlite3_file *pFile;            /* File iterator is reading from */
   120    122     u8 *aAlloc;                     /* Allocated space */
   121    123     u8 *aKey;                       /* Pointer to current key */
   122    124     u8 *aBuffer;                    /* Current read buffer */
   123    125     int nBuffer;                    /* Size of read buffer in bytes */
          126  +  u8 *aMap;                       /* Pointer to mapping of pFile */
   124    127   };
   125    128   
   126    129   /*
   127    130   ** An instance of this structure is used to organize the stream of records
   128    131   ** being written to files by the merge-sort code into aligned, page-sized
   129    132   ** blocks.  Doing all I/O in aligned page-sized blocks helps I/O to go
   130    133   ** faster on many operating systems.
................................................................................
   159    162   /*
   160    163   ** Free all memory belonging to the VdbeSorterIter object passed as the second
   161    164   ** argument. All structure fields are set to zero before returning.
   162    165   */
   163    166   static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){
   164    167     sqlite3DbFree(db, pIter->aAlloc);
   165    168     sqlite3DbFree(db, pIter->aBuffer);
          169  +  if( pIter->aMap ) sqlite3OsUnfetch(pIter->pFile, 0, pIter->aMap);
   166    170     memset(pIter, 0, sizeof(VdbeSorterIter));
   167    171   }
   168    172   
   169    173   /*
   170    174   ** Read nByte bytes of data from the stream of data iterated by object p.
   171    175   ** If successful, set *ppOut to point to a buffer containing the data
   172    176   ** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite
................................................................................
   179    183     sqlite3 *db,                    /* Database handle (for malloc) */
   180    184     VdbeSorterIter *p,              /* Iterator */
   181    185     int nByte,                      /* Bytes of data to read */
   182    186     u8 **ppOut                      /* OUT: Pointer to buffer containing data */
   183    187   ){
   184    188     int iBuf;                       /* Offset within buffer to read from */
   185    189     int nAvail;                     /* Bytes of data available in buffer */
          190  +
          191  +  if( p->aMap ){
          192  +    *ppOut = &p->aMap[p->iReadOff];
          193  +    p->iReadOff += nByte;
          194  +    return SQLITE_OK;
          195  +  }
          196  +
   186    197     assert( p->aBuffer );
   187    198   
   188    199     /* If there is no more data to be read from the buffer, read the next 
   189    200     ** p->nBuffer bytes of data from the file into it. Or, if there are less
   190    201     ** than p->nBuffer bytes remaining in the PMA, read all remaining data.  */
   191    202     iBuf = p->iReadOff % p->nBuffer;
   192    203     if( iBuf==0 ){
................................................................................
   260    271   /*
   261    272   ** Read a varint from the stream of data accessed by p. Set *pnOut to
   262    273   ** the value read.
   263    274   */
   264    275   static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){
   265    276     int iBuf;
   266    277   
   267         -  iBuf = p->iReadOff % p->nBuffer;
   268         -  if( iBuf && (p->nBuffer-iBuf)>=9 ){
   269         -    p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
          278  +  if( p->aMap ){
          279  +    p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut);
   270    280     }else{
   271         -    u8 aVarint[16], *a;
   272         -    int i = 0, rc;
   273         -    do{
   274         -      rc = vdbeSorterIterRead(db, p, 1, &a);
   275         -      if( rc ) return rc;
   276         -      aVarint[(i++)&0xf] = a[0];
   277         -    }while( (a[0]&0x80)!=0 );
   278         -    sqlite3GetVarint(aVarint, pnOut);
          281  +    iBuf = p->iReadOff % p->nBuffer;
          282  +    if( iBuf && (p->nBuffer-iBuf)>=9 ){
          283  +      p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
          284  +    }else{
          285  +      u8 aVarint[16], *a;
          286  +      int i = 0, rc;
          287  +      do{
          288  +        rc = vdbeSorterIterRead(db, p, 1, &a);
          289  +        if( rc ) return rc;
          290  +        aVarint[(i++)&0xf] = a[0];
          291  +      }while( (a[0]&0x80)!=0 );
          292  +      sqlite3GetVarint(aVarint, pnOut);
          293  +    }
   279    294     }
   280    295   
   281    296     return SQLITE_OK;
   282    297   }
   283    298   
   284    299   
   285    300   /*
................................................................................
   319    334     const VdbeSorter *pSorter,      /* Sorter object */
   320    335     i64 iStart,                     /* Start offset in pFile */
   321    336     VdbeSorterIter *pIter,          /* Iterator to populate */
   322    337     i64 *pnByte                     /* IN/OUT: Increment this value by PMA size */
   323    338   ){
   324    339     int rc = SQLITE_OK;
   325    340     int nBuf;
          341  +  void *pMap;
   326    342   
   327    343     nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
   328    344   
   329    345     assert( pSorter->iWriteOff>iStart );
   330    346     assert( pIter->aAlloc==0 );
   331    347     assert( pIter->aBuffer==0 );
   332    348     pIter->pFile = pSorter->pTemp1;
   333    349     pIter->iReadOff = iStart;
   334    350     pIter->nAlloc = 128;
   335    351     pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc);
   336         -  pIter->nBuffer = nBuf;
   337         -  pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
   338    352   
   339         -  if( !pIter->aBuffer ){
   340         -    rc = SQLITE_NOMEM;
          353  +  /* See if this PMA can be read using xFetch. */
          354  +  rc = sqlite3OsFetch(pIter->pFile, 0, pSorter->iWriteOff, &pMap);
          355  +  if( rc!=SQLITE_OK ) return rc;
          356  +  if( pMap ){
          357  +    pIter->aMap = (u8*)pMap;
   341    358     }else{
   342         -    int iBuf;
          359  +    pIter->nBuffer = nBuf;
          360  +    pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf);
   343    361   
   344         -    iBuf = iStart % nBuf;
   345         -    if( iBuf ){
   346         -      int nRead = nBuf - iBuf;
   347         -      if( (iStart + nRead) > pSorter->iWriteOff ){
   348         -        nRead = (int)(pSorter->iWriteOff - iStart);
          362  +    if( !pIter->aBuffer ){
          363  +      rc = SQLITE_NOMEM;
          364  +    }else{
          365  +      int iBuf;
          366  +
          367  +      iBuf = iStart % nBuf;
          368  +      if( iBuf ){
          369  +        int nRead = nBuf - iBuf;
          370  +        if( (iStart + nRead) > pSorter->iWriteOff ){
          371  +          nRead = (int)(pSorter->iWriteOff - iStart);
          372  +        }
          373  +        rc = sqlite3OsRead(
          374  +            pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
          375  +        );
          376  +        assert( rc!=SQLITE_IOERR_SHORT_READ );
   349    377         }
   350         -      rc = sqlite3OsRead(
   351         -          pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
   352         -      );
   353         -      assert( rc!=SQLITE_IOERR_SHORT_READ );
   354    378       }
          379  +  }
   355    380   
   356         -    if( rc==SQLITE_OK ){
   357         -      u64 nByte;                       /* Size of PMA in bytes */
   358         -      pIter->iEof = pSorter->iWriteOff;
   359         -      rc = vdbeSorterIterVarint(db, pIter, &nByte);
   360         -      pIter->iEof = pIter->iReadOff + nByte;
   361         -      *pnByte += nByte;
   362         -    }
          381  +  if( rc==SQLITE_OK ){
          382  +    u64 nByte;                       /* Size of PMA in bytes */
          383  +    pIter->iEof = pSorter->iWriteOff;
          384  +    rc = vdbeSorterIterVarint(db, pIter, &nByte);
          385  +    pIter->iEof = pIter->iReadOff + nByte;
          386  +    *pnByte += nByte;
   363    387     }
   364    388   
   365    389     if( rc==SQLITE_OK ){
   366    390       rc = vdbeSorterIterNext(db, pIter);
   367    391     }
   368    392     return rc;
   369    393   }
................................................................................
   484    508   
   485    509     if( !sqlite3TempInMemory(db) ){
   486    510       pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
   487    511       pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz;
   488    512       mxCache = db->aDb[0].pSchema->cache_size;
   489    513       if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
   490    514       pSorter->mxPmaSize = mxCache * pgsz;
          515  +
          516  +    pSorter->aMemory = (u8*)sqlite3DbMallocRaw(db, pSorter->mxPmaSize);
          517  +    assert( pSorter->iMemory==0 );
          518  +    if( !pSorter->aMemory ) return SQLITE_NOMEM;
   491    519     }
   492    520   
   493    521     return SQLITE_OK;
   494    522   }
   495    523   
   496    524   /*
   497    525   ** Free the list of sorted records starting at pRecord.
................................................................................
   517    545       sqlite3DbFree(db, pSorter->aIter);
   518    546       pSorter->aIter = 0;
   519    547     }
   520    548     if( pSorter->pTemp1 ){
   521    549       sqlite3OsCloseFree(pSorter->pTemp1);
   522    550       pSorter->pTemp1 = 0;
   523    551     }
   524         -  vdbeSorterRecordFree(db, pSorter->pRecord);
          552  +  if( pSorter->aMemory==0 ){
          553  +    vdbeSorterRecordFree(db, pSorter->pRecord);
          554  +  }
   525    555     pSorter->pRecord = 0;
   526    556     pSorter->iWriteOff = 0;
   527    557     pSorter->iReadOff = 0;
   528    558     pSorter->nInMemory = 0;
   529    559     pSorter->nTree = 0;
   530    560     pSorter->nPMA = 0;
   531    561     pSorter->aTree = 0;
          562  +  pSorter->iMemory = 0;
   532    563   }
   533    564   
   534    565   
   535    566   /*
   536    567   ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
   537    568   */
   538    569   void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
   539    570     VdbeSorter *pSorter = pCsr->pSorter;
   540    571     if( pSorter ){
   541    572       sqlite3VdbeSorterReset(db, pSorter);
   542    573       sqlite3DbFree(db, pSorter->pUnpacked);
          574  +    sqlite3DbFree(db, pSorter->aMemory);
   543    575       sqlite3DbFree(db, pSorter);
   544    576       pCsr->pSorter = 0;
   545    577     }
   546    578   }
   547    579   
   548    580   /*
   549    581   ** Allocate space for a file-handle and open a temporary file. If successful,
   550    582   ** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK.
   551    583   ** Otherwise, set *ppFile to 0 and return an SQLite error code.
   552    584   */
   553    585   static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
   554         -  int dummy;
   555         -  return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
          586  +  int rc;
          587  +  rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFile,
   556    588         SQLITE_OPEN_TEMP_JOURNAL |
   557    589         SQLITE_OPEN_READWRITE    | SQLITE_OPEN_CREATE |
   558         -      SQLITE_OPEN_EXCLUSIVE    | SQLITE_OPEN_DELETEONCLOSE, &dummy
          590  +      SQLITE_OPEN_EXCLUSIVE    | SQLITE_OPEN_DELETEONCLOSE, &rc
   559    591     );
          592  +  if( rc==SQLITE_OK ){
          593  +    i64 max = SQLITE_MAX_MMAP_SIZE;
          594  +    sqlite3OsFileControlHint( *ppFile, SQLITE_FCNTL_MMAP_SIZE, (void*)&max);
          595  +  }
          596  +  return rc;
   560    597   }
   561    598   
   562    599   /*
   563    600   ** Merge the two sorted lists p1 and p2 into a single list.
   564    601   ** Set *ppOut to the head of the new list.
   565    602   **
   566    603   ** In cases where key values are equal, keys from list p1 are considered
................................................................................
   721    758   static void fileWriterWriteVarint(FileWriter *p, u64 iVal){
   722    759     int nByte; 
   723    760     u8 aByte[10];
   724    761     nByte = sqlite3PutVarint(aByte, iVal);
   725    762     fileWriterWrite(p, aByte, nByte);
   726    763   }
   727    764   
          765  +#if SQLITE_MAX_MMAP_SIZE>0
          766  +/*
          767  +** The first argument is a file-handle open on a temporary file. The file
          768  +** is guaranteed to be nByte bytes or smaller in size. This function 
          769  +** attempts to extend the file to nByte bytes in size and to ensure that
          770  +** the VFS has memory mapped it.
          771  +**
          772  +** Whether or not the file does end up memory mapped of course depends on 
          773  +** the specific VFS implementation.
          774  +*/
          775  +static int vdbeSorterExtendFile(sqlite3_file *pFile, i64 nByte){
          776  +  int rc = sqlite3OsTruncate(pFile, nByte);
          777  +  if( rc==SQLITE_OK ){
          778  +    void *p = 0;
          779  +    sqlite3OsFetch(pFile, 0, nByte, &p);
          780  +    sqlite3OsUnfetch(pFile, 0, p);
          781  +  }
          782  +  return rc;
          783  +}
          784  +#else
          785  +# define vdbeSorterExtendFile(x,y) SQLITE_OK
          786  +#endif
          787  +
   728    788   /*
   729    789   ** Write the current contents of the in-memory linked-list to a PMA. Return
   730    790   ** SQLITE_OK if successful, or an SQLite error code otherwise.
   731    791   **
   732    792   ** The format of a PMA is:
   733    793   **
   734    794   **     * A varint. This varint contains the total number of bytes of content
................................................................................
   755    815     /* If the first temporary PMA file has not been opened, open it now. */
   756    816     if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
   757    817       rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1);
   758    818       assert( rc!=SQLITE_OK || pSorter->pTemp1 );
   759    819       assert( pSorter->iWriteOff==0 );
   760    820       assert( pSorter->nPMA==0 );
   761    821     }
          822  +
          823  +  /* Try to get the file to memory map */
          824  +  if( rc==SQLITE_OK ){
          825  +    rc = vdbeSorterExtendFile(
          826  +        pSorter->pTemp1, pSorter->iWriteOff + pSorter->nInMemory + 9
          827  +    );
          828  +  }
   762    829   
   763    830     if( rc==SQLITE_OK ){
   764    831       SorterRecord *p;
   765    832       SorterRecord *pNext = 0;
   766    833   
   767    834       fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff);
   768    835       pSorter->nPMA++;
   769    836       fileWriterWriteVarint(&writer, pSorter->nInMemory);
   770    837       for(p=pSorter->pRecord; p; p=pNext){
   771    838         pNext = p->pNext;
   772    839         fileWriterWriteVarint(&writer, p->nVal);
   773    840         fileWriterWrite(&writer, p->pVal, p->nVal);
   774         -      sqlite3DbFree(db, p);
          841  +      if( pSorter->aMemory==0 ) sqlite3DbFree(db, p);
   775    842       }
   776    843       pSorter->pRecord = p;
   777    844       rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff);
   778    845     }
   779    846   
          847  +  if( pSorter->aMemory ) pSorter->pRecord = 0;
          848  +  assert( pSorter->pRecord==0 || rc!=SQLITE_OK );
   780    849     return rc;
   781    850   }
   782    851   
   783    852   /*
   784    853   ** Add a record to the sorter.
   785    854   */
   786    855   int sqlite3VdbeSorterWrite(
   787    856     sqlite3 *db,                    /* Database handle */
   788    857     const VdbeCursor *pCsr,               /* Sorter cursor */
   789    858     Mem *pVal                       /* Memory cell containing record */
   790    859   ){
   791    860     VdbeSorter *pSorter = pCsr->pSorter;
          861  +  SorterRecord sRecord;           /* Used for aMemory overflow record */
   792    862     int rc = SQLITE_OK;             /* Return Code */
   793    863     SorterRecord *pNew;             /* New list element */
   794    864   
   795    865     assert( pSorter );
   796    866     pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n;
   797    867   
   798         -  pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord));
   799         -  if( pNew==0 ){
   800         -    rc = SQLITE_NOMEM;
          868  +  if( pSorter->aMemory ){
          869  +    int nReq = sizeof(SorterRecord) + pVal->n;
          870  +    if( (pSorter->iMemory+nReq) > pSorter->mxPmaSize ){
          871  +      pNew = &sRecord;
          872  +      pNew->pVal = pVal->z;
          873  +    }else{
          874  +      pNew = &pSorter->aMemory[pSorter->iMemory];
          875  +      pSorter->iMemory += ROUND8(nReq);
          876  +    }
   801    877     }else{
   802         -    pNew->pVal = (void *)&pNew[1];
          878  +    pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n+sizeof(SorterRecord));
          879  +    if( pNew==0 ){
          880  +      return SQLITE_NOMEM;
          881  +    }
          882  +  }
          883  +
          884  +  if( pNew!=&sRecord ){
          885  +    pNew->pVal = (void*)&pNew[1];
   803    886       memcpy(pNew->pVal, pVal->z, pVal->n);
   804         -    pNew->nVal = pVal->n;
   805         -    pNew->pNext = pSorter->pRecord;
   806         -    pSorter->pRecord = pNew;
   807    887     }
          888  +  pNew->nVal = pVal->n;
          889  +  pNew->pNext = pSorter->pRecord;
          890  +  pSorter->pRecord = pNew;
   808    891   
   809    892     /* See if the contents of the sorter should now be written out. They
   810    893     ** are written out when either of the following are true:
   811    894     **
   812    895     **   * The total memory allocated for the in-memory list is greater 
   813    896     **     than (page-size * cache-size), or
   814    897     **
   815    898     **   * The total memory allocated for the in-memory list is greater 
   816    899     **     than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
   817    900     */
   818         -  if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
   819         -        (pSorter->nInMemory>pSorter->mxPmaSize)
   820         -     || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull())
   821         -  )){
          901  +  if( pSorter->mxPmaSize>0 ){
          902  +    if( (pNew==&sRecord) || (pSorter->aMemory==0 && (
          903  +        (pSorter->nInMemory > pSorter->mxPmaSize)
          904  +     || (pSorter->nInMemory > pSorter->mnPmaSize && sqlite3HeapNearlyFull())
          905  +    ))){
   822    906   #ifdef SQLITE_DEBUG
   823         -    i64 nExpect = pSorter->iWriteOff
   824         -                + sqlite3VarintLen(pSorter->nInMemory)
   825         -                + pSorter->nInMemory;
          907  +      i64 nExpect = pSorter->iWriteOff
          908  +        + sqlite3VarintLen(pSorter->nInMemory)
          909  +        + pSorter->nInMemory;
   826    910   #endif
   827         -    rc = vdbeSorterListToPMA(db, pCsr);
   828         -    pSorter->nInMemory = 0;
   829         -    assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) );
          911  +      rc = vdbeSorterListToPMA(db, pCsr);
          912  +      pSorter->nInMemory = 0;
          913  +      pSorter->iMemory = 0;
          914  +      assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) );
          915  +      assert( rc!=SQLITE_OK || pSorter->pRecord==0 );
          916  +    }
   830    917     }
   831    918   
   832    919     return rc;
   833    920   }
   834    921   
   835    922   /*
   836    923   ** Helper function for sqlite3VdbeSorterRewind(). 
................................................................................
   930   1017           break;
   931   1018         }
   932   1019   
   933   1020         /* Open the second temp file, if it is not already open. */
   934   1021         if( pTemp2==0 ){
   935   1022           assert( iWrite2==0 );
   936   1023           rc = vdbeSorterOpenTempFile(db, &pTemp2);
         1024  +        if( rc==SQLITE_OK ){
         1025  +          rc = vdbeSorterExtendFile(pTemp2, pSorter->iWriteOff);
         1026  +        }
   937   1027         }
   938   1028   
   939   1029         if( rc==SQLITE_OK ){
   940   1030           int bEof = 0;
   941   1031           fileWriterInit(db, pTemp2, &writer, iWrite2);
   942   1032           fileWriterWriteVarint(&writer, nWrite);
   943   1033           while( rc==SQLITE_OK && bEof==0 ){
................................................................................
  1035   1125         }
  1036   1126         *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
  1037   1127       }
  1038   1128     }else{
  1039   1129       SorterRecord *pFree = pSorter->pRecord;
  1040   1130       pSorter->pRecord = pFree->pNext;
  1041   1131       pFree->pNext = 0;
  1042         -    vdbeSorterRecordFree(db, pFree);
         1132  +    if( pSorter->aMemory==0 ){
         1133  +      vdbeSorterRecordFree(db, pFree);
         1134  +    }
  1043   1135       *pbEof = !pSorter->pRecord;
  1044   1136       rc = SQLITE_OK;
  1045   1137     }
  1046   1138     return rc;
  1047   1139   }
  1048   1140   
  1049   1141   /*