/ Check-in [79a818bb]
Login

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

Overview
Comment:Handle NULL database names in ATTACH and DETACH as if they were empty strings. Ticket #1825. (CVS 3191)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 79a818bb05bc95c4c83375a679955dd18659b2b8
User & Date: drh 2006-05-25 11:52:38
Context
2006-05-25
12:17
Syntax errors override errors from the code generator, not the other way around. (CVS 3192) check-in: 5031ffc6 user: drh tags: trunk
11:52
Handle NULL database names in ATTACH and DETACH as if they were empty strings. Ticket #1825. (CVS 3191) check-in: 79a818bb user: drh tags: trunk
2006-05-24
12:43
When opening a new connection on a shared cache, be careful not to overwrite the encoding flag on the shared cache. Ticket #1824. (CVS 3190) check-in: c8e5ceed user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/attach.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
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
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
**    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 code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.51 2006/04/10 13:37:47 drh Exp $
*/
#include "sqliteInt.h"

/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
................................................................................
  const char *zFile;
  Db *aNew;
  char zErr[128];
  char *zErrDyn = 0;

  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);



  /* Check for the following errors:
  **
  **     * Too many attached databases,
  **     * Transaction currently open
  **     * Specified database name already being used.
  */
  if( db->nDb>=MAX_ATTACHED+2 ){
    sqlite3_snprintf(
      127, zErr, "too many attached databases - max %d", MAX_ATTACHED
    );
    goto attach_error;
  }
  if( !db->autoCommit ){
    strcpy(zErr, "cannot ATTACH database within transaction");
    goto attach_error;
  }
  for(i=0; i<db->nDb; i++){
    char *z = db->aDb[i].zName;
    if( z && sqlite3StrICmp(z, zName)==0 ){
      sqlite3_snprintf(127, zErr, "database %s is already in use", zName);
      goto attach_error;
    }
  }

  /* Allocate the new entry in the db->aDb[] array and initialise the schema
  ** hash tables.
  */
................................................................................
      db->aDb[iDb].pBt = 0;
      db->aDb[iDb].pSchema = 0;
    }
    sqlite3ResetInternalSchema(db, 0);
    db->nDb = iDb;
    if( rc==SQLITE_NOMEM ){
      if( !sqlite3MallocFailed() ) sqlite3FailedMalloc();
      sqlite3_snprintf(127, zErr, "out of memory");
    }else{
      sqlite3_snprintf(127, zErr, "unable to open database: %s", zFile);
    }
    goto attach_error;
  }
  
  return;

attach_error:
................................................................................
){
  const char *zName = (const char *)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_user_data(context);
  int i;
  Db *pDb = 0;
  char zErr[128];

  assert(zName);
  for(i=0; i<db->nDb; i++){
    pDb = &db->aDb[i];
    if( pDb->pBt==0 ) continue;
    if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
  }

  if( i>=db->nDb ){
    sqlite3_snprintf(sizeof(zErr), zErr, "no such database: %s", zName);
    goto detach_error;
  }
  if( i<2 ){
    sqlite3_snprintf(sizeof(zErr), zErr, "cannot detach database %s", zName);
    goto detach_error;
  }
  if( !db->autoCommit ){
    strcpy(zErr, "cannot DETACH database within transaction");
    goto detach_error;
  }








|







 







>
>









|









|
|







 







|

|







 







|







|



|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
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
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
**    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 code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.52 2006/05/25 11:52:38 drh Exp $
*/
#include "sqliteInt.h"

/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
................................................................................
  const char *zFile;
  Db *aNew;
  char zErr[128];
  char *zErrDyn = 0;

  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";

  /* Check for the following errors:
  **
  **     * Too many attached databases,
  **     * Transaction currently open
  **     * Specified database name already being used.
  */
  if( db->nDb>=MAX_ATTACHED+2 ){
    sqlite3_snprintf(
      sizeof(zErr), zErr, "too many attached databases - max %d", MAX_ATTACHED
    );
    goto attach_error;
  }
  if( !db->autoCommit ){
    strcpy(zErr, "cannot ATTACH database within transaction");
    goto attach_error;
  }
  for(i=0; i<db->nDb; i++){
    char *z = db->aDb[i].zName;
    if( z && zName && sqlite3StrICmp(z, zName)==0 ){
      sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName);
      goto attach_error;
    }
  }

  /* Allocate the new entry in the db->aDb[] array and initialise the schema
  ** hash tables.
  */
