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

Overview
Comment:Fix a memory leak in LSM.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8a39847dafa3047ba5d6107f0032c6b39d0ef104
User & Date: dan 2014-05-07 09:49:52.421
Context
2014-05-12
21:07
Added -lm to the build flags for Makefile.gcc-linux, based on ML feedback. check-in: 26964761e2 user: stephan tags: trunk
2014-05-07
09:49
Fix a memory leak in LSM. check-in: 8a39847daf user: dan tags: trunk
2014-03-18
19:29
Fix an important typo in the varint decoder documentation. check-in: f392aec8a5 user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to lsm-test/sqltest.c.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77


78
79
80
81
82
83
84
**     CREATE TABLE t1(k PRIMARY KEY, c0 BLOB, c1 BLOB, v BLOB);
**     CREATE INDEX i0 ON t1(c0);
**     CREATE INDEX i1 ON t1(c1);
**
** where the number of "c" columns (and indexes) is determined by the nIdx
** argument. The example above is as would be returned for nIdx==2.
*/
static char *create_schema_sql(int nIdx){
  char *zSchema;
  int i;

  zSchema = sqlite4_mprintf(0, "CREATE TABLE t1(k PRIMARY KEY,");
  for(i=0; i<nIdx; i++){
    zSchema = sqlite4_mprintf(0, "%z c%d BLOB,", zSchema, i);
  }
  zSchema = sqlite4_mprintf(0, "%z v BLOB);", zSchema);



  for(i=0; i<nIdx; i++){
    zSchema = sqlite4_mprintf(
      0, "%z\nCREATE INDEX i%d ON t1 (c%d);", zSchema, i, i
    );
  }








|







|
>
>







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
**     CREATE TABLE t1(k PRIMARY KEY, c0 BLOB, c1 BLOB, v BLOB);
**     CREATE INDEX i0 ON t1(c0);
**     CREATE INDEX i1 ON t1(c1);
**
** where the number of "c" columns (and indexes) is determined by the nIdx
** argument. The example above is as would be returned for nIdx==2.
*/
static char *create_schema_sql(int nIdx, int bWithoutRowid){
  char *zSchema;
  int i;

  zSchema = sqlite4_mprintf(0, "CREATE TABLE t1(k PRIMARY KEY,");
  for(i=0; i<nIdx; i++){
    zSchema = sqlite4_mprintf(0, "%z c%d BLOB,", zSchema, i);
  }
  zSchema = sqlite4_mprintf(0, "%z v BLOB)%s;", zSchema,
      (bWithoutRowid ? " WITHOUT ROWID" : "")
  );

  for(i=0; i<nIdx; i++){
    zSchema = sqlite4_mprintf(
      0, "%z\nCREATE INDEX i%d ON t1 (c%d);", zSchema, i, i
    );
  }

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  sqlite4_kvstore_control(db, "main", SQLITE4_KVCTRL_LSM_HANDLE, &pLsm);
  i = iSync;
  lsm_config(pLsm, LSM_CONFIG_SAFETY, &i);
  assert( i==iSync );

  install_rblob_function4(db);

  zCreateTbl = create_schema_sql(nIdx);
  zInsert = create_insert_sql(nIdx);

  /* Create the db schema and prepare the INSERT statement */
  EXPLODE(  sqlite4_exec(db, zCreateTbl, 0, 0)  );
  EXPLODE(  sqlite4_prepare(db, zInsert, -1, &pInsert, 0)  );

  /* Run the test */







|







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  sqlite4_kvstore_control(db, "main", SQLITE4_KVCTRL_LSM_HANDLE, &pLsm);
  i = iSync;
  lsm_config(pLsm, LSM_CONFIG_SAFETY, &i);
  assert( i==iSync );

  install_rblob_function4(db);

  zCreateTbl = create_schema_sql(nIdx, 0);
  zInsert = create_insert_sql(nIdx);

  /* Create the db schema and prepare the INSERT statement */
  EXPLODE(  sqlite4_exec(db, zCreateTbl, 0, 0)  );
  EXPLODE(  sqlite4_prepare(db, zInsert, -1, &pInsert, 0)  );

  /* Run the test */
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  EXPLODE( sqlite3_exec(db, "PRAGMA journal_mode=WAL", 0, 0, 0) );
  zSync = sqlite4_mprintf(0, "PRAGMA synchronous=%d", iSync);
  EXPLODE( sqlite3_exec(db, zSync, 0, 0, 0) );
  sqlite4_free(0, zSync);

  install_rblob_function3(db);

  zCreateTbl = create_schema_sql(nIdx);
  zInsert = create_insert_sql(nIdx);

  /* Create the db schema and prepare the INSERT statement */
  EXPLODE(  sqlite3_exec(db, zCreateTbl, 0, 0, 0)  );
  EXPLODE(  sqlite3_prepare(db, zInsert, -1, &pInsert, 0)  );

  /* Run the test */







|







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  EXPLODE( sqlite3_exec(db, "PRAGMA journal_mode=WAL", 0, 0, 0) );
  zSync = sqlite4_mprintf(0, "PRAGMA synchronous=%d", iSync);
  EXPLODE( sqlite3_exec(db, zSync, 0, 0, 0) );
  sqlite4_free(0, zSync);

  install_rblob_function3(db);

  zCreateTbl = create_schema_sql(nIdx, 1);
  zInsert = create_insert_sql(nIdx);

  /* Create the db schema and prepare the INSERT statement */
  EXPLODE(  sqlite3_exec(db, zCreateTbl, 0, 0, 0)  );
  EXPLODE(  sqlite3_prepare(db, zInsert, -1, &pInsert, 0)  );

  /* Run the test */
Changes to src/bt_main.c.
3722
3723
3724
3725
3726
3727
3728


3729
3730
3731

3732
3733
3734
3735
3736
3737
3738
        pHdr->iSubBlock = 0;
      }
    }
    if( rc==SQLITE4_OK && pCsr->nPg==1 ){
      rc = btExtendTree(pCsr);
    }
    if( rc==SQLITE4_OK ){


      if( bLeaf==0 || SQLITE4_NOTFOUND==(rc = btTryAppend(pCsr, nKV, apKV)) ){
        rc = btBalance(pCsr, bLeaf, nKV, apKV);
      }

    }
  }

  return rc;
}

