SQLite

Changes On Branch test_delete
Login

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

Changes In Branch test_delete Excluding Merge-Ins

This is equivalent to a diff from 6ac932c9 to 0e3ace39

2016-09-10
14:43
Add test code to delete an SQLite database and its auxiliary files. (check-in: 8a9d1281 user: dan tags: trunk)
2016-09-09
20:26
Make the new file test_delete.c portable to MSVC on Windows. (Closed-Leaf check-in: 0e3ace39 user: mistachkin tags: test_delete)
20:00
Add new file test_delete.c, containing test code for deleting an sqlite database. (check-in: fb0b95e9 user: dan tags: test_delete)
19:33
Performance improvements to the comparison operators in the bytecode engine. (check-in: 37803b19 user: drh tags: trunk)
15:12
Fix a out-of-order variable declaration for some compile-time configurations. (check-in: 6ac932c9 user: drh tags: trunk)
13:23
In releasetest.tcl, the --srcdir option is automatic, so no need to mention it in the --help output. (check-in: 2bdd838e user: drh tags: trunk)

Changes to Makefile.in.

378
379
380
381
382
383
384

385
386
387
388
389
390
391
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392







+







  $(TOP)/src/test_autoext.c \
  $(TOP)/src/test_async.c \
  $(TOP)/src/test_backup.c \
  $(TOP)/src/test_bestindex.c \
  $(TOP)/src/test_blob.c \
  $(TOP)/src/test_btree.c \
  $(TOP)/src/test_config.c \
  $(TOP)/src/test_delete.c \
  $(TOP)/src/test_demovfs.c \
  $(TOP)/src/test_devsym.c \
  $(TOP)/src/test_fs.c \
  $(TOP)/src/test_func.c \
  $(TOP)/src/test_hexio.c \
  $(TOP)/src/test_init.c \
  $(TOP)/src/test_intarray.c \

Changes to Makefile.msc.

1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277
1278
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279







+







  $(TOP)\src\test_autoext.c \
  $(TOP)\src\test_async.c \
  $(TOP)\src\test_backup.c \
  $(TOP)\src\test_bestindex.c \
  $(TOP)\src\test_blob.c \
  $(TOP)\src\test_btree.c \
  $(TOP)\src\test_config.c \
  $(TOP)\src\test_delete.c \
  $(TOP)\src\test_demovfs.c \
  $(TOP)\src\test_devsym.c \
  $(TOP)\src\test_fs.c \
  $(TOP)\src\test_func.c \
  $(TOP)\src\test_hexio.c \
  $(TOP)\src\test_init.c \
  $(TOP)\src\test_intarray.c \

Changes to main.mk.

289
290
291
292
293
294
295

296
297
298
299
300
301
302
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303







+







  $(TOP)/src/test_autoext.c \
  $(TOP)/src/test_async.c \
  $(TOP)/src/test_backup.c \
  $(TOP)/src/test_bestindex.c \
  $(TOP)/src/test_blob.c \
  $(TOP)/src/test_btree.c \
  $(TOP)/src/test_config.c \
  $(TOP)/src/test_delete.c \
  $(TOP)/src/test_demovfs.c \
  $(TOP)/src/test_devsym.c \
  $(TOP)/src/test_fs.c \
  $(TOP)/src/test_func.c \
  $(TOP)/src/test_hexio.c \
  $(TOP)/src/test_init.c \
  $(TOP)/src/test_intarray.c \

Changes to src/test1.c.

2383
2384
2385
2386
2387
2388
2389























2390
2391
2392
2393
2394
2395
2396
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419







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







  p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
  p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
  res = sqlite3_snapshot_cmp(p1, p2);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
  return TCL_OK;
}
#endif /* SQLITE_ENABLE_SNAPSHOT */

/*
** Usage: sqlite3_delete_database FILENAME
*/
int sqlite3_delete_database(const char*);   /* in test_delete.c */
static int SQLITE_TCLAPI test_delete_database(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc;
  const char *zFile;
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILE");
    return TCL_ERROR;
  }
  zFile = (const char*)Tcl_GetString(objv[1]);
  rc = sqlite3_delete_database(zFile);

  Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
  return TCL_OK;
}

