SQLite4
Check-in [d9560b73de51f4f4c085659af2c0e18d012375df]
Not logged in

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

Overview
SHA1 Hash:d9560b73de51f4f4c085659af2c0e18d012375df
Date: 2014-02-15 20:29:44
User: dan
Comment:Defer opening a bt database until it is first read.
Tags And Properties
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/kvbt.c

22
23
24
25
26
27
28



29
30
31
32
33
34
35
..
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
..
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
117
...
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229

230
231
232
233
234

235
236
237
238
239
240
241
...
278
279
280
281
282
283
284

285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
typedef struct KVBtCsr KVBtCsr;

/*
** An instance of an open connection to a bt_db store.  A subclass of KVStore.
*/
struct KVBt {
  KVStore base;                   /* Base class, must be first */



  bt_db *pDb;                     /* Database handle */
};

/*
** An instance of an open cursor pointing into an LSM store.  A subclass
** of KVCursor.
*/
................................................................................
  
/*
** Begin a transaction or subtransaction.
*/
static int btBegin(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;








  rc = sqlite4BtBegin(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Commit a transaction or subtransaction.
................................................................................
*/
static int btCommitPhaseOne(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}
static int btCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;

  rc = sqlite4BtCommit(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Rollback a transaction or subtransaction.
*/
static int btRollback(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;

  rc = sqlite4BtRollback(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);

  return rc;
}

/*
** Revert a transaction back to what it was when it started.
*/
#if 0
................................................................................
*/
static int btReplace(
  KVStore *pKVStore,
  const KVByteArray *aKey, KVSize nKey,
  const KVByteArray *aData, KVSize nData
){
  KVBt *p = (KVBt *)pKVStore;

  return sqlite4BtReplace(p->pDb, aKey, nKey, aData, nData);
}

/*
** Create a new cursor object.
*/
static int btOpenCursor(KVStore *pKVStore, KVCursor **ppKVCursor){
  KVBt *p = (KVBt *)pKVStore;
  int rc = SQLITE4_OK;
  bt_cursor *pCsr;
  KVBtCsr *pBtcsr;


  rc = sqlite4BtCsrOpen(p->pDb, sizeof(KVBtCsr), &pCsr);
  if( rc!=SQLITE4_OK ){
    pBtcsr = 0;
  }else{
    pBtcsr = (KVBtCsr*)sqlite4BtCsrExtra(pCsr);
    memset(pBtcsr, 0, sizeof(KVBtCsr));
    pBtcsr->base.pStore = pKVStore;
................................................................................
}

/*
** Destructor for the entire in-memory storage tree.
*/
static int btClose(KVStore *pKVStore){
  KVBt *p = (KVBt *)pKVStore;

  return sqlite4BtClose(p->pDb);
}

static int btControl(KVStore *pKVStore, int op, void *pArg){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtControl(p->pDb, op, pArg);
}

static int btGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVBt *p = (KVBt *)pKVStore;

  return sqlite4BtGetCookie(p->pDb, piVal);
}

static int btPutMeta(KVStore *pKVStore, unsigned int iVal){
  KVBt *p = (KVBt *)pKVStore;

  return sqlite4BtSetCookie(p->pDb, iVal);
}

static int btGetMethod(
  sqlite4_kvstore *pKVStore, 
  const char *zMethod, 
  void **ppArg,
................................................................................

  KVBt *pNew = 0;
  bt_db *pDb = 0;
  int rc;

  rc = sqlite4BtNew(pEnv, sizeof(KVBt), &pDb);
  if( rc==SQLITE4_OK ){

    pNew = (KVBt*)sqlite4BtExtra(pDb);
    pNew->base.pStoreVfunc = &bt_methods;
    pNew->base.pEnv = pEnv;
    pNew->pDb = pDb;
    rc = sqlite4BtOpen(pDb, zFilename);

  }

  if( rc!=SQLITE4_OK && pDb ){
    sqlite4BtClose(pDb);
    pNew = 0;
  }
  *ppKVStore = pNew;
  return rc;
}








>
>
>







 







>
>
>
>
>
>
>
>







 







>










|
>
|
|
>







 







>












>







 







>










>





>







 







>




|
>










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
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
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
typedef struct KVBtCsr KVBtCsr;

/*
** An instance of an open connection to a bt_db store.  A subclass of KVStore.
*/
struct KVBt {
  KVStore base;                   /* Base class, must be first */
  const char *zFilename;          /* File to open */
  int bOpen;                      /* See above */
  int openrc;                     /* See above */
  bt_db *pDb;                     /* Database handle */
};

/*
** An instance of an open cursor pointing into an LSM store.  A subclass
** of KVCursor.
*/
................................................................................
  
/*
** Begin a transaction or subtransaction.
*/
static int btBegin(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;
  if( p->openrc ) return p->openrc;
  if( p->bOpen==0 ){
    p->openrc = rc = sqlite4BtOpen(p->pDb, p->zFilename);
    if( rc!=SQLITE4_OK ){
      return rc;
    }
    p->bOpen = 1;
  }
  rc = sqlite4BtBegin(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Commit a transaction or subtransaction.
................................................................................
*/
static int btCommitPhaseOne(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}
static int btCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;
  assert( p->bOpen==1 );
  rc = sqlite4BtCommit(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Rollback a transaction or subtransaction.
*/
static int btRollback(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc = SQLITE4_OK;
  if( p->bOpen==1 ){
    rc = sqlite4BtRollback(p->pDb, iLevel);
    pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  }
  return rc;
}

/*
** Revert a transaction back to what it was when it started.
*/
#if 0
................................................................................
*/
static int btReplace(
  KVStore *pKVStore,
  const KVByteArray *aKey, KVSize nKey,
  const KVByteArray *aData, KVSize nData
){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtReplace(p->pDb, aKey, nKey, aData, nData);
}

/*
** Create a new cursor object.
*/
static int btOpenCursor(KVStore *pKVStore, KVCursor **ppKVCursor){
  KVBt *p = (KVBt *)pKVStore;
  int rc = SQLITE4_OK;
  bt_cursor *pCsr;
  KVBtCsr *pBtcsr;

  assert( p->bOpen==1 );
  rc = sqlite4BtCsrOpen(p->pDb, sizeof(KVBtCsr), &pCsr);
  if( rc!=SQLITE4_OK ){
    pBtcsr = 0;
  }else{
    pBtcsr = (KVBtCsr*)sqlite4BtCsrExtra(pCsr);
    memset(pBtcsr, 0, sizeof(KVBtCsr));
    pBtcsr->base.pStore = pKVStore;
................................................................................
}

/*
** Destructor for the entire in-memory storage tree.
*/
static int btClose(KVStore *pKVStore){
  KVBt *p = (KVBt *)pKVStore;
  sqlite4_free(pKVStore->pEnv, p->zFilename);
  return sqlite4BtClose(p->pDb);
}

static int btControl(KVStore *pKVStore, int op, void *pArg){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtControl(p->pDb, op, pArg);
}

static int btGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtGetCookie(p->pDb, piVal);
}

static int btPutMeta(KVStore *pKVStore, unsigned int iVal){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtSetCookie(p->pDb, iVal);
}

static int btGetMethod(
  sqlite4_kvstore *pKVStore, 
  const char *zMethod, 
  void **ppArg,
................................................................................

  KVBt *pNew = 0;
  bt_db *pDb = 0;
  int rc;

  rc = sqlite4BtNew(pEnv, sizeof(KVBt), &pDb);
  if( rc==SQLITE4_OK ){
    bt_env *pBtenv = 0;
    pNew = (KVBt*)sqlite4BtExtra(pDb);
    pNew->base.pStoreVfunc = &bt_methods;
    pNew->base.pEnv = pEnv;
    pNew->pDb = pDb;
    sqlite4BtControl(pDb, BT_CONTROL_GETVFS, (void*)&pBtenv);
    rc = pBtenv->xFullpath(pEnv, pBtenv, zFilename, &pNew->zFilename);
  }

  if( rc!=SQLITE4_OK && pDb ){
    sqlite4BtClose(pDb);
    pNew = 0;
  }
  *ppKVStore = pNew;
  return rc;
}

Changes to test/attach.test

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
      puts "\n**** Tests do not work when run as root ****"
      forcedelete cannot-read
      exit 1
    }
    catchsql {
      ATTACH DATABASE 'cannot-read' AS noread;
    }
  } {1 {unable to open database: cannot-read}}
  do_test attach-6.2.2 {
    db errorcode
  } {10}
  forcedelete cannot-read
}

# Check the error message if we try to access a database that has
................................................................................
do_test attach-8.1 {
  set fd [open test2.db w]
  puts $fd "This file is not a valid SQLite database"
  close $fd
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {unable to open database: test2.db}}
do_test attach-8.2 {
  db errorcode
} {26}
forcedelete test2.db
do_test attach-8.3 {
  sqlite4 db2 test2.db
  db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}







|







 







|







745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
      puts "\n**** Tests do not work when run as root ****"
      forcedelete cannot-read
      exit 1
    }
    catchsql {
      ATTACH DATABASE 'cannot-read' AS noread;
    }
  } {1 {disk I/O error}}
  do_test attach-6.2.2 {
    db errorcode
  } {10}
  forcedelete cannot-read
}

