SQLite

Check-in [2f58c8c972]
Login

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

Overview
Comment:Fix a memory leak caused by duplicate entries in the sqlite_stat1 table.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2f58c8c9722fffc486610f9e6b08178d53a56b64
User & Date: dan 2015-04-20 15:13:08.018
Context
2015-04-20
18:58
Many new configuration options for fuzzershell. (check-in: 41c9543916 user: drh tags: trunk)
15:13
Fix a memory leak caused by duplicate entries in the sqlite_stat1 table. (check-in: 2f58c8c972 user: dan tags: trunk)
13:59
Fix an obscure memory leak in sqlite3Stat4ProbeFree() (check-in: c72abbe2c1 user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/analyze.c.
1515
1516
1517
1518
1519
1520
1521

1522
1523



1524
1525


1526
1527

1528
1529


1530
1531
1532
1533
1534
1535
1536
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527


1528
1529


1530


1531
1532
1533
1534
1535
1536
1537
1538
1539







+


+
+
+
-
-
+
+
-
-
+
-
-
+
+







    pIndex = sqlite3PrimaryKeyIndex(pTable);
  }else{
    pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
  }
  z = argv[2];

  if( pIndex ){
    tRowcnt *aiRowEst = 0;
    int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    /* Index.aiRowEst may already be set here if there are duplicate 
    ** sqlite_stat1 entries for this index. In that case just clobber
    ** the old data with the new instead of allocating a new array.  */
    tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
        sizeof(tRowcnt) * nCol
    if( pIndex->aiRowEst==0 ){
      pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
    );
    if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
      if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
#else
    tRowcnt * const aiRowEst = 0;
    }
    aiRowEst = pIndex->aiRowEst;
#endif
    pIndex->bUnordered = 0;
    decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
    if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
  }else{
    Index fakeIdx;
    fakeIdx.szIdxRow = pTable->szTabRow;
Changes to test/analyze3.test.
12
13
14
15
16
17
18

19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26







+







# This file implements regression tests for SQLite library. This file 
# implements tests for range and LIKE constraints that use bound variables
# instead of literal constant arguments.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix analyze3

ifcapable !stat4&&!stat3 {
  finish_test
  return
}

#----------------------------------------------------------------------
41
42
43
44
45
46
47



48
49
50
51
52
53
54
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+
+
+







#               within sqlite3Reprepare() are handled correctly.
#
# analyze3-5.*: Check that the query plans of applicable statements are
#               invalidated if the values of SQL parameter are modified
#               using the clear_bindings() or transfer_bindings() APIs.
# 
# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
#
# analyze3-7.*: Test that some memory leaks discovered by fuzz testing 
#               have been fixed.
#

proc getvar {varname} { uplevel #0 set $varname }
db function var getvar

proc eqp {sql {db db}} {
  uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
670
671
672
673
674
675
676
677













678
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695








+
+
+
+
+
+
+
+
+
+
+
+
+

  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1,1,'0000');
  CREATE INDEX t0b ON t1(b);
  ANALYZE;
  SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1);
} {}

# At one point duplicate stat1 entries were causing a memory leak.
#
reset_db
do_execsql_test 7.2 {
  CREATE TABLE t1(a,b,c);
  CREATE INDEX t1a ON t1(a);
  ANALYZE;
  SELECT * FROM sqlite_stat1;
  INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
  INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
  ANALYZE sqlite_master;
}

finish_test