static int btDeleteFromPage(BtCursor *pCsr, int nDel){







>
>



>







3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
        pHdr->iSubBlock = 0;
      }
    }
    if( rc==SQLITE4_OK && pCsr->nPg==1 ){
      rc = btExtendTree(pCsr);
    }
    if( rc==SQLITE4_OK ){
      rc = btBalance(pCsr, bLeaf, nKV, apKV);
#if 0
      if( bLeaf==0 || SQLITE4_NOTFOUND==(rc = btTryAppend(pCsr, nKV, apKV)) ){
        rc = btBalance(pCsr, bLeaf, nKV, apKV);
      }
#endif
    }
  }

  return rc;
}

static int btDeleteFromPage(BtCursor *pCsr, int nDel){
Changes to src/lsm_file.c.
757
758
759
760
761
762
763








764
765
766
767
768
769
770
    pPg = pFS->pLruFirst;
    while( pPg ){
      Page *pNext = pPg->pLruNext;
      if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }









    if( pFS->fdDb ) lsmEnvClose(pFS->pEnv, pFS->fdDb );
    if( pFS->fdLog ) lsmEnvClose(pFS->pEnv, pFS->fdLog );
    lsmFree(pEnv, pFS->pLsmFile);
    lsmFree(pEnv, pFS->apHash);
    lsmFree(pEnv, pFS->aIBuffer);
    lsmFree(pEnv, pFS->aOBuffer);







>
>
>
>
>
>
>
>







757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
    pPg = pFS->pLruFirst;
    while( pPg ){
      Page *pNext = pPg->pLruNext;
      if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    pPg = pFS->pFree;
    while( pPg ){
      Page *pNext = pPg->pFreeNext;
      if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    if( pFS->fdDb ) lsmEnvClose(pFS->pEnv, pFS->fdDb );
    if( pFS->fdLog ) lsmEnvClose(pFS->pEnv, pFS->fdLog );
    lsmFree(pEnv, pFS->pLsmFile);
    lsmFree(pEnv, pFS->apHash);
    lsmFree(pEnv, pFS->aIBuffer);
    lsmFree(pEnv, pFS->aOBuffer);
Changes to test/selectF.test.
1
2
3
4
5
6
7
8
9
10
11


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



27
28
29
30
31
32
33
34
35
36
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
# 2013 June 12
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# 


# Test cases for SELECT statements.
#

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

# Evaluate the SQL query passed as the only argument using database
# connection [db]. Return any results as a list of lists - one list
# element for each row. i.e.
#
#   "SELECT 1, 2 UNION SELECT 3, 4" -> "{1 2} {3 4}"
#
proc eval_to_list {bOrdered sql} {
  set sqlresult [list]



  db eval $sql a {
    set row [list]
    foreach c $a(*) { lappend row $a($c) }
    lappend sqlresult $row
  }
  if {!$bOrdered} {set sqlresult [lsort $sqlresult]}
  set sqlresult
}

# Execute SELECT query $zSql using [eval_to_list] and compare the results
# to $lRes. If argument $bOrdered is false, this indicates that the order
# of results is non-deterministic. In this case the results are passed
# to [lsort] before they are compared to $lRes.
#
proc do_select_test {testname bOrdered zSql lRes} {
  uplevel [list do_test $testname [list eval_to_list $bOrdered $zSql] $lRes]
}

# The SELECT tests in this file all use the following command. See the
# example below for details.
#
proc do_select_test_set {tn data indexes tests} {
  db_delete_and_reopen
  execsql $data
  db_save_and_close

  if {$tn=="*"} {
    foreach {tn2 bOrder sql res} $tests {
      puts "$tn2 $bOrder \"$sql\" {[eval_to_list $bOrder $sql]}"

    }
  } else {
    foreach {tn1 sql} $indexes {
      db_restore_and_reopen
      foreach {tn2 bOrder sql res} $tests {
        do_select_test $tn.$tn1.$tn2 $bOrder $sql $res
      }
    }
  }
}



#--------------------------------------------------------------------
# Warm-body tests. This block serves as an example of how to use
# the [do_select_test_set] command.
#
do_select_test_set 1 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(2, 4,  6);
  INSERT INTO t1 VALUES(1, 2,  3);
  INSERT INTO t1 VALUES(4, 8,  12);
  INSERT INTO t1 VALUES(3, 6,  9);
  INSERT INTO t1 VALUES(6, 12, 18);
  INSERT INTO t1 VALUES(5, 10, 15);
} {
  1 { }
  2 { CREATE INDEX ON t1(a, b, c) }
  3 { CREATE INDEX ON t1(c, b, a) }
  4 { 
    CREATE INDEX ON t1(a);
    CREATE INDEX ON t1(b);
    CREATE INDEX ON t1(c);
  }
} {

1 0 "SELECT * FROM t1 WHERE a = 2" {{2 4 6}}

2 0 "SELECT * FROM t1 WHERE a < 4" {{1 2 3} {2 4 6} {3 6 9}}
3 0 "SELECT * FROM t1 WHERE a = b/2 AND c%2" {{1 2 3} {3 6 9} {5 10 15}}
4 0 "SELECT (a/2) FROM t1 GROUP BY (a/2)" {0 1 2 3}
5 0 "SELECT a+b FROM t1 GROUP BY (a+b)" {12 15 18 3 6 9}
6 1 "SELECT a+b FROM t1 GROUP BY (a+b) ORDER BY 1" {3 6 9 12 15 18}
7 0 "SELECT a*b FROM t1 WHERE (c%2)" {18 2 50}
8 0 "SELECT count(*) FROM t1, t1 AS t2 WHERE t1.a=t2.a" {6}
9 0 "SELECT * FROM t1 WHERE a=1 AND b=2" {{1 2 3}}
10 0 "SELECT * FROM t1 WHERE a>3 AND b<12" {{4 8 12} {5 10 15}}

11 1 "SELECT a FROM t1 ORDER BY a" {1 2 3 4 5 6}
12 1 "SELECT a FROM t1 ORDER BY +a" {1 2 3 4 5 6}
13 1 "SELECT a FROM t1 ORDER BY b DESC" {6 5 4 3 2 1}

}

finish_test

|









|
>
>
|






<
<
<
<
<
<
<
|
>
>
>
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
>
|
<
<
<
<
<
<
|
<
<
|
>
>
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
>
|
>
|
<
<
<
|
<
<
<
<
|
<
<
<

|
|

<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20







21
22
23
24
25







26








27


28




29



30
31






32


33
34
35
36
37

38
















39

40
41
42
43



44




45



46
47
48
49

# 2014-03-03
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file verifies that an OP_Copy operation is used instead of OP_SCopy
# in a compound select in a case where the source register might be changed
# before the copy is used.
#

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








do_execsql_test 1 {
  BEGIN TRANSACTION;
  CREATE TABLE t1(a, b, c);
  INSERT INTO "t1" VALUES(1,'one','I');
  CREATE TABLE t2(d, e, f);







  INSERT INTO "t2" VALUES(5,'ten','XX');








  INSERT INTO "t2" VALUES(6,NULL,NULL);







  CREATE INDEX i1 ON t1(b, a);



  COMMIT;
}









#explain_i {
#  SELECT * FROM t2
#  UNION ALL 
#  SELECT * FROM t1 WHERE a<5 
#  ORDER BY 2, 1

#}


















do_execsql_test 2 {
  SELECT * FROM t2
  UNION ALL 
  SELECT * FROM t1 WHERE a<5 



  ORDER BY 2, 1




} {6 {} {} 1 one I 5 ten XX}





  
finish_test