mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add some simple tests and fixes for shared-schema locking. (CVS 2869)
FossilOrigin-Name: d054bed15aee3edef93cc84c83be443cdd489946
This commit is contained in:
22
manifest
22
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Back\sout\sthe\saddition\sof\sthe\snew\sheader\sfile\s-\sbad\sidea.\s(CVS\s2868)
|
C Add\ssome\ssimple\stests\sand\sfixes\sfor\sshared-schema\slocking.\s(CVS\s2869)
|
||||||
D 2006-01-06T12:03:19
|
D 2006-01-06T13:00:29
|
||||||
F Makefile.in 131285a3e97597dd7ed3eb23a1010c7d0685ae41
|
F Makefile.in 131285a3e97597dd7ed3eb23a1010c7d0685ae41
|
||||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@@ -34,8 +34,8 @@ F src/alter.c e9deb3f4fd7c663a0d1f235d541bc5ea1f2cfa8b
|
|||||||
F src/analyze.c d821684cdb4d0403e327e4a3440a832e9e54fa3a
|
F src/analyze.c d821684cdb4d0403e327e4a3440a832e9e54fa3a
|
||||||
F src/attach.c 999104c56a60b88eab11ef9c8f40dedf1650b287
|
F src/attach.c 999104c56a60b88eab11ef9c8f40dedf1650b287
|
||||||
F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f
|
F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f
|
||||||
F src/btree.c d1402f4e1cfc500b31d13990f36dd8d3d27443bc
|
F src/btree.c f34c1e8d93003cbd8cc579865e0c0db4f595b97e
|
||||||
F src/btree.h 96b8c00c6e11ff92f8d3d6a7a0ff358bd10d8f19
|
F src/btree.h f7ba8e2f9f387cca4978e1495504a0bf556dcbf2
|
||||||
F src/build.c 715ac7d49bbfcae5f3fdfd60885397b2133c283b
|
F src/build.c 715ac7d49bbfcae5f3fdfd60885397b2133c283b
|
||||||
F src/callback.c 62066afd516f220575e81b1a1239ab92a2eae252
|
F src/callback.c 62066afd516f220575e81b1a1239ab92a2eae252
|
||||||
F src/complete.c df1681cef40dec33a286006981845f87b194e7a4
|
F src/complete.c df1681cef40dec33a286006981845f87b194e7a4
|
||||||
@@ -63,7 +63,7 @@ F src/pager.c 07509ddb478f5a70f9ff53607ab8a44456c22811
|
|||||||
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
|
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
|
||||||
F src/parse.y 58258759fabdd48f1d2561e276097290b1ea2680
|
F src/parse.y 58258759fabdd48f1d2561e276097290b1ea2680
|
||||||
F src/pragma.c 4af4041a88d41421b8ff2e5574d82d7b9d1e35b1
|
F src/pragma.c 4af4041a88d41421b8ff2e5574d82d7b9d1e35b1
|
||||||
F src/prepare.c 67ff283f7c71e32a91d8c843e758eb4bf68ab94e
|
F src/prepare.c 48baea211104dfcfa59857a32d62c934f63a15ed
|
||||||
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
|
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
|
||||||
F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d
|
F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d
|
||||||
F src/select.c a60e5c7fad9ce7adc78d9eb32a0a89dd5acd04fb
|
F src/select.c a60e5c7fad9ce7adc78d9eb32a0a89dd5acd04fb
|
||||||
@@ -222,7 +222,7 @@ F test/select4.test c239f516aa31f42f2ef7c6d7cd01105f08f934ca
|
|||||||
F test/select5.test 07a90ab3c7e3f0a241a9cdea1d997b2c8a89ff0b
|
F test/select5.test 07a90ab3c7e3f0a241a9cdea1d997b2c8a89ff0b
|
||||||
F test/select6.test f459a19bdac0501c4d3eb1a4df4b7a76f1bb8ad4
|
F test/select6.test f459a19bdac0501c4d3eb1a4df4b7a76f1bb8ad4
|
||||||
F test/select7.test 1bf795b948c133a15a2a5e99d3270e652ec58ce6
|
F test/select7.test 1bf795b948c133a15a2a5e99d3270e652ec58ce6
|
||||||
F test/shared.test ee5a4154d257e4c2ce1ae418783b87847473de90
|
F test/shared.test eb6b9ac456f60ed485b9ca5873d563abacae815a
|
||||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||||
F test/subquery.test e6de53332c0301b3cfa34edc3f3cd5fa1e859efd
|
F test/subquery.test e6de53332c0301b3cfa34edc3f3cd5fa1e859efd
|
||||||
F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2
|
F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2
|
||||||
@@ -328,7 +328,7 @@ F www/optimizing.tcl f0b2538988d1bbad16cbfe63ec6e8f48c9eb04e5
|
|||||||
F www/optoverview.tcl 815df406a38c9f69b27d37e8f7ede004c6d9f19e
|
F www/optoverview.tcl 815df406a38c9f69b27d37e8f7ede004c6d9f19e
|
||||||
F www/pragma.tcl 44f7b665ca598ad24724f35991653638a36a6e3f
|
F www/pragma.tcl 44f7b665ca598ad24724f35991653638a36a6e3f
|
||||||
F www/quickstart.tcl 2f3daf8038e82a102e1e8cc877aafa7a413f5f11
|
F www/quickstart.tcl 2f3daf8038e82a102e1e8cc877aafa7a413f5f11
|
||||||
F www/sharedcache.tcl c42098d1436bcb54ec7f08d07c2e75316e2dde68
|
F www/sharedcache.tcl 884a93bf0f814204b24959c0c6229d61dd4734cc
|
||||||
F www/speed.tcl 656ed5be8cc9d536353e1a96927b925634a62933
|
F www/speed.tcl 656ed5be8cc9d536353e1a96927b925634a62933
|
||||||
F www/sqlite.tcl a883ed7b47371d31d471e6aea5ed1f972ae8e1be
|
F www/sqlite.tcl a883ed7b47371d31d471e6aea5ed1f972ae8e1be
|
||||||
F www/support.tcl 7961ce16290692578d783bb11f0dc8391a9be9c3
|
F www/support.tcl 7961ce16290692578d783bb11f0dc8391a9be9c3
|
||||||
@@ -337,7 +337,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||||
P 752a2754879becc32da9f9b910f3330f8c7145e4
|
P 0c4c45c36fe1c3c2980155ef5126a2ad53100d65
|
||||||
R 77860345776bf3dbb42b93b9296c48b1
|
R c892910cec71c19aeb323bc85b1a92ea
|
||||||
U drh
|
U danielk1977
|
||||||
Z 246dc71f2673d21c26bf8f1421f9f9ff
|
Z 5e6321921a4935029ecd84d938104014
|
||||||
|
@@ -1 +1 @@
|
|||||||
0c4c45c36fe1c3c2980155ef5126a2ad53100d65
|
d054bed15aee3edef93cc84c83be443cdd489946
|
14
src/btree.c
14
src/btree.c
@@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.281 2006/01/06 06:33:12 danielk1977 Exp $
|
** $Id: btree.c,v 1.282 2006/01/06 13:00:29 danielk1977 Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@@ -601,7 +601,7 @@ static int restoreCursorPosition(BtCursor *pCur, int doSeek){
|
|||||||
** Query to see if btree handle p may obtain a lock of type eLock
|
** Query to see if btree handle p may obtain a lock of type eLock
|
||||||
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
|
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
|
||||||
** SQLITE_OK if the lock may be obtained (by calling lockTable()), or
|
** SQLITE_OK if the lock may be obtained (by calling lockTable()), or
|
||||||
** SQLITE_BUSY if not.
|
** SQLITE_LOCKED if not.
|
||||||
*/
|
*/
|
||||||
static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
@@ -635,7 +635,7 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
|||||||
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
|
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
|
||||||
if( pIter->pBtree!=p && pIter->iTable==iTab &&
|
if( pIter->pBtree!=p && pIter->iTable==iTab &&
|
||||||
(pIter->eLock!=eLock || eLock!=READ_LOCK) ){
|
(pIter->eLock!=eLock || eLock!=READ_LOCK) ){
|
||||||
return SQLITE_BUSY;
|
return SQLITE_LOCKED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6484,6 +6484,14 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
|
|||||||
return pBt->pSchema;
|
return pBt->pSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return true if another user of the same shared btree as the argument
|
||||||
|
** handle holds an exclusive lock on the sqlite_master table.
|
||||||
|
*/
|
||||||
|
int sqlite3BtreeSchemaLocked(Btree *p){
|
||||||
|
return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
/*
|
/*
|
||||||
** Enable the shared pager and schema features.
|
** Enable the shared pager and schema features.
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** subsystem. See comments in the source code for a detailed description
|
** subsystem. See comments in the source code for a detailed description
|
||||||
** of what each interface routine does.
|
** of what each interface routine does.
|
||||||
**
|
**
|
||||||
** @(#) $Id: btree.h,v 1.67 2006/01/05 11:34:34 danielk1977 Exp $
|
** @(#) $Id: btree.h,v 1.68 2006/01/06 13:00:30 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@@ -77,6 +77,7 @@ int sqlite3BtreeIsInTrans(Btree*);
|
|||||||
int sqlite3BtreeIsInStmt(Btree*);
|
int sqlite3BtreeIsInStmt(Btree*);
|
||||||
int sqlite3BtreeSync(Btree*, const char *zMaster);
|
int sqlite3BtreeSync(Btree*, const char *zMaster);
|
||||||
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
||||||
|
int sqlite3BtreeSchemaLocked(Btree *);
|
||||||
|
|
||||||
const char *sqlite3BtreeGetFilename(Btree *);
|
const char *sqlite3BtreeGetFilename(Btree *);
|
||||||
const char *sqlite3BtreeGetDirname(Btree *);
|
const char *sqlite3BtreeGetDirname(Btree *);
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** interface, and routines that contribute to loading the database schema
|
** interface, and routines that contribute to loading the database schema
|
||||||
** from disk.
|
** from disk.
|
||||||
**
|
**
|
||||||
** $Id: prepare.c,v 1.13 2006/01/05 11:34:34 danielk1977 Exp $
|
** $Id: prepare.c,v 1.14 2006/01/06 13:00:30 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -436,6 +436,7 @@ int sqlite3_prepare(
|
|||||||
Parse sParse;
|
Parse sParse;
|
||||||
char *zErrMsg = 0;
|
char *zErrMsg = 0;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
int i;
|
||||||
|
|
||||||
assert( !sqlite3Tsd()->mallocFailed );
|
assert( !sqlite3Tsd()->mallocFailed );
|
||||||
|
|
||||||
@@ -445,6 +446,19 @@ int sqlite3_prepare(
|
|||||||
return SQLITE_MISUSE;
|
return SQLITE_MISUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If any attached database schemas are locked, do not proceed with
|
||||||
|
** compilation. Instead return SQLITE_LOCKED immediately.
|
||||||
|
*/
|
||||||
|
for(i=0; i<db->nDb; i++) {
|
||||||
|
Btree *pBt = db->aDb[i].pBt;
|
||||||
|
if( pBt && sqlite3BtreeSchemaLocked(pBt) ){
|
||||||
|
const char *zDb = db->aDb[i].zName;
|
||||||
|
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
|
||||||
|
sqlite3SafetyOff(db);
|
||||||
|
return SQLITE_LOCKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(&sParse, 0, sizeof(sParse));
|
memset(&sParse, 0, sizeof(sParse));
|
||||||
sParse.db = db;
|
sParse.db = db;
|
||||||
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
||||||
@@ -524,7 +538,7 @@ int sqlite3_prepare16(
|
|||||||
** tricky bit is figuring out the pointer to return in *pzTail.
|
** tricky bit is figuring out the pointer to return in *pzTail.
|
||||||
*/
|
*/
|
||||||
char *zSql8 = 0;
|
char *zSql8 = 0;
|
||||||
char *zTail8 = 0;
|
const char *zTail8 = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if( sqlite3SafetyCheck(db) ){
|
if( sqlite3SafetyCheck(db) ){
|
||||||
|
103
test/shared.test
103
test/shared.test
@@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the SELECT statement.
|
# focus of this file is testing the SELECT statement.
|
||||||
#
|
#
|
||||||
# $Id: shared.test,v 1.3 2006/01/06 06:33:13 danielk1977 Exp $
|
# $Id: shared.test,v 1.4 2006/01/06 13:00:30 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -73,7 +73,7 @@ do_test shared-1.4 {
|
|||||||
catchsql {
|
catchsql {
|
||||||
INSERT INTO abc VALUES(4, 5, 6);
|
INSERT INTO abc VALUES(4, 5, 6);
|
||||||
} db2
|
} db2
|
||||||
} {1 {database is locked}}
|
} {1 {database table is locked}}
|
||||||
do_test shared-1.5 {
|
do_test shared-1.5 {
|
||||||
# Using connection 2 (the one without the open transaction), try to create
|
# Using connection 2 (the one without the open transaction), try to create
|
||||||
# a new table. This should fail because of the open read transaction
|
# a new table. This should fail because of the open read transaction
|
||||||
@@ -81,7 +81,7 @@ do_test shared-1.5 {
|
|||||||
catchsql {
|
catchsql {
|
||||||
CREATE TABLE def(d, e, f);
|
CREATE TABLE def(d, e, f);
|
||||||
} db2
|
} db2
|
||||||
} {1 {database is locked}}
|
} {1 {database table is locked}}
|
||||||
do_test shared-1.6 {
|
do_test shared-1.6 {
|
||||||
# Upgrade connection 1's transaction to a write transaction. Create
|
# Upgrade connection 1's transaction to a write transaction. Create
|
||||||
# a new table - def - and insert a row into it. Because the connection 1
|
# a new table - def - and insert a row into it. Because the connection 1
|
||||||
@@ -104,7 +104,7 @@ do_test shared-1.7 {
|
|||||||
catchsql {
|
catchsql {
|
||||||
SELECT * FROM sqlite_master;
|
SELECT * FROM sqlite_master;
|
||||||
} db2
|
} db2
|
||||||
} {1 {database is locked}}
|
} {1 {database schema is locked: main}}
|
||||||
do_test shared-1.8 {
|
do_test shared-1.8 {
|
||||||
# Commit the connection 1 transaction.
|
# Commit the connection 1 transaction.
|
||||||
execsql {
|
execsql {
|
||||||
@@ -133,7 +133,7 @@ do_test shared-2.2 {
|
|||||||
catchsql {
|
catchsql {
|
||||||
INSERT INTO abc VALUES(1, 2, 3);
|
INSERT INTO abc VALUES(1, 2, 3);
|
||||||
} db2
|
} db2
|
||||||
} {1 {database is locked}}
|
} {1 {database table is locked}}
|
||||||
do_test shared-2.3 {
|
do_test shared-2.3 {
|
||||||
# Turn db's transaction into a write-transaction. db3 should still be
|
# Turn db's transaction into a write-transaction. db3 should still be
|
||||||
# able to read from table def (but will not see the new row). Connection
|
# able to read from table def (but will not see the new row). Connection
|
||||||
@@ -157,7 +157,7 @@ do_test shared-2.3 {
|
|||||||
] [
|
] [
|
||||||
catchsql { SELECT * FROM def; } db2
|
catchsql { SELECT * FROM def; } db2
|
||||||
]
|
]
|
||||||
} {0 {IV V VI} 1 {database is locked}}
|
} {0 {IV V VI} 1 {database table is locked}}
|
||||||
do_test shared-2.4 {
|
do_test shared-2.4 {
|
||||||
# Commit the open transaction on db. db2 still holds a read-transaction.
|
# Commit the open transaction on db. db2 still holds a read-transaction.
|
||||||
# This should prevent db3 from writing to the database, but not from
|
# This should prevent db3 from writing to the database, but not from
|
||||||
@@ -257,10 +257,16 @@ do_test shared-4.1.3 {
|
|||||||
set sqlite_open_file_count
|
set sqlite_open_file_count
|
||||||
} {2}
|
} {2}
|
||||||
|
|
||||||
|
# Sanity check: Create a table in ./test.db via handle db, and test that handle
|
||||||
|
# db2 can "see" the new table immediately. A handle using a seperate pager
|
||||||
|
# cache would have to reload the database schema before this were possible.
|
||||||
|
#
|
||||||
do_test shared-4.2.1 {
|
do_test shared-4.2.1 {
|
||||||
execsql {
|
execsql {
|
||||||
CREATE TABLE abc(a, b, c);
|
CREATE TABLE abc(a, b, c);
|
||||||
|
CREATE TABLE def(d, e, f);
|
||||||
INSERT INTO abc VALUES('i', 'ii', 'iii');
|
INSERT INTO abc VALUES('i', 'ii', 'iii');
|
||||||
|
INSERT INTO def VALUES('I', 'II', 'III');
|
||||||
}
|
}
|
||||||
} {}
|
} {}
|
||||||
do_test shared-4.2.2 {
|
do_test shared-4.2.2 {
|
||||||
@@ -269,6 +275,91 @@ do_test shared-4.2.2 {
|
|||||||
} db2
|
} db2
|
||||||
} {i ii iii}
|
} {i ii iii}
|
||||||
|
|
||||||
|
# Open a read-transaction and read from table abc via handle 2. Check that
|
||||||
|
# handle 1 can read table abc. Check that handle 1 cannot modify table abc
|
||||||
|
# or the database schema. Then check that handle 1 can modify table def.
|
||||||
|
#
|
||||||
|
do_test shared-4.3.1 {
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
SELECT * FROM test.abc;
|
||||||
|
} db2
|
||||||
|
} {i ii iii}
|
||||||
|
do_test shared-4.3.2 {
|
||||||
|
catchsql {
|
||||||
|
INSERT INTO abc VALUES('iv', 'v', 'vi');
|
||||||
|
}
|
||||||
|
} {1 {database table is locked}}
|
||||||
|
do_test shared-4.3.3 {
|
||||||
|
catchsql {
|
||||||
|
CREATE TABLE ghi(g, h, i);
|
||||||
|
}
|
||||||
|
} {1 {database table is locked}}
|
||||||
|
do_test shared-4.3.3 {
|
||||||
|
catchsql {
|
||||||
|
INSERT INTO def VALUES('IV', 'V', 'VI');
|
||||||
|
}
|
||||||
|
} {0 {}}
|
||||||
|
do_test shared-4.3.4 {
|
||||||
|
# Cleanup: commit the transaction opened by db2.
|
||||||
|
execsql {
|
||||||
|
COMMIT
|
||||||
|
} db2
|
||||||
|
} {}
|
||||||
|
|
||||||
|
# Open a write-transaction using handle 1 and modify the database schema.
|
||||||
|
# Then try to execute a compiled statement to read from the same
|
||||||
|
# database via handle 2 (fails to get the lock on sqlite_master). Also
|
||||||
|
# try to compile a read of the same database using handle 2 (also fails).
|
||||||
|
# Finally, compile a read of the other database using handle 2. This
|
||||||
|
# should also fail.
|
||||||
|
#
|
||||||
|
do_test shared-4.4.1.2 {
|
||||||
|
# Sanity check 1: Check that the schema is what we think it is when viewed
|
||||||
|
# via handle 1.
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE test2.ghi(g, h, i);
|
||||||
|
SELECT 'test.db:'||name FROM sqlite_master
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'test2.db:'||name FROM test2.sqlite_master;
|
||||||
|
}
|
||||||
|
} {test.db:abc test.db:def test2.db:ghi}
|
||||||
|
do_test shared-4.4.1.2 {
|
||||||
|
# Sanity check 2: Check that the schema is what we think it is when viewed
|
||||||
|
# via handle 2.
|
||||||
|
execsql {
|
||||||
|
SELECT 'test2.db:'||name FROM sqlite_master
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'test.db:'||name FROM test.sqlite_master;
|
||||||
|
} db2
|
||||||
|
} {test2.db:ghi test.db:abc test.db:def}
|
||||||
|
|
||||||
|
do_test shared-4.4.2 {
|
||||||
|
set ::DB2 [sqlite3_connection_pointer db2]
|
||||||
|
set sql {SELECT * FROM abc}
|
||||||
|
set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
CREATE TABLE jkl(j, k, l);
|
||||||
|
}
|
||||||
|
sqlite3_step $::STMT1
|
||||||
|
} {SQLITE_ERROR}
|
||||||
|
do_test shared-4.4.3 {
|
||||||
|
sqlite3_finalize $::STMT1
|
||||||
|
} {SQLITE_LOCKED}
|
||||||
|
do_test shared-4.4.4 {
|
||||||
|
set rc [catch {
|
||||||
|
set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
|
||||||
|
} msg]
|
||||||
|
list $rc $msg
|
||||||
|
} {1 {(6) database schema is locked: test}}
|
||||||
|
do_test shared-4.4.5 {
|
||||||
|
set rc [catch {
|
||||||
|
set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY]
|
||||||
|
} msg]
|
||||||
|
list $rc $msg
|
||||||
|
} {1 {(6) database schema is locked: test}}
|
||||||
|
|
||||||
catch {db2 close}
|
catch {db2 close}
|
||||||
catch {db close}
|
catch {db close}
|
||||||
|
|
||||||
|
@@ -120,12 +120,9 @@ read-lock, write-lock or no lock on each database table.
|
|||||||
or a single active write lock. To read data a table, a connection must
|
or a single active write lock. To read data a table, a connection must
|
||||||
first obtain a read-lock. To write to a table, a connection must obtain a
|
first obtain a read-lock. To write to a table, a connection must obtain a
|
||||||
write-lock on that table. If a required table lock cannot be obtained,
|
write-lock on that table. If a required table lock cannot be obtained,
|
||||||
the query fails and SQLITE_BUSY is returned to the caller.
|
the query fails and SQLITE_LOCKED is returned to the caller.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><b>TODO: Should we be invoking the busy-handler here? Just waiting won't do
|
|
||||||
any good, but something else might... </b></p>
|
|
||||||
|
|
||||||
<p>Once a connection obtains a table lock, it is not released until the
|
<p>Once a connection obtains a table lock, it is not released until the
|
||||||
current transaction (read or write) is concluded.
|
current transaction (read or write) is concluded.
|
||||||
</p>
|
</p>
|
||||||
@@ -181,12 +178,32 @@ accessing any database tables or obtaining any other read or write locks.</li>
|
|||||||
a CREATE or DROP TABLE statement), a connection must obtain a write-lock on
|
a CREATE or DROP TABLE statement), a connection must obtain a write-lock on
|
||||||
<i>sqlite_master</i>.
|
<i>sqlite_master</i>.
|
||||||
</li>
|
</li>
|
||||||
<li>A connection may not compile an SQL statement that refers to database
|
<li>A connection may not compile an SQL statement if any other connection
|
||||||
tables if any other connection is holding a write-lock on <i>sqlite_master</i>.
|
is holding a write-lock on the <i>sqlite_master</i> table of any attached
|
||||||
|
database (including the default database, "main").
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HEADING 3 {Schema locking and attached databases}
|
||||||
|
|
||||||
|
puts {
|
||||||
|
<p>The final point in the bullet list is deceptively complicated when
|
||||||
|
multiple databases are attached to connections. Exactly when is access to a
|
||||||
|
specific database schema "required" to compile a statement? The way in
|
||||||
|
which SQLite resolves the names of schema objects (i.e. tables, indices,
|
||||||
|
triggers and views) depends on whether or not the name was qualified
|
||||||
|
or unqualified in the original SQL statement. The first statement below
|
||||||
|
uses a qualified table name, the second uses an unqualified table name.
|
||||||
|
Both refer to the same underlying table.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
SELECT name FROM main.sqlite_master;
|
||||||
|
SELECT name FROM sqlite_master;
|
||||||
|
</pre>
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
HEADING 1 {Thread Related Issues}
|
HEADING 1 {Thread Related Issues}
|
||||||
|
|
||||||
puts {
|
puts {
|
||||||
|
Reference in New Issue
Block a user