SQLite

Check-in [39dd67afa5]
Login

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

Overview
Comment:Correctly interpret negative "PRAGMA cache_size" values when determining the cache-size used for sorting large amounts of data (i.e. the functionality in vdbesort.c).
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | branch-3.12.0
Files: files | file ages | folders
SHA1: 39dd67afa508aea8f41387806b263b760512377f
User & Date: drh 2016-04-18 16:18:13.574
Context
2016-04-18
17:30
Version 3.12.2 (Leaf check-in: 92dc59fd5a user: drh tags: release, branch-3.12.0, version-3.12.2)
16:18
Correctly interpret negative "PRAGMA cache_size" values when determining the cache-size used for sorting large amounts of data (i.e. the functionality in vdbesort.c). (check-in: 39dd67afa5 user: drh tags: branch-3.12.0)
16:12
Fix a problem in the code generator for joins on virtual tables where the outer loop of the join uses the IN operator. (check-in: a2cf496896 user: drh tags: branch-3.12.0)
2016-04-14
15:44
Correctly interpret negative "PRAGMA cache_size" values when determining the cache-size used for sorting large amounts of data (i.e. the functionality in vdbesort.c). (check-in: 79147dca87 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbesort.c.
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
int sqlite3VdbeSorterInit(
  sqlite3 *db,                    /* Database connection (for malloc()) */
  int nField,                     /* Number of key fields in each record */
  VdbeCursor *pCsr                /* Cursor that holds the new sorter */
){
  int pgsz;                       /* Page size of main database */
  int i;                          /* Used to iterate through aTask[] */
  int mxCache;                    /* Cache size */
  VdbeSorter *pSorter;            /* The new sorter */
  KeyInfo *pKeyInfo;              /* Copy of pCsr->pKeyInfo with db==0 */
  int szKeyInfo;                  /* Size of pCsr->pKeyInfo in bytes */
  int sz;                         /* Size of pSorter in bytes */
  int rc = SQLITE_OK;
#if SQLITE_MAX_WORKER_THREADS==0
# define nWorker 0







<







927
928
929
930
931
932
933

934
935
936
937
938
939
940
int sqlite3VdbeSorterInit(
  sqlite3 *db,                    /* Database connection (for malloc()) */
  int nField,                     /* Number of key fields in each record */
  VdbeCursor *pCsr                /* Cursor that holds the new sorter */
){
  int pgsz;                       /* Page size of main database */
  int i;                          /* Used to iterate through aTask[] */

  VdbeSorter *pSorter;            /* The new sorter */
  KeyInfo *pKeyInfo;              /* Copy of pCsr->pKeyInfo with db==0 */
  int szKeyInfo;                  /* Size of pCsr->pKeyInfo in bytes */
  int sz;                         /* Size of pSorter in bytes */
  int rc = SQLITE_OK;
#if SQLITE_MAX_WORKER_THREADS==0
# define nWorker 0
984
985
986
987
988
989
990

991
992

993
994






995

996
997
998
999
1000
1001
1002
    pSorter->db = db;
    for(i=0; i<pSorter->nTask; i++){
      SortSubtask *pTask = &pSorter->aTask[i];
      pTask->pSorter = pSorter;
    }

    if( !sqlite3TempInMemory(db) ){

      u32 szPma = sqlite3GlobalConfig.szPma;
      pSorter->mnPmaSize = szPma * pgsz;

      mxCache = db->aDb[0].pSchema->cache_size;
      if( mxCache<(int)szPma ) mxCache = (int)szPma;






      pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);


      /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
      ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
      ** large heap allocations.
      */
      if( sqlite3GlobalConfig.pScratch==0 ){
        assert( pSorter->iMemory==0 );







>


>

|
>
>
>
>
>
>
|
>







983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
    pSorter->db = db;
    for(i=0; i<pSorter->nTask; i++){
      SortSubtask *pTask = &pSorter->aTask[i];
      pTask->pSorter = pSorter;
    }

    if( !sqlite3TempInMemory(db) ){
      i64 mxCache;                /* Cache size in bytes*/
      u32 szPma = sqlite3GlobalConfig.szPma;
      pSorter->mnPmaSize = szPma * pgsz;

      mxCache = db->aDb[0].pSchema->cache_size;
      if( mxCache<0 ){
        /* A negative cache-size value C indicates that the cache is abs(C)
        ** KiB in size.  */
        mxCache = mxCache * -1024;
      }else{
        mxCache = mxCache * pgsz;
      }
      mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
      pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);

      /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
      ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
      ** large heap allocations.
      */
      if( sqlite3GlobalConfig.pScratch==0 ){
        assert( pSorter->iMemory==0 );
Changes to test/sort5.test.
37
38
39
40
41
42
43







































































44


do_execsql_test 1.2 {
  CREATE INDEX i1 ON t1(b);
}

db close
tvfs delete







































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

do_execsql_test 1.2 {
  CREATE INDEX i1 ON t1(b);
}

db close
tvfs delete

#-------------------------------------------------------------------------
# Test that the PMA size is determined correctly. The PMA size should be
# roughly the same amount of memory allocated to the main pager cache, or
# 250 pages if this is larger.
#
testvfs tvfs
tvfs script tv_callback
tvfs filter {xOpen xWrite}

proc tv_callback {method args} {
  global iTemp
  global F
  switch $method {
    xOpen {
      if {[lindex $args 0]==""} { return "temp[incr iTemp]" }
      return "SQLITE_OK"
    }

    xWrite {
      foreach {filename id off amt} $args {}
      if {[info exists F($id)]==0 || $F($id)<($off + $amt)} {
        set F($id) [expr $off+$amt]
      }
    }
  }
}

catch { db close }
forcedelete test.db
sqlite3 db test.db -vfs tvfs
execsql { CREATE TABLE t1(x) }

# Each iteration of the following loop attempts to sort 10001 records
# each a bit over 100 bytes in size. In total a little more than 1MiB 
# of data.
#
breakpoint
foreach {tn pgsz cachesz bTemp} {
  2 1024   1000  1

  1 4096   1000  0
  2 1024   1000  1

  3 4096  -1000  1
  4 1024  -1000  1

  5 4096  -9000  0
  6 1024  -9000  0
} {
  do_execsql_test 2.$tn.0 "
    PRAGMA page_size = $pgsz;
    VACUUM;
    PRAGMA cache_size = $cachesz;
  "

  do_test 2.$tn.1 {
    set ::iTemp 0
    catch { array unset F }
    execsql {
      WITH x(i, j) AS (
        SELECT 1, randomblob(100)
        UNION ALL
        SELECT i+1, randomblob(100) FROM x WHERE i<10000
      )
      SELECT * FROM x ORDER BY j;
    }
    expr {[array names F]!=""}
  } $bTemp
}

finish_test