................................................................................
      db->aDb[iDb].pBt = 0;
      db->aDb[iDb].pSchema = 0;
    }
    sqlite3ResetInternalSchema(db, 0);
    db->nDb = iDb;
    if( rc==SQLITE_NOMEM ){
      if( !sqlite3MallocFailed() ) sqlite3FailedMalloc();
      sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
    }else{
      sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
    }
    goto attach_error;
  }
  
  return;

attach_error:
................................................................................
){
  const char *zName = (const char *)sqlite3_value_text(argv[0]);
  sqlite3 *db = sqlite3_user_data(context);
  int i;
  Db *pDb = 0;
  char zErr[128];

  if( zName==0 ) zName = "";
  for(i=0; i<db->nDb; i++){
    pDb = &db->aDb[i];
    if( pDb->pBt==0 ) continue;
    if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
  }

  if( i>=db->nDb ){
    sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
    goto detach_error;
  }
  if( i<2 ){
    sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
    goto detach_error;
  }
  if( !db->autoCommit ){
    strcpy(zErr, "cannot DETACH database within transaction");
    goto detach_error;
  }

Changes to test/attach3.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
237
238
239
240
241
242
243
244



























































































245
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and schema changes to attached databases.
#
# $Id: attach3.test,v 1.15 2005/03/29 03:11:00 danielk1977 Exp $
#


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

# Create tables t1 and t2 in the main database
................................................................................
  }
} {0 {}}
do_test attach3-11.2 {
  catchsql {
    DETACH DATABASE notadb;
  }
} {0 {}}




























































































finish_test







|







 








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

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and schema changes to attached databases.
#
# $Id: attach3.test,v 1.16 2006/05/25 11:52:38 drh Exp $
#


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

# Create tables t1 and t2 in the main database
................................................................................
  }
} {0 {}}
do_test attach3-11.2 {
  catchsql {
    DETACH DATABASE notadb;
  }
} {0 {}}

# Return a list of attached databases
#
proc db_list {} {
  set x [execsql {
    PRAGMA database_list;
  }]
  set y {}
  foreach {n id file} $x {lappend y $id}
  return $y
}

# Ticket #1825
#
do_test attach3-12.1 {
  db_list
} {main temp aux}
do_test attach3-12.2 {
  execsql {
    ATTACH DATABASE ? AS ?
  }
  db_list
} {main temp aux {}}
do_test attach3-12.3 {
  execsql {
    DETACH aux
  }
  db_list
} {main temp {}}
do_test attach3-12.4 {
  execsql {
    DETACH ?
  }
  db_list
} {main temp}
do_test attach3-12.5 {
  execsql {
    ATTACH DATABASE '' AS ''
  }
  db_list
} {main temp {}}
do_test attach3-12.6 {
  execsql {
    DETACH ''
  }
  db_list
} {main temp}
do_test attach3-12.7 {
  execsql {
    ATTACH DATABASE '' AS ?
  }
  db_list
} {main temp {}}
do_test attach3-12.8 {
  execsql {
    DETACH ''
  }
  db_list
} {main temp}
do_test attach3-12.9 {
  execsql {
    ATTACH DATABASE '' AS NULL
  }
  db_list
} {main temp {}}
do_test attach3-12.10 {
  execsql {
    DETACH ?
  }
  db_list
} {main temp}
do_test attach3-12.11 {
  catchsql {
    DETACH NULL
  }
} {1 {no such database: }}
do_test attach3-12.12 {
  catchsql {
    ATTACH null AS null;
    ATTACH '' AS '';
  }
} {1 {database  is already in use}}
do_test attach3-12.13 {
  db_list
} {main temp {}}
do_test attach3-12.14 {
  execsql {
    DETACH '';
  }
  db_list
} {main temp}

finish_test