mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Five-algorithm conflict resolution appears to be working. (CVS 363)
FossilOrigin-Name: 0115518f8e4591123582e3d2bb67282111ebcf60
This commit is contained in:
26
manifest
26
manifest
@@ -1,5 +1,5 @@
|
||||
C Get\sthe\sABORT\sconflict\sresolution\salgorithm\sworking.\s(CVS\s362)
|
||||
D 2002-02-02T18:49:20
|
||||
C Five-algorithm\sconflict\sresolution\sappears\sto\sbe\sworking.\s(CVS\s363)
|
||||
D 2002-02-03T00:56:10
|
||||
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
|
||||
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
|
||||
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
||||
@@ -19,21 +19,21 @@ F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
|
||||
F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360
|
||||
F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
|
||||
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
|
||||
F src/btree.c 94deba286af8e1f665d98378c099da2f7455f291
|
||||
F src/btree.c ba5712cf620f80055948cc41157e14eab6ceee86
|
||||
F src/btree.h a94bef69f5174461331b6b9ae45a2d84f05af6db
|
||||
F src/build.c 397d78ce466e3c22d56de85ae23d8a2777d3b9e6
|
||||
F src/build.c 0c7346d0522e59be67a4bb841020540d8ba5d136
|
||||
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
|
||||
F src/expr.c a2a87dbd411a508ff89dffa90505ad42dac2f920
|
||||
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
|
||||
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
|
||||
F src/insert.c 051e909cf4c8505aae930dcd773215404e187f23
|
||||
F src/insert.c 173da7b06fe9282e0f529ff1e599460304ceeb23
|
||||
F src/main.c 300320ba68d3e5b22c2c5b2c07fa884878202181
|
||||
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
||||
F src/os.c 1953080d14098cd45e5bde88941567688efb72b1
|
||||
F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6
|
||||
F src/pager.c 4059bda97a7e10083b77b7d347fea45426b08589
|
||||
F src/pager.h b28f004e2f5541dc60cc32db01bf80cf4d056283
|
||||
F src/parse.y 88856227ae8472d0f4ae8514bc9561a6ca060690
|
||||
F src/parse.y f081d7d4ef17deb2e20511addd32d07e277edc25
|
||||
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
|
||||
F src/random.c f6b36bec5ebd3edb3440224bf5bf811fe4ac9a1b
|
||||
F src/select.c fc11d5a8c2bae1b62d8028ffb111c773ad6bf161
|
||||
@@ -49,7 +49,7 @@ F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
|
||||
F src/tokenize.c 01a09db6adf933e941db1b781789a0c175be6504
|
||||
F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
|
||||
F src/util.c 8f8973dd55a6ec63be9632fc5de86965c99d6327
|
||||
F src/vdbe.c 3e9d9dba06fb7f6fe85ca3c345eedd32bf27f3a7
|
||||
F src/vdbe.c df1c920e74b2cd76d763833a655fbabb67f17237
|
||||
F src/vdbe.h 3791edabb212038ae5fbcfa72580204596be01a7
|
||||
F src/where.c 2dda39367f193194e4c7d2e0dcab31527d9d8aba
|
||||
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
|
||||
@@ -57,7 +57,7 @@ F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
||||
F test/btree.test 6ab4dc5f595905a276ef588fad3c9236dc07a47b
|
||||
F test/btree2.test 08e9485619265cbaf5d11bd71f357cdc26bb87e0
|
||||
F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895
|
||||
F test/conflict.test 70d40d77bb83f326574488d3cde1d0f3c51a0949
|
||||
F test/conflict.test dd1b380595bb48b90289d761f4d11a46d7c60178
|
||||
F test/copy.test 9ff0063c0b95b3d51b8d0c7fe0ff51dabaa66549
|
||||
F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
|
||||
F test/expr.test c8a495050dcec3f9e68538c3ef466726933302c1
|
||||
@@ -108,21 +108,21 @@ F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
|
||||
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
|
||||
F www/c_interface.tcl 82a026b1681757f13b3f62e035f3a31407c1d353
|
||||
F www/changes.tcl 5c3b5b80d7144d46f100f333d4cab6184828a6c2
|
||||
F www/conflict.tcl 3f70c01680b8d763bf3305eb67f6d85fdf83b497
|
||||
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
|
||||
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
|
||||
F www/download.tcl a6d75b8b117cd33dcb090bef7e80d7556d28ebe0
|
||||
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
|
||||
F www/faq.tcl 32cbc134879871604070d4cc3a32e73fb22a35f9
|
||||
F www/formatchng.tcl 2d9a35c787823b48d72a5c64bb5414a43e26d5ad
|
||||
F www/index.tcl 748614d8208c761ed3840e7958b8eed04de81822
|
||||
F www/lang.tcl 7ad595247fd81f394012a0cfd84ccd6241b9e59a
|
||||
F www/lang.tcl 260f3f9015344634ed9c2518f9a856462d37d6a6
|
||||
F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
|
||||
F www/opcode.tcl bdec8ef9f100dbd87bbef8976c54b88e43fd8ccc
|
||||
F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
|
||||
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
||||
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
|
||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||
P aaa53e113ef849e34883ead8ae584c722ad967db
|
||||
R f2763ccecef4a6c8cd264dd83b3c6a22
|
||||
P 9be4d4c6f12056782966396dca0b8e2d384d0cf2
|
||||
R 60fe69f0169f5844176ca5b7853e2e65
|
||||
U drh
|
||||
Z fb37183391242f0b96b036b1bf3ee1ea
|
||||
Z fa5a72d3a4d7961b510d6a8d5ba99c2c
|
||||
|
@@ -1 +1 @@
|
||||
9be4d4c6f12056782966396dca0b8e2d384d0cf2
|
||||
0115518f8e4591123582e3d2bb67282111ebcf60
|
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.47 2002/02/02 18:49:20 drh Exp $
|
||||
** $Id: btree.c,v 1.48 2002/02/03 00:56:10 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -816,7 +816,9 @@ int sqliteBtreeRollback(Btree *pBt){
|
||||
*/
|
||||
int sqliteBtreeBeginCkpt(Btree *pBt){
|
||||
int rc;
|
||||
if( !pBt->inTrans || pBt->inCkpt ) return SQLITE_ERROR;
|
||||
if( !pBt->inTrans || pBt->inCkpt ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
rc = sqlitepager_ckpt_begin(pBt->pPager);
|
||||
pBt->inCkpt = 1;
|
||||
return rc;
|
||||
@@ -834,6 +836,7 @@ int sqliteBtreeCommitCkpt(Btree *pBt){
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
pBt->inCkpt = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -856,6 +859,7 @@ int sqliteBtreeRollbackCkpt(Btree *pBt){
|
||||
}
|
||||
}
|
||||
rc = sqlitepager_ckpt_rollback(pBt->pPager);
|
||||
pBt->inCkpt = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.71 2002/02/02 18:49:20 drh Exp $
|
||||
** $Id: build.c,v 1.72 2002/02/03 00:56:10 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -518,7 +518,6 @@ void sqliteAddNotNull(Parse *pParse, int onError){
|
||||
int i;
|
||||
if( (p = pParse->pNewTable)==0 ) return;
|
||||
i = p->nCol-1;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
if( i>=0 ) p->aCol[i].notNull = onError;
|
||||
}
|
||||
|
||||
@@ -618,7 +617,6 @@ void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
|
||||
if( iCol>=0 && iCol<pTab->nCol ){
|
||||
zType = pTab->aCol[iCol].zType;
|
||||
}
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
if( pParse->db->file_format>=1 &&
|
||||
zType && sqliteStrICmp(zType, "INTEGER")==0 ){
|
||||
pTab->iPKey = iCol;
|
||||
@@ -854,7 +852,6 @@ void sqliteCreateIndex(
|
||||
int hideName = 0; /* Do not put table name in the hash table */
|
||||
|
||||
if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
|
||||
/*
|
||||
** Find the table that is to be indexed. Return early if not found.
|
||||
|
23
src/insert.c
23
src/insert.c
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.40 2002/02/02 18:49:20 drh Exp $
|
||||
** $Id: insert.c,v 1.41 2002/02/03 00:56:10 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -396,9 +396,6 @@ void sqliteGenerateConstraintChecks(
|
||||
v = sqliteGetVdbe(pParse);
|
||||
assert( v!=0 );
|
||||
nCol = pTab->nCol;
|
||||
if( overrideError==OE_Default ){
|
||||
overrideError = pParse->db->onError;
|
||||
}
|
||||
|
||||
/* Test all NOT NULL constraints.
|
||||
*/
|
||||
@@ -412,7 +409,8 @@ void sqliteGenerateConstraintChecks(
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = pParse->db->onError;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
}
|
||||
if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
|
||||
onError = OE_Abort;
|
||||
@@ -447,16 +445,17 @@ void sqliteGenerateConstraintChecks(
|
||||
|
||||
/* Test all UNIQUE constraints. Add index records as we go.
|
||||
*/
|
||||
if( (recnoChng || !isUpdate) && pTab->iPKey>=0 && pTab->keyConf!=OE_Replace
|
||||
&& overrideError!=OE_Replace ){
|
||||
sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
|
||||
jumpInst = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
|
||||
if( (recnoChng || !isUpdate) && pTab->iPKey>=0 ){
|
||||
onError = pTab->keyConf;
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = pParse->db->onError;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
}
|
||||
if( onError!=OE_Replace ){
|
||||
sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
|
||||
jumpInst = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
|
||||
switch( onError ){
|
||||
case OE_Rollback:
|
||||
case OE_Abort:
|
||||
@@ -478,6 +477,7 @@ void sqliteGenerateConstraintChecks(
|
||||
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
extra = 0;
|
||||
for(extra=(-1), iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
||||
if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;
|
||||
@@ -497,7 +497,8 @@ void sqliteGenerateConstraintChecks(
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = pParse->db->onError;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
|
||||
jumpInst = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
|
||||
|
@@ -14,7 +14,7 @@
|
||||
** the parser. Lemon will also generate a header file containing
|
||||
** numeric codes for all of the tokens.
|
||||
**
|
||||
** @(#) $Id: parse.y,v 1.46 2002/02/02 15:01:16 drh Exp $
|
||||
** @(#) $Id: parse.y,v 1.47 2002/02/03 00:56:10 drh Exp $
|
||||
*/
|
||||
%token_prefix TK_
|
||||
%token_type {Token}
|
||||
@@ -57,10 +57,7 @@ explain ::= EXPLAIN. {pParse->explain = 1;}
|
||||
///////////////////// Begin and end transactions. ////////////////////////////
|
||||
//
|
||||
|
||||
// For now, disable the ability to change the default conflict resolution
|
||||
// algorithm in a transaction. We made add it back later.
|
||||
// cmd ::= BEGIN trans_opt onconf(R). {sqliteBeginTransaction(pParse,R);}
|
||||
cmd ::= BEGIN trans_opt. {sqliteBeginTransaction(pParse, OE_Default);}
|
||||
cmd ::= BEGIN trans_opt onconf(R). {sqliteBeginTransaction(pParse,R);}
|
||||
trans_opt ::= .
|
||||
trans_opt ::= TRANSACTION.
|
||||
trans_opt ::= TRANSACTION ids.
|
||||
|
@@ -30,7 +30,7 @@
|
||||
** But other routines are also provided to help in building up
|
||||
** a program instruction by instruction.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.114 2002/02/02 18:49:21 drh Exp $
|
||||
** $Id: vdbe.c,v 1.115 2002/02/03 00:56:10 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -4511,10 +4511,9 @@ cleanup:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
}
|
||||
sqliteBtreeCommitCkpt(pBt);
|
||||
if( db->pBeTemp ) sqliteBtreeCommitCkpt(db->pBeTemp);
|
||||
}
|
||||
return rc;
|
||||
|
||||
/* Jump to here if a malloc() fails. It's hard to get a malloc()
|
||||
|
@@ -13,263 +13,368 @@
|
||||
# This file implements tests for the conflict resolution extension
|
||||
# to SQLite.
|
||||
#
|
||||
# $Id: conflict.test,v 1.4 2002/01/31 15:54:23 drh Exp $
|
||||
# $Id: conflict.test,v 1.5 2002/02/03 00:56:11 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Create a table with three fields, two of which must be
|
||||
# UNIQUE.
|
||||
# Create tables for the first group of tests.
|
||||
#
|
||||
do_test conflict-1.1 {
|
||||
do_test conflict-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b, c, UNIQUE(a,b));
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
CREATE TABLE t2(x);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {3}
|
||||
do_test conflict-1.2 {
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
do_test conflict-1.3 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 3}
|
||||
do_test conflict-1.4 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 4}
|
||||
do_test conflict-1.5 {
|
||||
catchsql {
|
||||
INSERT OR ABORT INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
do_test conflict-1.6 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 4}
|
||||
do_test conflict-1.7 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 5}
|
||||
do_test conflict-1.8 {
|
||||
catchsql {
|
||||
INSERT OR ABORT INTO t1 VALUES(1,2,6);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
} {}
|
||||
|
||||
do_test conflict-1.9 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t2(a,b,c);
|
||||
INSERT INTO t2 VALUES(1,2,11);
|
||||
INSERT INTO t2 VALUES(1,2,12);
|
||||
INSERT INTO t2 VALUES(1,2,13);
|
||||
INSERT INTO t2 VALUES(1,2,14);
|
||||
INSERT INTO t2 VALUES(1,3,21);
|
||||
INSERT INTO t2 VALUES(1,3,22);
|
||||
INSERT INTO t2 VALUES(1,3,23);
|
||||
INSERT INTO t2 VALUES(1,3,24);
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t2;
|
||||
}
|
||||
} 8
|
||||
do_test conflict-1.10 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {5 21}}
|
||||
do_test conflict-1.11 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {14 24}}
|
||||
|
||||
###### Fix me!
|
||||
do_test conflict-1.12 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {14 24}}
|
||||
|
||||
do_test conflict-1.13 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An INSERT or REPLACE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "c" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t2
|
||||
#
|
||||
foreach {i conf cmd t0 t1 t2} {
|
||||
1 {} INSERT 1 {} 1
|
||||
2 {} {INSERT OR IGNORE} 0 3 1
|
||||
3 {} {INSERT OR REPLACE} 0 4 1
|
||||
4 {} REPLACE 0 4 1
|
||||
5 {} {INSERT OR FAIL} 1 {} 1
|
||||
6 {} {INSERT OR ABORT} 1 {} 1
|
||||
7 {} {INSERT OR ROLLBACK} 1 {} {}
|
||||
8 IGNORE INSERT 0 3 1
|
||||
9 IGNORE {INSERT OR IGNORE} 0 3 1
|
||||
10 IGNORE {INSERT OR REPLACE} 0 4 1
|
||||
11 IGNORE REPLACE 0 4 1
|
||||
12 IGNORE {INSERT OR FAIL} 1 {} 1
|
||||
13 IGNORE {INSERT OR ABORT} 1 {} 1
|
||||
14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
|
||||
15 REPLACE INSERT 0 4 1
|
||||
16 FAIL INSERT 1 {} 1
|
||||
17 ABORT INSERT 1 {} 1
|
||||
18 ROLLBACK INSERT 1 {} {}
|
||||
} {
|
||||
do_test conflict-1.$i {
|
||||
if {$conf!=""} {set conf "ON CONFLICT $conf"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
INSERT INTO t1 VALUES(1,3,4);
|
||||
INSERT INTO t1 VALUES(2,3,5);
|
||||
COMMIT;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 2 3 1 3 4 2 3 5}
|
||||
do_test conflict-1.14 {
|
||||
catchsql {
|
||||
UPDATE OR ABORT t1 SET b=3 WHERE b=2;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}};
|
||||
do_test conflict-1.15 {
|
||||
catchsql {
|
||||
UPDATE t1 SET b=3 WHERE b=2;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}};
|
||||
do_test conflict-1.16 {
|
||||
catchsql {
|
||||
UPDATE OR IGNORE t1 SET b=3 WHERE b=2;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {1 2 3 1 3 4 2 3 5}}
|
||||
do_test conflict-1.17 {
|
||||
catchsql {
|
||||
UPDATE OR REPLACE t1 SET b=3 WHERE b=2;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {1 3 3 2 3 5}}
|
||||
BEGIN $conf;
|
||||
INSERT INTO t2 VALUES(1);
|
||||
$cmd INTO t1 VALUES(1,2,4);
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
|
||||
set r2 [execsql {SELECT x FROM t2}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
do_test conflict-2.1 {
|
||||
# Create tables for the first group of tests.
|
||||
#
|
||||
do_test conflict-2.0 {
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t1(a integer primary key, b, c, UNIQUE(a,b));
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE INDEX t1bc ON t1(b,c);
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(a,b));
|
||||
CREATE TABLE t2(x);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {3}
|
||||
do_test conflict-2.2 {
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
do_test conflict-2.3 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 3}
|
||||
do_test conflict-2.4 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 VALUES(1,2,4);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 4}
|
||||
do_test conflict-2.5 {
|
||||
catchsql {
|
||||
INSERT OR ABORT INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
do_test conflict-2.6 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 4}
|
||||
do_test conflict-2.7 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 VALUES(1,2,5);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 5}
|
||||
do_test conflict-2.8 {
|
||||
catchsql {
|
||||
INSERT OR ABORT INTO t1 VALUES(1,2,6);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}}
|
||||
} {}
|
||||
|
||||
do_test conflict-2.9 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t2(a,b,c INTEGER PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES(1,2,11);
|
||||
INSERT INTO t2 VALUES(1,2,12);
|
||||
INSERT INTO t2 VALUES(1,2,13);
|
||||
INSERT INTO t2 VALUES(1,2,14);
|
||||
INSERT INTO t2 VALUES(2,2,21);
|
||||
INSERT INTO t2 VALUES(2,2,22);
|
||||
INSERT INTO t2 VALUES(2,2,23);
|
||||
INSERT INTO t2 VALUES(2,2,24);
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t2;
|
||||
}
|
||||
} 8
|
||||
do_test conflict-2.10 {
|
||||
catchsql {
|
||||
INSERT OR IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {5 21}}
|
||||
do_test conflict-2.11 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {14 24}}
|
||||
|
||||
###### Fix me!
|
||||
do_test conflict-2.12 {
|
||||
catchsql {
|
||||
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {0 {14 24}}
|
||||
|
||||
do_test conflict-2.13 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An INSERT or REPLACE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "c" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t2
|
||||
#
|
||||
foreach {i conf cmd t0 t1 t2} {
|
||||
1 {} INSERT 1 {} 1
|
||||
2 {} {INSERT OR IGNORE} 0 3 1
|
||||
3 {} {INSERT OR REPLACE} 0 4 1
|
||||
4 {} REPLACE 0 4 1
|
||||
5 {} {INSERT OR FAIL} 1 {} 1
|
||||
6 {} {INSERT OR ABORT} 1 {} 1
|
||||
7 {} {INSERT OR ROLLBACK} 1 {} {}
|
||||
8 IGNORE INSERT 0 3 1
|
||||
9 IGNORE {INSERT OR IGNORE} 0 3 1
|
||||
10 IGNORE {INSERT OR REPLACE} 0 4 1
|
||||
11 IGNORE REPLACE 0 4 1
|
||||
12 IGNORE {INSERT OR FAIL} 1 {} 1
|
||||
13 IGNORE {INSERT OR ABORT} 1 {} 1
|
||||
14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
|
||||
15 REPLACE INSERT 0 4 1
|
||||
16 FAIL INSERT 1 {} 1
|
||||
17 ABORT INSERT 1 {} 1
|
||||
18 ROLLBACK INSERT 1 {} {}
|
||||
} {
|
||||
do_test conflict-2.$i {
|
||||
if {$conf!=""} {set conf "ON CONFLICT $conf"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
INSERT INTO t1 VALUES(2,3,4);
|
||||
INSERT INTO t1 VALUES(3,3,5);
|
||||
COMMIT;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 2 3 2 3 4 3 3 5}
|
||||
do_test conflict-2.14 {
|
||||
catchsql {
|
||||
UPDATE OR ABORT t1 SET a=2, b=3 WHERE b=2;
|
||||
BEGIN $conf;
|
||||
INSERT INTO t2 VALUES(1);
|
||||
$cmd INTO t1 VALUES(1,2,4);
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
|
||||
set r2 [execsql {SELECT x FROM t2}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
# Create tables for the first group of tests.
|
||||
#
|
||||
do_test conflict-3.0 {
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t1(a, b, c INTEGER PRIMARY KEY, UNIQUE(a,b));
|
||||
CREATE TABLE t2(x);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
}
|
||||
} {1 {constraint failed}};
|
||||
do_test conflict-2.15 {
|
||||
catchsql {
|
||||
UPDATE t1 SET a=2, b=3 WHERE b=2;
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
} {}
|
||||
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An INSERT or REPLACE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "c" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t2
|
||||
#
|
||||
foreach {i conf cmd t0 t1 t2} {
|
||||
1 {} INSERT 1 {} 1
|
||||
2 {} {INSERT OR IGNORE} 0 3 1
|
||||
3 {} {INSERT OR REPLACE} 0 4 1
|
||||
4 {} REPLACE 0 4 1
|
||||
5 {} {INSERT OR FAIL} 1 {} 1
|
||||
6 {} {INSERT OR ABORT} 1 {} 1
|
||||
7 {} {INSERT OR ROLLBACK} 1 {} {}
|
||||
8 IGNORE INSERT 0 3 1
|
||||
9 IGNORE {INSERT OR IGNORE} 0 3 1
|
||||
10 IGNORE {INSERT OR REPLACE} 0 4 1
|
||||
11 IGNORE REPLACE 0 4 1
|
||||
12 IGNORE {INSERT OR FAIL} 1 {} 1
|
||||
13 IGNORE {INSERT OR ABORT} 1 {} 1
|
||||
14 IGNORE {INSERT OR ROLLBACK} 1 {} {}
|
||||
15 REPLACE INSERT 0 4 1
|
||||
16 FAIL INSERT 1 {} 1
|
||||
17 ABORT INSERT 1 {} 1
|
||||
18 ROLLBACK INSERT 1 {} {}
|
||||
} {
|
||||
do_test conflict-3.$i {
|
||||
if {$conf!=""} {set conf "ON CONFLICT $conf"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
BEGIN $conf;
|
||||
INSERT INTO t2 VALUES(1);
|
||||
$cmd INTO t1 VALUES(1,2,4);
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
|
||||
set r2 [execsql {SELECT x FROM t2}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
do_test conflict-4.0 {
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(x);
|
||||
SELECT x FROM t2;
|
||||
}
|
||||
} {1 {constraint failed}};
|
||||
do_test conflict-2.16 {
|
||||
catchsql {
|
||||
UPDATE OR IGNORE t1 SET a=2, b=3 WHERE b=2;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
} {}
|
||||
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf1 The conflict resolution algorithm on the UNIQUE constraint
|
||||
# conf2 The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An INSERT or REPLACE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "c" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t2
|
||||
#
|
||||
foreach {i conf1 conf2 cmd t0 t1 t2} {
|
||||
1 {} {} INSERT 1 {} 1
|
||||
2 REPLACE {} INSERT 0 4 1
|
||||
3 IGNORE {} INSERT 0 3 1
|
||||
4 FAIL {} INSERT 1 {} 1
|
||||
5 ABORT {} INSERT 1 {} 1
|
||||
6 ROLLBACK {} INSERT 1 {} {}
|
||||
7 REPLACE {} {INSERT OR IGNORE} 0 3 1
|
||||
8 IGNORE {} {INSERT OR REPLACE} 0 4 1
|
||||
9 FAIL {} {INSERT OR IGNORE} 0 3 1
|
||||
10 ABORT {} {INSERT OR REPLACE} 0 4 1
|
||||
11 ROLLBACK {} {INSERT OR IGNORE } 0 3 1
|
||||
12 REPLACE IGNORE INSERT 0 4 1
|
||||
13 IGNORE REPLACE INSERT 0 3 1
|
||||
14 FAIL IGNORE INSERT 1 {} 1
|
||||
15 ABORT REPLACE INSERT 1 {} 1
|
||||
16 ROLLBACK IGNORE INSERT 1 {} {}
|
||||
} {
|
||||
do_test conflict-4.$i {
|
||||
if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
|
||||
if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a,b,c,UNIQUE(a,b) $conf1);
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
BEGIN $conf2;
|
||||
INSERT INTO t2 VALUES(1);
|
||||
$cmd INTO t1 VALUES(1,2,4);
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
|
||||
set r2 [execsql {SELECT x FROM t2}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
do_test conflict-5.0 {
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(x);
|
||||
SELECT x FROM t2;
|
||||
}
|
||||
} {0 {1 2 3 2 3 4 3 3 5}}
|
||||
do_test conflict-2.17 {
|
||||
catchsql {
|
||||
UPDATE OR REPLACE t1 SET a=2, b=3 WHERE b=2;
|
||||
SELECT * FROM t1 ORDER BY c;
|
||||
} {}
|
||||
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf1 The conflict resolution algorithm on the NOT NULL constraint
|
||||
# conf2 The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An INSERT or REPLACE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "c" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t2
|
||||
#
|
||||
foreach {i conf1 conf2 cmd t0 t1 t2} {
|
||||
1 {} {} INSERT 1 {} 1
|
||||
2 REPLACE {} INSERT 0 5 1
|
||||
3 IGNORE {} INSERT 0 {} 1
|
||||
4 FAIL {} INSERT 1 {} 1
|
||||
5 ABORT {} INSERT 1 {} 1
|
||||
6 ROLLBACK {} INSERT 1 {} {}
|
||||
7 REPLACE {} {INSERT OR IGNORE} 0 {} 1
|
||||
8 IGNORE {} {INSERT OR REPLACE} 0 5 1
|
||||
9 FAIL {} {INSERT OR IGNORE} 0 {} 1
|
||||
10 ABORT {} {INSERT OR REPLACE} 0 5 1
|
||||
11 ROLLBACK {} {INSERT OR IGNORE} 0 {} 1
|
||||
12 {} {} {INSERT OR IGNORE} 0 {} 1
|
||||
13 {} {} {INSERT OR REPLACE} 0 5 1
|
||||
14 {} {} {INSERT OR FAIL} 1 {} 1
|
||||
15 {} {} {INSERT OR ABORT} 1 {} 1
|
||||
16 {} {} {INSERT OR ROLLBACK} 1 {} {}
|
||||
17 {} IGNORE INSERT 0 {} 1
|
||||
18 {} REPLACE INSERT 0 5 1
|
||||
19 {} FAIL INSERT 1 {} 1
|
||||
20 {} ABORT INSERT 1 {} 1
|
||||
21 {} ROLLBACK INSERT 1 {} {}
|
||||
22 REPLACE FAIL INSERT 0 5 1
|
||||
23 IGNORE ROLLBACK INSERT 0 {} 1
|
||||
} {
|
||||
if {$t0} {set t1 {constraint failed}}
|
||||
do_test conflict-5.$i {
|
||||
if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
|
||||
if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a,b,c NOT NULL $conf1 DEFAULT 5);
|
||||
DELETE FROM t2;
|
||||
BEGIN $conf2;
|
||||
INSERT INTO t2 VALUES(1);
|
||||
$cmd INTO t1 VALUES(1,2,NULL);
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {!$r0} {set r1 [execsql {SELECT c FROM t1}]}
|
||||
set r2 [execsql {SELECT x FROM t2}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
do_test conflict-6.0 {
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(a,b,c);
|
||||
INSERT INTO t2 VALUES(1,2,1);
|
||||
INSERT INTO t2 VALUES(2,3,2);
|
||||
INSERT INTO t2 VALUES(3,4,1);
|
||||
INSERT INTO t2 VALUES(4,5,4);
|
||||
SELECT c FROM t2 ORDER BY b;
|
||||
CREATE TABLE t3(x);
|
||||
INSERT INTO t3 VALUES(1);
|
||||
}
|
||||
} {0 {2 3 3 3 3 5}}
|
||||
} {1 2 1 4}
|
||||
|
||||
# Six columns of configuration data as follows:
|
||||
#
|
||||
# i The reference number of the test
|
||||
# conf1 The conflict resolution algorithm on the UNIQUE constraint
|
||||
# conf2 The conflict resolution algorithm on the BEGIN statement
|
||||
# cmd An UPDATE command to execute against table t1
|
||||
# t0 True if there is an error from $cmd
|
||||
# t1 Content of "b" column of t1 assuming no error in $cmd
|
||||
# t2 Content of "x" column of t3
|
||||
#
|
||||
foreach {i conf1 conf2 cmd t0 t1 t2} {
|
||||
1 {} {} UPDATE 1 {6 7 8 9} 1
|
||||
2 REPLACE {} UPDATE 0 {7 6 9} 1
|
||||
3 IGNORE {} UPDATE 0 {6 7 3 9} 1
|
||||
4 FAIL {} UPDATE 1 {6 7 3 4} 1
|
||||
5 ABORT {} UPDATE 1 {1 2 3 4} 1
|
||||
6 ROLLBACK {} UPDATE 1 {1 2 3 4} 0
|
||||
7 REPLACE {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
|
||||
8 IGNORE {} {UPDATE OR REPLACE} 0 {7 6 9} 1
|
||||
9 FAIL {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
|
||||
10 ABORT {} {UPDATE OR REPLACE} 0 {7 6 9} 1
|
||||
11 ROLLBACK {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
|
||||
12 {} {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1
|
||||
13 {} {} {UPDATE OR REPLACE} 0 {7 6 9} 1
|
||||
14 {} {} {UPDATE OR FAIL} 1 {6 7 3 4} 1
|
||||
15 {} {} {UPDATE OR ABORT} 1 {1 2 3 4} 1
|
||||
16 {} {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0
|
||||
17 {} IGNORE UPDATE 0 {6 7 3 9} 1
|
||||
18 {} REPLACE UPDATE 0 {7 6 9} 1
|
||||
19 {} FAIL UPDATE 1 {6 7 3 4} 1
|
||||
20 {} ABORT UPDATE 1 {1 2 3 4} 1
|
||||
21 {} ROLLBACK UPDATE 1 {1 2 3 4} 0
|
||||
22 REPLACE FAIL UPDATE 0 {7 6 9} 1
|
||||
23 IGNORE ROLLBACK UPDATE 0 {6 7 3 9} 1
|
||||
} {
|
||||
if {$t0} {set t1 {constraint failed}}
|
||||
do_test conflict-6.$i {
|
||||
if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
|
||||
if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
|
||||
set r0 [catch {execsql [subst {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
|
||||
INSERT INTO t1 SELECT * FROM t2;
|
||||
UPDATE t3 SET x=0;
|
||||
BEGIN $conf2;
|
||||
$cmd t3 SET x=1;
|
||||
$cmd t1 SET a=c+5;
|
||||
}]} r1]
|
||||
execsql {COMMIT}
|
||||
if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
|
||||
set r2 [execsql {SELECT x FROM t3}]
|
||||
list $r0 $r1 $r2
|
||||
} [list $t0 $t1 $t2]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
208
www/conflict.tcl
208
www/conflict.tcl
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the constraint.html file.
|
||||
#
|
||||
set rcsid {$Id: conflict.tcl,v 1.1 2002/01/30 16:17:25 drh Exp $ }
|
||||
set rcsid {$Id: conflict.tcl,v 1.2 2002/02/03 00:56:11 drh Exp $ }
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@@ -22,7 +22,8 @@ puts {
|
||||
In most SQL databases, if you have a UNIQUE constraint on
|
||||
a table and you try to do an UPDATE or INSERT that violates
|
||||
that constraint, the database will aborts the operation in
|
||||
progress and rolls back the current transaction.
|
||||
progress, back out any prior changes associated with that
|
||||
one UPDATE or INSERT command, and return an error.
|
||||
This is the default behavior of SQLite.
|
||||
Beginning with version 2.3.0, though, SQLite allows you to
|
||||
define alternative ways for dealing with constraint violations.
|
||||
@@ -32,154 +33,71 @@ This article describes those alternatives and how to use them.
|
||||
<h2>Conflict Resolution Algorithms</h2>
|
||||
|
||||
<p>
|
||||
The default conflict resolution algorithm is to abort the
|
||||
operation in progress, rollback all changes, and cancel the
|
||||
current transaction. Call this algorithm "ABORT". Abort
|
||||
is the standard way of dealing with a constraint error
|
||||
in most SQL databases.
|
||||
SQLite defines five constraint conflict resolution algorithms
|
||||
as follows:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sometimes ABORT is not the most helpful way of dealing
|
||||
with constraint violations. Suppose, for example, you are
|
||||
<dl>
|
||||
<dt><b>ROLLBACK</b></dt>
|
||||
<dd><p>When a constraint violation occurs, an immediate ROLLBACK
|
||||
occurs, thus ending the current transaction, and the command aborts
|
||||
with a return code of SQLITE_CONSTRAINT. If no transaction is
|
||||
active (other than the implied transaction that is created on every
|
||||
command) then this algorithm works the same as ABORT.</p></dd>
|
||||
|
||||
<dt><b>ABORT</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the command backs out
|
||||
any prior changes it might have made and aborts with a return code
|
||||
of SQLITE_CONSTRAINT. But no ROLLBACK is executed so changes
|
||||
from prior commands within the same transaction
|
||||
are preserved. This is the default behavior for SQLite.</p></dd>
|
||||
|
||||
<dt><b>FAIL</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the command aborts with a
|
||||
return code SQLITE_CONSTRAINT. But any changes to the database that
|
||||
the command made prior to encountering the constraint violation
|
||||
are preserved and are not backed out. For example, if an UPDATE
|
||||
statement encountered a constraint violation on the 100th row that
|
||||
it attempts to update, then the first 99 row changes are preserved
|
||||
by change to rows 100 and beyond never occur.</p></dd>
|
||||
|
||||
<dt><b>IGNORE</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the one row that contains
|
||||
the constraint violation is not inserted or changed. But the command
|
||||
continues executing normally. Other rows before and after the row that
|
||||
contained the constraint violation continue to be inserted or updated
|
||||
normally. No error is returned.</p></dd>
|
||||
|
||||
<dt><b>REPLACE</b></dt>
|
||||
<dd><p>When a UNIQUE constraint violation occurs, the pre-existing row
|
||||
that caused the constraint violation is removed prior to inserting
|
||||
or updating the current row. Thus the insert or update always occurs.
|
||||
The command continues executing normally. No error is returned.</p></dd>
|
||||
</dl>
|
||||
|
||||
<h2>Why So Many Choices?</h2>
|
||||
|
||||
<p>SQLite provides multiple conflict resolution algorithms for a
|
||||
couple of reasons. First, SQLite tries to be roughly compatible with as
|
||||
many other SQL databases as possible, but different SQL database
|
||||
engines exhibit different conflict resolution strategies. For
|
||||
example, PostgreSQL always uses ROLLBACK, Oracle always uses ABORT, and
|
||||
MySQL usually uses FAIL but can be instructed to use IGNORE or REPLACE.
|
||||
By supporting all five alternatives, SQLite provides maximum
|
||||
portability.</p>
|
||||
|
||||
<p>Another reason for supporing multiple algorithms is that sometimes
|
||||
it is useful to use an algorithm other than the default.
|
||||
Suppose, for example, you are
|
||||
inserting 1000 records into a database, all within a single
|
||||
transaction, but one of those records is malformed and causes
|
||||
a constraint error. With the default ABORT behavior, none
|
||||
of the 1000 records gets inserted. But sometimes it is
|
||||
desirable to just omit the single malformed insert and
|
||||
finish the other 999.
|
||||
</p>
|
||||
a constraint error. Under PostgreSQL or Oracle, none of the
|
||||
1000 records would get inserted. In MySQL, some subset of the
|
||||
records that appeared before the malformed record would be inserted
|
||||
but the rest would not. Neither behavior is espeically helpful.
|
||||
What you really want is to use the IGNORE algorithm to insert
|
||||
all but the malformed record.</p>
|
||||
|
||||
<p>
|
||||
SQLite defines two addition conflict resolution algorithms
|
||||
called "IGNORE" and "REPLACE".
|
||||
If you are trying to do multiple INSERTs or UPDATEs when a constraint
|
||||
fails for a single row and the conflict behavior is IGNORE, then
|
||||
that row remains uninserted or unmodified. But the overall operation
|
||||
is not aborted and no rollback occurs. If a constraint
|
||||
fails and the behavior is REPLACE, then SQLite tries to
|
||||
delete other rows in the table in order to eliminate the
|
||||
constraint problem. Again, the overall operation continues
|
||||
and no rollback occurs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The default conflict resolution algorithm is always ABORT
|
||||
but you can specify an alternative algorithm using special
|
||||
(non-standard) syntax on the INSERT and UPDATE commands.
|
||||
You can add the clause "ON CONFLICT <algorithm>" immediately
|
||||
after the "INSERT" or "UPDATE" keywords to specify the
|
||||
conflict resolution algorithm to use for that one operation.
|
||||
(Substitute "ABORT", "IGNORE", or "REPLACE" for <algorithm>,
|
||||
of course.)
|
||||
</p>
|
||||
|
||||
Consider this example:
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
CREATE TABLE t1(
|
||||
a INTEGER,
|
||||
b INTEGER,
|
||||
c INTEGER,
|
||||
UNIQUE(a,b)
|
||||
);
|
||||
INSERT INTO a VALUES(1,2,3);
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO a VALUES(2,3,4);
|
||||
INSERT INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In the last instruction, the UNIQUE constraint fails
|
||||
and the entire transaction is rolled back. The database
|
||||
now contains a single entry: {1,2,3}.
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(2,3,4);
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(1,2,5);
|
||||
COMMIT;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>This time the "ON CONFLICT IGNORE" clause tells SQLite to use
|
||||
IGNORE semantics when a constraint fails. The second
|
||||
INSERT statement fails, but the database is
|
||||
not rolled back and there is no failure. The database
|
||||
now contains two rows: {1,2,3} and {2,3,4}.</p>
|
||||
|
||||
<blockquote><pre>
|
||||
BEGIN;
|
||||
INSERT ON CONFLICT REPLACE INTO a VALUES(1,2,5);
|
||||
COMMIT;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Here the "ON CONFLICT REPLACE" clause tells SQLite to use REPLACE
|
||||
semantics. The {1,2,3} is deleted when the {1,2,5} row
|
||||
is inserted in order to satisfy the constraint. After
|
||||
the above, the database contains {1,2,5} and {2,3,4}.</p>
|
||||
|
||||
<h2>A Syntactic Shortcut</h2>
|
||||
|
||||
<p>On an INSERT, the "ON CONFLICT" keywords may be omitted for brevity.
|
||||
So you can say</p>
|
||||
|
||||
<blockquote><pre>
|
||||
INSERT IGNORE INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Instead of the more wordy:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
INSERT ON CONFLICT IGNORE INTO a VALUES(1,2,5);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Unfortunately, you cannot do this with an UPDATE.</p>
|
||||
|
||||
<h2>Changing The Default Conflict Resolution Algorithm</h2>
|
||||
|
||||
<p>You can change the default conflict resolution algorithm
|
||||
on a constraint-by-constraint basis using special (non-standard)
|
||||
syntax in CREATE TABLE and CREATE INDEX statements. The
|
||||
same "ON CONFLICT" clause that appears in INSERT and UPDATE
|
||||
statements is used but the clause is attached to the constraint
|
||||
in the CREATE TABLE statement. Like this:
|
||||
|
||||
<blockquote><pre>
|
||||
CREATE TABLE t1 (
|
||||
a INTEGER,
|
||||
b INTEGER,
|
||||
c INTEGER,
|
||||
UNIQUE(a,b) ON CONFLICT REPLACE
|
||||
);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The ON CONFLICT clause in the above table definition says that
|
||||
the default conflict resolution algorithm is REPLACE instead
|
||||
of ABORT. REPLACE will always be used unless you override
|
||||
this by saying "INSERT IGNORE" or "INSERT ABORT".</p>
|
||||
|
||||
<p>The ON CONFLICT clause can also appear on a NOT NULL constraint,
|
||||
a PRIMARY KEY constraint, and a CHECK constraint.
|
||||
(Note, however, that CHECK constraints are not currently enforced
|
||||
so the ON CONFLICT clause has no effect there.)</p>
|
||||
|
||||
<p>A NOT NULL constraint will normally ABORT if you try to insert
|
||||
a NULL. But if you substitute the REPLACE algorithm, it tries to insert
|
||||
the default value in place of the NULL. If there is no default value,
|
||||
then REPLACE is the same as ABORT for NOT NULL constraints.
|
||||
With the IGNORE algorithm on a NOT NULL, the INSERT or UPDATE
|
||||
is suppressed if the value is NULL.</p>
|
||||
|
||||
<h2>Portability</h2>
|
||||
|
||||
<p>The ON CONFLICT syntax is not standard SQL and will not
|
||||
(as far as is known) work on any other database product. Furthermore,
|
||||
the syntax might change in future versions of SQLite. So use it
|
||||
with appropriate discretion.</p>
|
||||
}
|
||||
|
||||
puts {
|
||||
|
356
www/lang.tcl
356
www/lang.tcl
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the sqlite.html file.
|
||||
#
|
||||
set rcsid {$Id: lang.tcl,v 1.20 2002/01/31 15:54:23 drh Exp $}
|
||||
set rcsid {$Id: lang.tcl,v 1.21 2002/02/03 00:56:11 drh Exp $}
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@@ -42,6 +42,7 @@ foreach {section} [lsort -index 0 -dictionary {
|
||||
{{DROP TABLE} droptable}
|
||||
{{DROP INDEX} dropindex}
|
||||
{INSERT insert}
|
||||
{REPLACE replace}
|
||||
{DELETE delete}
|
||||
{UPDATE update}
|
||||
{SELECT select}
|
||||
@@ -61,7 +62,7 @@ the sequel.</p>
|
||||
}
|
||||
|
||||
proc Syntax {args} {
|
||||
puts {<table cellpadding="15">}
|
||||
puts {<table cellpadding="10">}
|
||||
foreach {rule body} $args {
|
||||
puts "<tr><td align=\"right\" valign=\"top\">"
|
||||
puts "<i><font color=\"#ff3434\">$rule</font></i> ::=</td>"
|
||||
@@ -105,7 +106,7 @@ proc Example {text} {
|
||||
Section {BEGIN TRANSACTION} createindex
|
||||
|
||||
Syntax {sql-statement} {
|
||||
BEGIN [TRANSACTION [<name>]]
|
||||
BEGIN [TRANSACTION [<name>]] [ON CONFLICT <conflict-algorithm>]
|
||||
}
|
||||
Syntax {sql-statement} {
|
||||
END [TRANSACTION [<name>]]
|
||||
@@ -119,9 +120,7 @@ ROLLBACK [TRANSACTION [<name>]]
|
||||
|
||||
puts {
|
||||
<p>Beginning in version 2.0, SQLite supports transactions with
|
||||
rollback and atomic commit. However, only a single level of
|
||||
transaction is allowed. Transactions may not be nested.
|
||||
</p>
|
||||
rollback and atomic commit.</p>
|
||||
|
||||
<p>
|
||||
No changes can be made to the database except within a transaction.
|
||||
@@ -132,52 +131,32 @@ are committed at the conclusion of the command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Transactions can be started manually using the BEGIN TRANSACTION
|
||||
command. Such transactions persist until a COMMIT or ROLLBACK
|
||||
or until an error occurs or the database is closed. If an
|
||||
error is encountered or the database is closed, the transaction
|
||||
is automatically rolled back. The END TRANSACTION command is
|
||||
a alias for COMMIT.
|
||||
Transactions can be started manually using the BEGIN
|
||||
command. Such transactions usually persist until the next
|
||||
COMMIT or ROLLBACK command. But a transaction will also
|
||||
ROLLBACK if the database is closed or if an error occurs
|
||||
and the ROLLBACK conflict resolution algorithm is specified.
|
||||
See the documention on the <a href="#conflict">ON CONFLICT</a>
|
||||
clause for additional information about the ROLLBACK
|
||||
conflict resolution algorithm.
|
||||
</p>
|
||||
}
|
||||
|
||||
Section {ON CONFLICT clause} conflict
|
||||
|
||||
Syntax {conflict-clause} {
|
||||
ON CONFLICT <algorithm>
|
||||
} {algorithm} {
|
||||
ABORT | IGNORE | REPLACE
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The ON CONFLICT clause is not a separate SQL command. It is a
|
||||
non-standard clause that can appear in many other SQL commands.
|
||||
It is given its own section in this document because it is not
|
||||
part of standard SQL and therefore might not be familiar.</p>
|
||||
|
||||
<p>The ON CONFLICT clause specifies an algorithm used to resolve
|
||||
constraint conflicts. The default algorithm is ABORT. When the
|
||||
ABORT algorithm is in use, any constraint violation causes the
|
||||
command to abort and the current transaction to be rolled back.
|
||||
This is the only behavior exhibited by most SQL engines. But
|
||||
SQLite allows two alternative behaviors: IGNORE and REPLACE.
|
||||
The IGNORE algorithm means that when a constraint violation occurs
|
||||
on a COPY, INSERT or UPDATE, the particular row that caused the constraint
|
||||
violation is not inserted or changed, but other rows effected by the
|
||||
COPY, INSERT, or UPDATE are insert or changed as usual.
|
||||
The command is not aborted and no rollback occurs.
|
||||
If the algorithm is REPLACE, then SQLite tries to
|
||||
delete preexisting rows from the table to remove the constraint
|
||||
violation before inserting or changing the row.</p>
|
||||
|
||||
<p>For additional information, see
|
||||
<a href="conflict.html">conflict.html</a>.</p>
|
||||
<p>
|
||||
The optional ON CONFLICT clause at the end of a BEGIN statement
|
||||
can be used to changed the default conflict resolution algorithm.
|
||||
The normal default is ABORT. If an alternative is specified by
|
||||
the ON CONFLICT clause of a BEGIN, then that alternative is used
|
||||
as the default for all commands within the transaction. The default
|
||||
algorithm is overridden by ON CONFLICT clauses on individual
|
||||
constraints within the CREATE TABLE or CREATE INDEX statements
|
||||
and by the OR clauses on COPY, INSERT, and UPDATE commands.
|
||||
</p>
|
||||
}
|
||||
|
||||
Section COPY copy
|
||||
|
||||
Syntax {sql-statement} {
|
||||
COPY [ <conflict-clause> ] <table-name> FROM <filename>
|
||||
COPY [ OR <conflict-algorithm> ] <table-name> FROM <filename>
|
||||
[ USING DELIMITERS <delim> ]
|
||||
}
|
||||
|
||||
@@ -219,7 +198,7 @@ Section {CREATE INDEX} createindex
|
||||
Syntax {sql-statement} {
|
||||
CREATE [UNIQUE] INDEX <index-name>
|
||||
ON <table-name> ( <column-name> [, <column-name>]* )
|
||||
[ <conflict-clause> ]
|
||||
[ ON CONFLICT <conflict-algorithm> ]
|
||||
} {column-name} {
|
||||
<name> [ ASC | DESC ]
|
||||
}
|
||||
@@ -282,6 +261,8 @@ DEFAULT <value>
|
||||
PRIMARY KEY ( <name> [, <name>]* ) [ <conflict-clause> ]|
|
||||
UNIQUE ( <name> [, <name>]* ) [ <conflict-clause> ] |
|
||||
CHECK ( <expr> ) [ <conflict-clause> ]
|
||||
} {conflict-clause} {
|
||||
ON CONFLICT <conflict-algorithm>
|
||||
}
|
||||
|
||||
puts {
|
||||
@@ -563,8 +544,8 @@ The "<b>count(*)</b>" syntax is supported but
|
||||
Section INSERT insert
|
||||
|
||||
Syntax {sql-statement} {
|
||||
INSERT [ <conflict-clause> ] INTO <table-name> [( <column-list> )] VALUES ( <value-list> ) |
|
||||
INSERT [ <conflict-clause> ] INTO <table-name> [( <column-list> )] <select-statement>
|
||||
INSERT [OR <conflict-algorithm>] INTO <table-name> [(<column-list>)] VALUES(<value-list>) |
|
||||
INSERT [OR <conflict-algorithm>] INTO <table-name> [(<column-list>)] <select-statement>
|
||||
}
|
||||
|
||||
puts {
|
||||
@@ -590,7 +571,199 @@ the ORDER BY is ignored.</p>
|
||||
<p>The optional conflict-clause allows the specification of an alternative
|
||||
constraint conflict resolution algorithm to use during this one command.
|
||||
See the section titled
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
|
||||
<a href="#conflict">ON CONFLICT</a> for additional information.
|
||||
For compatibility with MySQL, the parser allows the use of the
|
||||
single keyword "REPLACE" as an alias for "INSERT OR REPLACE".
|
||||
</p>
|
||||
}
|
||||
|
||||
Section {ON CONFLICT clause} conflict
|
||||
|
||||
Syntax {conflict-clause} {
|
||||
ON CONFLICT <conflict-algorithm>
|
||||
} {conflict-algorithm} {
|
||||
ROLLBACK | ABORT | FAIL | IGNORE | REPLACE
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The ON CONFLICT clause is not a separate SQL command. It is a
|
||||
non-standard clause that can appear in many other SQL commands.
|
||||
It is given its own section in this document because it is not
|
||||
part of standard SQL and therefore might not be familiar.</p>
|
||||
|
||||
<p>The syntax for the ON CONFLICT clause is as shown above for
|
||||
the CREATE TABLE, CREATE INDEX, and BEGIN TRANSACTION commands.
|
||||
For the COPY, INSERT, and UPDATE commands, the keywords
|
||||
"ON CONFLICT" are replaced by "OR", to make the syntax seem more
|
||||
natural. But the meaning of the clause is the same either way.</p>
|
||||
|
||||
<p>The ON CONFLICT clause specifies an algorithm used to resolve
|
||||
constraint conflicts. There are five choices: ROLLBACK, ABORT,
|
||||
FAIL, IGNORE, and REPLACE. The default algorithm is ABORT. This
|
||||
is what they mean:</p>
|
||||
|
||||
<dl>
|
||||
<dt><b>ROLLBACK</b></dt>
|
||||
<dd><p>When a constraint violation occurs, an immediate ROLLBACK
|
||||
occurs, thus ending the current transaction, and the command aborts
|
||||
with a return code of SQLITE_CONSTRAINT. If no transaction is
|
||||
active (other than the implied transaction that is created on every
|
||||
command) then this algorithm works the same as ABORT.</p></dd>
|
||||
|
||||
<dt><b>ABORT</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the command backs out
|
||||
any prior changes it might have made and aborts with a return code
|
||||
of SQLITE_CONSTRAINT. But no ROLLBACK is executed so changes
|
||||
from prior commands within the same transaction
|
||||
are preserved. This is the default behavior.</p></dd>
|
||||
|
||||
<dt><b>FAIL</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the command aborts with a
|
||||
return code SQLITE_CONSTRAINT. But any changes to the database that
|
||||
the command made prior to encountering the constraint violation
|
||||
are preserved and are not backed out. For example, if an UPDATE
|
||||
statement encountered a constraint violation on the 100th row that
|
||||
it attempts to update, then the first 99 row changes are preserved
|
||||
by change to rows 100 and beyond never occur.</p></dd>
|
||||
|
||||
<dt><b>IGNORE</b></dt>
|
||||
<dd><p>When a constraint violation occurs, the one row that contains
|
||||
the constraint violation is not inserted or changed. But the command
|
||||
continues executing normally. Other rows before and after the row that
|
||||
contained the constraint violation continue to be inserted or updated
|
||||
normally. No error is returned.</p></dd>
|
||||
|
||||
<dt><b>REPLACE</b></dt>
|
||||
<dd><p>When a UNIQUE constraint violation occurs, the pre-existing row
|
||||
that is causing the constraint violation is removed prior to inserting
|
||||
or updating the current row. Thus the insert or update always occurs.
|
||||
The command continues executing normally. No error is returned.</p></dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
The conflict resolution algorithm can be specified in three places,
|
||||
in order from lowest to highest precedence:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li><p>
|
||||
On a BEGIN TRANSACTION command.
|
||||
</p></li>
|
||||
|
||||
<li><p>
|
||||
On individual constraints within a CREATE TABLE or CREATE INDEX
|
||||
statement.
|
||||
</p></li>
|
||||
|
||||
<li><p>
|
||||
In the OR clause of a COPY, INSERT, or UPDATE command.
|
||||
</p></li>
|
||||
</ol>
|
||||
|
||||
<p>The algorithm specified in the OR clause of a COPY, INSERT, or UPDATE
|
||||
overrides any algorithm specified by a CREATE TABLE or CREATE INDEX.
|
||||
The algorithm specified within a CREATE TABLE or CREATE INDEX will, in turn,
|
||||
override the algorithm specified by a BEGIN TRANSACTION command.
|
||||
If no algorithm is specified anywhere, the ABORT algorithm is used.</p>
|
||||
|
||||
}
|
||||
# <p>For additional information, see
|
||||
# <a href="conflict.html">conflict.html</a>.</p>
|
||||
|
||||
|
||||
Section PRAGMA pragma
|
||||
|
||||
Syntax {sql-statement} {
|
||||
PRAGMA <name> = <value> |
|
||||
PRAGMA <function>(<arg>)
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The PRAGMA command is used to modify the operation of the SQLite library.
|
||||
The pragma command is experimental and specific pragma statements may
|
||||
removed or added in future releases of SQLite. Use this command
|
||||
with caution.</p>
|
||||
|
||||
<p>The current implementation supports the following pragmas:</p>
|
||||
|
||||
<ul>
|
||||
<li><p><b>PRAGMA cache_size = </b><i>Number-of-pages</i><b>;</b></p>
|
||||
<p>Change the maximum number of database disk pages that SQLite
|
||||
will hold in memory at once. Each page uses about 1.5K of RAM.
|
||||
The default cache size is 100. If you are doing UPDATEs or DELETEs
|
||||
that change many rows of a database and you do not mind if SQLite
|
||||
uses more memory, you can increase the cache size for a possible speed
|
||||
improvement.</p></li>
|
||||
|
||||
<li><p><b>PRAGMA count_changes = ON;
|
||||
<br>PRAGMA count_changes = OFF;</b></p>
|
||||
<p>When on, the COUNT_CHANGES pragma causes the callback function to
|
||||
be invoked once for each DELETE, INSERT, or UPDATE operation. The
|
||||
argument is the number of rows that were changed.</p>
|
||||
|
||||
<li><p><b>PRAGMA empty_result_callbacks = ON;
|
||||
<br>PRAGMA empty_result_callbacks = OFF;</b></p>
|
||||
<p>When on, the EMPTY_RESULT_CALLBACKS pragma causes the callback
|
||||
function to be invoked once for each query that has an empty result
|
||||
set. The third "<b>argv</b>" parameter to the callback is set to NULL
|
||||
because there is no data to report. But the second "<b>argc</b>" and
|
||||
fourth "<b>columnNames</b>" parameters are valid and can be used to
|
||||
determine the number and names of the columns that would have been in
|
||||
the result set had the set not been empty.</p>
|
||||
|
||||
<li><p><b>PRAGMA full_column_names = ON;
|
||||
<br>PRAGMA full_column_names = OFF;</b></p>
|
||||
<p>The column names reported in an SQLite callback are normally just
|
||||
the name of the column itself, except for joins when "TABLE.COLUMN"
|
||||
is used. But when full_column_names is turned on, column names are
|
||||
always reported as "TABLE.COLUMN" even for simple queries.</p></li>
|
||||
|
||||
<li><p><b>PRAGMA index_info(</b><i>index-name</i><b>);</b></p>
|
||||
<p>For each column that the named index references, invoke the
|
||||
callback function
|
||||
once with information about that column, including the column name,
|
||||
and the column number.</p>
|
||||
|
||||
<li><p><b>PRAGMA index_list(</b><i>table-name</i><b>);</b></p>
|
||||
<p>For each index on the named table, invoke the callback function
|
||||
once with information about that index. Arguments include the
|
||||
index name and a flag to indicate whether or not the index must be
|
||||
unique.</p>
|
||||
|
||||
<li><p><b>PRAGMA parser_trace = ON;<br>PRAGMA parser_trace = OFF;</b></p>
|
||||
<p>Turn tracing of the SQL parser inside of the
|
||||
SQLite library on and off. This is used for debugging.
|
||||
This only works if the library is compiled without the NDEBUG macro.
|
||||
</p></li>
|
||||
|
||||
<li><p><b>PRAGMA table_info(</b><i>table-name</i><b>);</b></p>
|
||||
<p>For each column in the named table, invoke the callback function
|
||||
once with information about that column, including the column name,
|
||||
data type, whether or not the column can be NULL, and the default
|
||||
value for the column.</p>
|
||||
|
||||
<li><p><b>PRAGMA vdbe_trace = ON;<br>PRAGMA vdbe_trace = OFF;</b></p>
|
||||
<p>Turn tracing of the virtual database engine inside of the
|
||||
SQLite library on and off. This is used for debugging.</p></li>
|
||||
</ul>
|
||||
|
||||
<p>No error message is generated if an unknown pragma is issued.
|
||||
Unknown pragmas are ignored.</p>
|
||||
}
|
||||
|
||||
Section REPLACE replace
|
||||
|
||||
Syntax {sql-statement} {
|
||||
REPLACE INTO <table-name> [( <column-list> )] VALUES ( <value-list> ) |
|
||||
REPLACE INTO <table-name> [( <column-list> )] <select-statement>
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The REPLACE command is an alias for the "INSERT OR REPLACE" variant
|
||||
of the <a href="#insert">INSERT command</a>. This alias is provided for
|
||||
compatibility with MySQL. See the
|
||||
<a href="#insert">INSERT command</a> documentation for additional
|
||||
information.</p>
|
||||
}
|
||||
|
||||
Section SELECT select
|
||||
@@ -675,7 +848,7 @@ are connected into a compound, they group from left to right.</p>
|
||||
Section UPDATE update
|
||||
|
||||
Syntax {sql-statement} {
|
||||
UPDATE [ <conflict-clause> ] <table-name>
|
||||
UPDATE [ OR <conflict-algorithm> ] <table-name>
|
||||
SET <assignment> [, <assignment>]
|
||||
[WHERE <expression>]
|
||||
} {assignment} {
|
||||
@@ -713,89 +886,6 @@ the database backend and VACUUM has become a no-op.
|
||||
</p>
|
||||
}
|
||||
|
||||
Section PRAGMA pragma
|
||||
|
||||
Syntax {sql-statement} {
|
||||
PRAGMA <name> = <value> |
|
||||
PRAGMA <function>(<arg>)
|
||||
}
|
||||
|
||||
puts {
|
||||
<p>The PRAGMA command is used to modify the operation of the SQLite library.
|
||||
The pragma command is experimental and specific pragma statements may
|
||||
removed or added in future releases of SQLite. Use this command
|
||||
with caution.</p>
|
||||
|
||||
<p>The current implementation supports the following pragmas:</p>
|
||||
|
||||
<ul>
|
||||
<li><p><b>PRAGMA cache_size = </b><i>Number-of-pages</i><b>;</b></p>
|
||||
<p>Change the maximum number of database disk pages that SQLite
|
||||
will hold in memory at once. Each page uses about 1.5K of RAM.
|
||||
The default cache size is 100. If you are doing UPDATEs or DELETEs
|
||||
that change many rows of a database and you do not mind if SQLite
|
||||
uses more memory, you can increase the cache size for a possible speed
|
||||
improvement.</p></li>
|
||||
|
||||
<li><p><b>PRAGMA count_changes = ON;
|
||||
<br>PRAGMA count_changes = OFF;</b></p>
|
||||
<p>When on, the COUNT_CHANGES pragma causes the callback function to
|
||||
be invoked once for each DELETE, INSERT, or UPDATE operation. The
|
||||
argument is the number of rows that were changed.</p>
|
||||
|
||||
<li><p><b>PRAGMA empty_result_callbacks = ON;
|
||||
<br>PRAGMA empty_result_callbacks = OFF;</b></p>
|
||||
<p>When on, the EMPTY_RESULT_CALLBACKS pragma causes the callback
|
||||
function to be invoked once for each query that has an empty result
|
||||
set. The third "<b>argv</b>" parameter to the callback is set to NULL
|
||||
because there is no data to report. But the second "<b>argc</b>" and
|
||||
fourth "<b>columnNames</b>" parameters are valid and can be used to
|
||||
determine the number and names of the columns that would have been in
|
||||
the result set had the set not been empty.</p>
|
||||
|
||||
<li><p><b>PRAGMA full_column_names = ON;
|
||||
<br>PRAGMA full_column_names = OFF;</b></p>
|
||||
<p>The column names reported in an SQLite callback are normally just
|
||||
the name of the column itself, except for joins when "TABLE.COLUMN"
|
||||
is used. But when full_column_names is turned on, column names are
|
||||
always reported as "TABLE.COLUMN" even for simple queries.</p></li>
|
||||
|
||||
<li><p><b>PRAGMA index_info(</b><i>index-name</i><b>);</b></p>
|
||||
<p>For each column that the named index references, invoke the
|
||||
callback function
|
||||
once with information about that column, including the column name,
|
||||
and the column number.</p>
|
||||
|
||||
<li><p><b>PRAGMA index_list(</b><i>table-name</i><b>);</b></p>
|
||||
<p>For each index on the named table, invoke the callback function
|
||||
once with information about that index. Arguments include the
|
||||
index name and a flag to indicate whether or not the index must be
|
||||
unique.</p>
|
||||
|
||||
<li><p><b>PRAGMA parser_trace = ON;<br>PRAGMA parser_trace = OFF;</b></p>
|
||||
<p>Turn tracing of the SQL parser inside of the
|
||||
SQLite library on and off. This is used for debugging.
|
||||
This only works if the library is compiled without the NDEBUG macro.
|
||||
</p></li>
|
||||
|
||||
<li><p><b>PRAGMA table_info(</b><i>table-name</i><b>);</b></p>
|
||||
<p>For each column in the named table, invoke the callback function
|
||||
once with information about that column, including the column name,
|
||||
data type, whether or not the column can be NULL, and the default
|
||||
value for the column.</p>
|
||||
|
||||
<li><p><b>PRAGMA vdbe_trace = ON;<br>PRAGMA vdbe_trace = OFF;</b></p>
|
||||
<p>Turn tracing of the virtual database engine inside of the
|
||||
SQLite library on and off. This is used for debugging.</p></li>
|
||||
</ul>
|
||||
|
||||
<p>No error message is generated if an unknown pragma is issued.
|
||||
Unknown pragmas are ignored.</p>
|
||||
}
|
||||
|
||||
puts {
|
||||
<p></p>
|
||||
}
|
||||
|
||||
puts {
|
||||
<p><hr /></p>
|
||||
|
Reference in New Issue
Block a user