# Check the error message if we try to access a database that has
................................................................................
do_test attach-8.1 {
  set fd [open test2.db w]
  puts $fd "This file is not a valid SQLite database"
  close $fd
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {file is encrypted or is not a database}}
do_test attach-8.2 {
  db errorcode
} {26}
forcedelete test2.db
do_test attach-8.3 {
  sqlite4 db2 test2.db
  db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}

Changes to test/attach3.test

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# Failure to attach leaves us in a workable state.
# Ticket #811
#
do_test attach3-11.0 {
  catchsql {
    ATTACH DATABASE '/nodir/nofile.x' AS notadb;
  }
} {1 {unable to open database: /nodir/nofile.x}}
do_test attach3-11.1 {
  catchsql {
    ATTACH DATABASE ':memory:' AS notadb;
  }
} {0 {}}
do_test attach3-11.2 {
  catchsql {







|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# Failure to attach leaves us in a workable state.
# Ticket #811
#
do_test attach3-11.0 {
  catchsql {
    ATTACH DATABASE '/nodir/nofile.x' AS notadb;
  }
} {1 {disk I/O error}}
do_test attach3-11.1 {
  catchsql {
    ATTACH DATABASE ':memory:' AS notadb;
  }
} {0 {}}
do_test attach3-11.2 {
  catchsql {

Changes to test/bt1.test

44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
  execsql { SELECT * FROM t1 }
} {abcd}

do_test 1.3 { 
  db close
  hexio_write test.db  8 55555555

  list [catch {sqlite4 db test.db} msg] $msg

} {1 {file is encrypted or is not a database}}

#-------------------------------------------------------------------------
# Test that, if there is a *-wal file that contains a valid copy of page
# 1 (with the db header), it is possible to open the database even if
# the header at byte offset 0 is damaged.
#







|
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  execsql { SELECT * FROM t1 }
} {abcd}

do_test 1.3 { 
  db close
  hexio_write test.db  8 55555555

  sqlite4 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {file is encrypted or is not a database}}

#-------------------------------------------------------------------------
# Test that, if there is a *-wal file that contains a valid copy of page
# 1 (with the db header), it is possible to open the database even if
# the header at byte offset 0 is damaged.
#

Changes to test/fault1.test

11
12
13
14
15
16
17


18
19
20
21
22
23
24
25
26
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set ::testprefix fault1




do_faultsim_test 1.0 -faults oom* -body {
  execsql { SELECT * FROM sqlite_master }
} -test {
  faultsim_test_result {0 {}} 
}

finish_test








>
>









11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set ::testprefix fault1


execsql { SELECT *  FROM  sqlite_master }

do_faultsim_test 1.0 -faults oom* -body {
  execsql { SELECT * FROM sqlite_master }
} -test {
  faultsim_test_result {0 {}} 
}

finish_test

Changes to test/permutations.test

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#   full
#
lappend ::testsuitelist xxx

test_suite "bt" -prefix "bt-" -description {
} -files {
bt1.test

aggerror.test
alter.test
alter3.test
alter4.test
analyze.test
analyze3.test
analyze4.test







<







131
132
133
134
135
136
137

138
139
140
141
142
143
144
#   full
#
lappend ::testsuitelist xxx

test_suite "bt" -prefix "bt-" -description {
} -files {
bt1.test

aggerror.test
alter.test
alter3.test
alter4.test
analyze.test
analyze3.test
analyze4.test