/*
** Usage:  sqlite3_next_stmt  DB  STMT
**
** Return the next statment in sequence after STMT.
*/
static int SQLITE_TCLAPI test_next_stmt(
7479
7480
7481
7482
7483
7484
7485

7486
7487
7488
7489
7490
7491
7492
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516







+







     { "vfs_current_time_int64",           vfsCurrentTimeInt64,   0 },
#ifdef SQLITE_ENABLE_SNAPSHOT
     { "sqlite3_snapshot_get", test_snapshot_get, 0 },
     { "sqlite3_snapshot_open", test_snapshot_open, 0 },
     { "sqlite3_snapshot_free", test_snapshot_free, 0 },
     { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
#endif
     { "sqlite3_delete_database", test_delete_database, 0 },
  };
  static int bitmask_size = sizeof(Bitmask)*8;
  static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;

Added src/test_delete.c.













































































































































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
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
134
135
136
137
138
139
140
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** 2016 September 10
**
** 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 contains test code to delete an SQLite database and all
** of its associated files. Associated files include:
**
**   * The journal file.
**   * The wal file.
**   * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files.
**   * Files created by the test_multiplex.c module to extend any of the 
**     above.
*/

#if SQLITE_OS_WIN
#  include <io.h>
#  define F_OK 0
#else
#  include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include "sqlite3.h"

/* The following #defines are copied from test_multiplex.c */
#ifndef MX_CHUNK_NUMBER 
# define MX_CHUNK_NUMBER 299
#endif
#ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
# define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
#endif
#ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
# define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
#endif

/*
** This routine is a copy of (most of) the code from SQLite function
** sqlite3FileSuffix3(). It modifies the filename in buffer z in the
** same way as SQLite does when in 8.3 filenames mode.
*/
static void sqlite3Delete83Name(char *z){
  int i, sz;
  sz = strlen(z);
  for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
  if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
}

/*
** zFile is a filename. Assuming no error occurs, if this file exists, 
** set *pbExists to true and unlink it. Or, if the file does not exist,
** set *pbExists to false before returning.
**
** If an error occurs, the value of errno is returned. Or, if no error
** occurs, zero is returned.
*/
static int sqlite3DeleteUnlinkIfExists(const char *zFile, int *pbExists){
  int rc;
  rc = access(zFile, F_OK);
  if( rc ){
    if( errno==ENOENT ){ 
      if( pbExists ) *pbExists = 0;
      return 0; 
    }
    return errno;
  }
  if( pbExists ) *pbExists = 1;
  rc = unlink(zFile);
  if( rc ) return errno;
  return 0;
}

/*
** Delete the database file identified by the string argument passed to this
** function. The string must contain a filename, not an SQLite URI.
*/
int sqlite3_delete_database(
  const char *zFile               /* File to delete */
){
  char *zBuf;                     /* Buffer to sprintf() filenames to */
  int nBuf;                       /* Size of buffer in bytes */
  int rc = 0;                     /* System error code */
  int i;                          /* Iterate through azFmt[] and aMFile[] */

  const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };

  struct MFile {
    const char *zFmt;
    int iOffset;
    int b83;
  } aMFile[] = {
    { "%s%03d",         0,   0 },
    { "%s-journal%03d", 0,   0 },
    { "%s-wal%03d",     0,   0 },
    { "%s%03d",         0,   1 },
    { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
    { "%s-wal%03d",     SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
  };

  /* Allocate a buffer large enough for any of the files that need to be
  ** deleted.  */
  nBuf = strlen(zFile) + 100;
  zBuf = (char*)sqlite3_malloc(nBuf);
  if( zBuf==0 ) return SQLITE_NOMEM;

  /* Delete both the regular and 8.3 filenames versions of the database,
  ** journal, wal and shm files.  */
  for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
    sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
    rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
    if( rc==0 && i!=0 ){
      sqlite3Delete83Name(zBuf);
      rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
    }
  }

  /* Delete any multiplexor files */
  for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
    struct MFile *p = &aMFile[i];
    int iChunk;
    for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
      int bExists;
      sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
      if( p->b83 ) sqlite3Delete83Name(zBuf);
      rc = sqlite3DeleteUnlinkIfExists(zBuf, &bExists);
      if( bExists==0 || rc!=0 ) break;
    }
  }

  sqlite3_free(zBuf);
  return (rc ? SQLITE_ERROR : SQLITE_OK);
}


Added test/delete_db.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
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2016 September 10
#
# 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 implements regression tests for SQLite library.  The
# focus of this file is testing the DELETE FROM statement.
#

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

proc delete_all {} {
  foreach f [glob -nocomplain test2*] { file delete $f }
  foreach f [glob -nocomplain test3*] { file delete $f }
}

