SQLite

Check-in [ac1fd6beb6]
Login

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

Overview
Comment:Allow ATTACH and DETACH to occur inside of a transaction.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | attach-in-trans
Files: files | file ages | folders
SHA3-256: ac1fd6beb6c804af5faf1e06a51177a8316007ff9e718c398bd7a24d2ecc4ed3
User & Date: drh 2017-07-26 18:26:44.412
Context
2017-08-01
00:20
Allow ATTACH and DETACH inside of a transaction. (check-in: 95e8f31658 user: drh tags: trunk)
2017-07-26
18:26
Allow ATTACH and DETACH to occur inside of a transaction. (Closed-Leaf check-in: ac1fd6beb6 user: drh tags: attach-in-trans)
10:04
Fix a comment on the UnpackedRecord.r1 and UnpackedRecord.r2 fields. No changes to code. (check-in: 622b108915 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/attach.c.
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  */
  if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
    zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", 
      db->aLimit[SQLITE_LIMIT_ATTACHED]
    );
    goto attach_error;
  }
  if( !db->autoCommit ){
    zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
    goto attach_error;
  }
  for(i=0; i<db->nDb; i++){
    char *z = db->aDb[i].zDbSName;
    assert( z && zName );
    if( sqlite3StrICmp(z, zName)==0 ){
      zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
      goto attach_error;
    }







<
<
<
<







89
90
91
92
93
94
95




96
97
98
99
100
101
102
  */
  if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
    zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", 
      db->aLimit[SQLITE_LIMIT_ATTACHED]
    );
    goto attach_error;
  }




  for(i=0; i<db->nDb; i++){
    char *z = db->aDb[i].zDbSName;
    assert( z && zName );
    if( sqlite3StrICmp(z, zName)==0 ){
      zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
      goto attach_error;
    }
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
    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 ){
    sqlite3_snprintf(sizeof(zErr), zErr,
                     "cannot DETACH database within transaction");
    goto detach_error;
  }
  if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
    sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
    goto detach_error;
  }

  sqlite3BtreeClose(pDb->pBt);
  pDb->pBt = 0;







<
<
<
<
<







280
281
282
283
284
285
286





287
288
289
290
291
292
293
    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( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
    sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
    goto detach_error;
  }

  sqlite3BtreeClose(pDb->pBt);
  pDb->pBt = 0;
Changes to test/attach2.test.
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  execsql {
    BEGIN;
  }
} {}
do_test attach2-6.2 {
  catchsql {
    ATTACH 'test3.db' as aux2;

  }
} {1 {cannot ATTACH database within transaction}}

# EVIDENCE-OF: R-59740-55581 This statement will fail if SQLite is in
# the middle of a transaction.
#
do_test attach2-6.3 {
  catchsql {
    DETACH aux;
  }
} {1 {cannot DETACH database within transaction}}
do_test attach2-6.4 {
  execsql {
    COMMIT;
    DETACH aux;
  }
} {}

db close

finish_test







>

|








<
<
<
<
<
<
|




370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387






388
389
390
391
392
  execsql {
    BEGIN;
  }
} {}
do_test attach2-6.2 {
  catchsql {
    ATTACH 'test3.db' as aux2;
    DETACH aux2;
  }
} {0 {}}

# EVIDENCE-OF: R-59740-55581 This statement will fail if SQLite is in
# the middle of a transaction.
#
do_test attach2-6.3 {
  catchsql {
    DETACH aux;
  }






} {0 {}}

db close

finish_test
Changes to test/savepoint.test.
611
612
613
614
615
616
617



618
619
620
621
622

623
624
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
#-------------------------------------------------------------------------
# The following tests - savepoint-10.* - test the interaction of 
# savepoints and ATTACH statements.
# 

# First make sure it is not possible to attach or detach a database while
# a savepoint is open (it is not possible if any transaction is open).



#
do_test savepoint-10.1.1 {
  catchsql {
    SAVEPOINT one;
    ATTACH 'test2.db' AS aux;

  }
} {1 {cannot ATTACH database within transaction}}
do_test savepoint-10.1.2 {
  execsql {
    RELEASE one;
    ATTACH 'test2.db' AS aux;
  }
  catchsql {
    SAVEPOINT one;
    DETACH aux;

  }
} {1 {cannot DETACH database within transaction}}
do_test savepoint-10.1.3 {
  execsql {
    RELEASE one;
    DETACH aux;
  }
} {}








>
>
>





>

|








>

|







611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
#-------------------------------------------------------------------------
# The following tests - savepoint-10.* - test the interaction of 
# savepoints and ATTACH statements.
# 

# First make sure it is not possible to attach or detach a database while
# a savepoint is open (it is not possible if any transaction is open).
#
# UPDATE 2017-07-26:  It is not possible to ATTACH and DETACH within a
# a transaction.
#
do_test savepoint-10.1.1 {
  catchsql {
    SAVEPOINT one;
    ATTACH 'test2.db' AS aux;
    DETACH aux;
  }
} {0 {}}
do_test savepoint-10.1.2 {
  execsql {
    RELEASE one;
    ATTACH 'test2.db' AS aux;
  }
  catchsql {
    SAVEPOINT one;
    DETACH aux;
    ATTACH 'test2.db' AS aux;
  }
} {0 {}}
do_test savepoint-10.1.3 {
  execsql {
    RELEASE one;
    DETACH aux;
  }
} {}