proc copydb {} {
  foreach f [glob -nocomplain test3*] { file delete $f }
  foreach f [glob -nocomplain test2*] { 
    set p [string range $f 5 end]
    file copy "test2$p" "test3$p"
  }
}

proc files {} {
  lsort [glob -nocomplain test3*]
}

db close
delete_all
sqlite3 db test2.database

#-------------------------------------------------------------------------
#
# 1.1: Journal files.
# 1.2: Wal files.
# 1.3: Multiplexor with journal file.
# 1.4: Multiplexor with wal file.
#
# 2.* are a copy of 1.* with the multiplexor enabled.
#
# 3.* tests errors.
#

do_test 1.1.0 {
  execsql {
    CREATE TABLE t1(x, y);
    BEGIN;
      INSERT INTO t1 VALUES(1, 2);
  }
  copydb
  files
} {test3.database test3.database-journal}

do_test 1.1.1 {
  sqlite3_delete_database test3.database
  files
} {}

do_test 1.2.0 {
  execsql {
    COMMIT;
    PRAGMA journal_mode = wal;
    INSERT INTO t1 VALUES(3, 4);
  }
  copydb
  files
} {test3.database test3.database-shm test3.database-wal}
do_test 1.2.1 {
  sqlite3_delete_database test3.database
  files
} {}

db close
delete_all
sqlite3_multiplex_initialize "" 0
sqlite3 db test2.database -vfs multiplex
sqlite3_multiplex_control db "main" chunk_size 32768

do_test 1.3.0 {
  execsql {
    CREATE TABLE x1(a, b);
    WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
    INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
    BEGIN;
      UPDATE x1 SET a=randomblob(101)
  }
  copydb
  files
} [list {*}{
  test3.database test3.database-journal test3.database001 
  test3.database002 test3.database003
}]
do_test 1.3.1 {
  sqlite3_delete_database test3.database
  files
} {}


do_test 1.4.0 {
  execsql {
    COMMIT;
    PRAGMA journal_mode = wal;
    UPDATE x1 SET a=randomblob(102)
  }
  copydb
  files
} [list {*}{
  test3.database test3.database-shm test3.database-wal test3.database001 
  test3.database002 test3.database003
}]
do_test 1.4.1 {
  sqlite3_delete_database test3.database
  files
} {}


ifcapable 8_3_names {
  db close
  delete_all
  sqlite3 db file:test2.db?8_3_names=1 -uri 1

  do_test 2.1.0 {
    execsql {
      CREATE TABLE t1(x, y);
      BEGIN;
        INSERT INTO t1 VALUES(1, 2);
    }
    copydb
    files
  } {test3.db test3.nal}
  
  do_test 2.1.1 {
    sqlite3_delete_database test3.db
    files
  } {}
  
  do_test 2.2.0 {
    execsql {
      COMMIT;
      PRAGMA journal_mode = wal;
      INSERT INTO t1 VALUES(3, 4);
    }
    copydb
    files
  } {test3.db test3.shm test3.wal}
  do_test 2.2.1 {
    sqlite3_delete_database test3.db
    files
  } {}


  db close
  delete_all
  sqlite3_multiplex_initialize "" 0
  sqlite3 db file:test2.db?8_3_names=1 -uri 1 -vfs multiplex
  sqlite3_multiplex_control db "main" chunk_size 32768
  
  do_test 2.3.0 {
    execsql {
      CREATE TABLE x1(a, b);
      WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
      INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
      BEGIN;
        UPDATE x1 SET a=randomblob(101)
    }
    copydb
    files
  } [list {*}{
    test3.001 test3.002 test3.003 test3.db test3.nal 
  }]
  do_test 2.3.1 {
    sqlite3_delete_database test3.db
    files
  } {}
  
  
  do_test 2.4.0 {
    execsql {
      COMMIT;
      PRAGMA journal_mode = wal;
      UPDATE x1 SET a=randomblob(102)
    }
    copydb
    files
  } [list {*}{
    test3.001 test3.002 test3.003 test3.db test3.db-shm test3.wal 
  }]
  do_test 2.4.1 {
    sqlite3_delete_database test3.db
    files
  } {}
}

db close
delete_all
sqlite3_multiplex_shutdown 

do_test 3.0 {
  file mkdir dir2.db
  sqlite3_delete_database dir2.db
} {SQLITE_ERROR}
do_test 3.1 {
  sqlite3_delete_database dir2.db/test.db
} {SQLITE_OK}

finish_test