1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Change to five conflict resolution algorithms: ROLLBACK, ABORT, FAIL,

IGNORE, and REPLACE.  This checkin is code only.  Documentation and
tests are still needed.  Also, ABORT is not fully implemented. (CVS 360)

FossilOrigin-Name: d0e7cf4a83e6abad7129bed356b7492dddaff474
This commit is contained in:
drh
2002-01-31 15:54:21 +00:00
parent b419a926d4
commit 1c92853dac
17 changed files with 331 additions and 239 deletions

View File

@ -1,5 +1,5 @@
C Added\sON\sCONFLICT\ssupport\sto\sCOPY.\sUpdates\sto\sdocumentation.\sBug\sfixes.\s(CVS\s359)
D 2002-01-30T16:17:24
C Change\sto\sfive\sconflict\sresolution\salgorithms:\sROLLBACK,\sABORT,\sFAIL,\nIGNORE,\sand\sREPLACE.\s\sThis\scheckin\sis\scode\sonly.\s\sDocumentation\sand\ntests\sare\sstill\sneeded.\s\sAlso,\sABORT\sis\snot\sfully\simplemented.\s(CVS\s360)
D 2002-01-31T15:54:21
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@ -16,40 +16,40 @@ F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6
F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
F publish.sh 523db0d8a451df7a8300e193afaa4ac44e41f98c
F publish.sh 60adffbe50226a1d7d1a2930e8b7eb31535c4fe4
F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c c796e387da340cb628dc1e41f684fc20253f561e
F src/btree.h 9ead7f54c270d8a554e59352ca7318fdaf411390
F src/build.c 78571589a39d4b03b19b1300db8b23f1d3e1bab2
F src/delete.c 4cdb6d2e94e2eb1b1aa79eefafd4669d43c249d6
F src/build.c f725dc396d784f723950cf3d47a10f1a69b2f7b7
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
F src/expr.c a2a87dbd411a508ff89dffa90505ad42dac2f920
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
F src/insert.c 37971598f1cbfc9de9bd1d269529e233003652b8
F src/main.c 0205771a6c31a9858ff131fc1e797b589afb76bf
F src/insert.c 42e89cb227ce744802622886db3572f78e72093f
F src/main.c 637582b8b80a85b0308ca5bab8f2b42ebb002af8
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c c615faa4d23e742e0650e0751a6ad2a18438ad53
F src/os.h 5405a5695bf16889d4fc6caf9d42043caa41c269
F src/pager.c 1e80a3ba731e454df6bd2e58d32eeba7dd65121b
F src/pager.h f78d064c780855ff70beacbeba0e2324471b26fe
F src/parse.y e80f1cf6a280e3da0f49c9b60b14edc2f15912ec
F src/parse.y 90e9fc913c60b26217f4210d48a4c5c4e78f16f2
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
F src/random.c f6b36bec5ebd3edb3440224bf5bf811fe4ac9a1b
F src/select.c fc11d5a8c2bae1b62d8028ffb111c773ad6bf161
F src/shell.c c102dfe388c7618a668c944ff157c49cb48f28e3
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
F src/sqliteInt.h 3bf0938d01e1cc57154c39c730d7e91d9bd60359
F src/sqliteInt.h 70fd20107f4953312e76a9630a704c9405161040
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
F src/tokenize.c 1199b96a82d5c41509b5e24fc9faa1852b7f3135
F src/update.c c6215079d7604fd1cf785eff64ec0e03e97bd138
F src/tokenize.c 01a09db6adf933e941db1b781789a0c175be6504
F src/update.c 3fb7c1601bbd379e39881d6b731d3223b822188a
F src/util.c 8f8973dd55a6ec63be9632fc5de86965c99d6327
F src/vdbe.c 14667d889d9d9ebdc5f5f5d030312071f41b7873
F src/vdbe.c 8e6f1bfff67639b7c3bd07822595fc2ef19f0f34
F src/vdbe.h 5b1bd518126fc5a30e6ea13fe11de931b32c4b59
F src/where.c 2dda39367f193194e4c7d2e0dcab31527d9d8aba
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
@ -57,8 +57,8 @@ F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/btree.test 6ab4dc5f595905a276ef588fad3c9236dc07a47b
F test/btree2.test 08e9485619265cbaf5d11bd71f357cdc26bb87e0
F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895
F test/conflict.test 685725a37ec13e671ec57f48285c1c08bba21c99
F test/copy.test 4079990fb84be696d29c43de9fa6492312f165f0
F test/conflict.test 70d40d77bb83f326574488d3cde1d0f3c51a0949
F test/copy.test 9ff0063c0b95b3d51b8d0c7fe0ff51dabaa66549
F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
F test/expr.test c8a495050dcec3f9e68538c3ef466726933302c1
F test/func.test 51dbe3f8a4c28972751697423e6acc5d6b551df1
@ -73,7 +73,7 @@ F test/lock.test 19593689260c419efe7ced55b1418653a4b7bcd1
F test/main.test 1626345b5f630c5398eede500d9354813b76b0fd
F test/malloc.test 70fdd0812e2a57eb746aaf015350f58bb8eee0b1
F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6
F test/notnull.test 70856457c86fe50877f760e4057e99fdedd2997c
F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
F test/pager.test 59bbc4e3d489529ed33db6e15595789e51056077
F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05
@ -110,19 +110,19 @@ F www/c_interface.tcl 82a026b1681757f13b3f62e035f3a31407c1d353
F www/changes.tcl 3770ded78faa7a634b55fbf5316caa4cb150e5f9
F www/conflict.tcl 3f70c01680b8d763bf3305eb67f6d85fdf83b497
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0
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 f04d74017e627f6f133438234bd20fbe585ca4cf
F www/lang.tcl 7ad595247fd81f394012a0cfd84ccd6241b9e59a
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 9bbddb8e013b47547164f71f2d7abd995f8d7385
R ad077c176de250ed6687e2b5636281f6
P cf1538d71c9ce12d5e59f367e03642cbcaf6b717
R b0c9c7a017538a09b4eca555b386a82f
U drh
Z 1ba7e7bec405961a534e04fc39ece2b3
Z b508e059fe2aafe83b423b2a1e04f6ed

View File

@ -1 +1 @@
cf1538d71c9ce12d5e59f367e03642cbcaf6b717
d0e7cf4a83e6abad7129bed356b7492dddaff474

View File

@ -28,7 +28,9 @@ gzip sqlite.bin
# under Linux
#
make target_source
rm sqlite_source.zip
cd tsrc
zip ../sqlite_source.zip *
rm shell.c
TCLDIR=/home/drh/tcltk/8.2linux
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
@ -36,9 +38,14 @@ OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
strip tclsqlite.so
mv tclsqlite.so ..
rm tclsqlite.c
gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so
strip sqlite.so
mv sqlite.so ..
cd ..
rm -f tclsqlite.so.gz
rm -f tclsqlite.so.gz sqlite.so.gz
gzip tclsqlite.so
gzip sqlite.so
# Build the tclsqlite.dll shared library that can be imported into tclsh
# or wish on windows.
@ -69,9 +76,43 @@ i386-mingw32-dllwrap \
-dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
i386-mingw32-strip tclsqlite.dll
mv tclsqlite.dll ..
rm tclsqlite.o
cat >sqlite.def <<\END_OF_FILE
EXPORTS
sqlite_open
sqlite_close
sqlite_exec
sqlite_last_insert_rowid
sqlite_error_string
sqlite_interrupt
sqlite_complete
sqlite_busy_handler
sqlite_busy_timeout
sqlite_get_table
sqlite_free_table
sqlite_mprintf
sqlite_vmprintf
sqlite_exec_printf
sqlite_exec_vprintf
sqlite_get_table_printf
sqlite_get_table_vprintf
sqliteMalloc
sqliteFree
sqliteRealloc
END_OF_FILE
i386-mingw32-dllwrap \
--def sqlite.def -v --export-all \
--driver-name i386-mingw32-gcc \
--dlltool-name i386-mingw32-dlltool \
--as i386-mingw32-as \
--target i386-mingw32 \
-dllname sqlite.dll -lmsvcrt *.o
i386-mingw32-strip sqlite.dll
mv sqlite.dll sqlite.def ..
cd ..
rm -f tclsqlite.zip
rm -f tclsqlite.zip sqlitedll.zip
zip tclsqlite.zip tclsqlite.dll
zip sqlitedll.zip sqlite.dll sqlite.def
# Build the sqlite.exe executable for windows.
#
@ -103,3 +144,4 @@ cp $srcdir/../historical/* .
rm -rf doc
make doc
ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc
ln sqlitedll.zip sqlite.so.gz sqlite_source.zip doc

View File

@ -25,7 +25,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.69 2002/01/30 16:17:24 drh Exp $
** $Id: build.c,v 1.70 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -422,7 +422,7 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){
rc = sqliteBtreeBeginTrans(db->pBeTemp);
if( rc!=SQLITE_OK ){
sqliteSetNString(&pParse->zErrMsg, "unable to get a write lock on "
"the temporary datbase file", 0);
"the temporary database file", 0);
pParse->nErr++;
return;
}
@ -474,11 +474,7 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
pParse->pNewTable = pTable;
if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
if( !isTemp ){
sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
@ -738,9 +734,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){
sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
sqliteVdbeAddOp(v, OP_Close, 0, 0);
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
}
}
@ -802,11 +796,7 @@ void sqliteDropTable(Parse *pParse, Token *pName){
{ OP_Close, 0, 0, 0},
};
Index *pIdx;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
if( !pTable->isTemp ){
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
sqliteVdbeChangeP3(v, base+2, pTable->zName, P3_STATIC);
@ -817,9 +807,7 @@ void sqliteDropTable(Parse *pParse, Token *pName){
for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
}
/* Move the table (and all its indices) to the pending DROP queue.
@ -1057,11 +1045,7 @@ void sqliteCreateIndex(
v = sqliteGetVdbe(pParse);
if( v==0 ) goto exit_create_index;
if( pTable!=0 ){
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
if( !isTemp ){
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
@ -1118,9 +1102,7 @@ void sqliteCreateIndex(
sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
sqliteVdbeAddOp(v, OP_Close, 0, 0);
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
}
}
@ -1173,11 +1155,7 @@ void sqliteDropIndex(Parse *pParse, Token *pName){
int base;
Table *pTab = pIndex->pTable;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
if( !pTab->isTemp ){
base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC);
@ -1185,9 +1163,7 @@ void sqliteDropIndex(Parse *pParse, Token *pName){
sqliteVdbeChangeP1(v, base+10, db->next_cookie);
}
sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
}
/* Move the index onto the pending DROP queue. Or, if the index was
@ -1337,7 +1313,7 @@ void sqliteCopy(
){
Table *pTab;
char *zTab;
int i, j;
int i;
Vdbe *v;
int addr, end;
Index *pIdx;
@ -1362,11 +1338,7 @@ void sqliteCopy(
v = sqliteGetVdbe(pParse);
if( v ){
int openOp;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
sqliteVdbeDequoteP3(v, addr);
@ -1411,9 +1383,7 @@ void sqliteCopy(
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_Noop, 0, 0);
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
@ -1450,11 +1420,7 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
}
v = sqliteGetVdbe(pParse);
if( v==0 ) goto vacuum_cleanup;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
if( zName ){
sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
@ -1472,9 +1438,7 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
}
}
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
vacuum_cleanup:
sqliteFree(zName);
@ -1484,20 +1448,15 @@ vacuum_cleanup:
/*
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse){
void sqliteBeginTransaction(Parse *pParse, int onError){
sqlite *db;
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( db->flags & SQLITE_InTrans ) return;
v = sqliteGetVdbe(pParse);
if( v ){
sqliteVdbeAddOp(v, OP_Transaction, 1, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
db->flags |= SQLITE_InTrans;
db->onError = onError;
}
/*
@ -1505,16 +1464,13 @@ void sqliteBeginTransaction(Parse *pParse){
*/
void sqliteCommitTransaction(Parse *pParse){
sqlite *db;
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( (db->flags & SQLITE_InTrans)==0 ) return;
v = sqliteGetVdbe(pParse);
if( v ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
db->flags &= ~SQLITE_InTrans;
sqliteEndWriteOperation(pParse);
db->onError = OE_Default;
}
/*
@ -1532,8 +1488,46 @@ void sqliteRollbackTransaction(Parse *pParse){
sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
}
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
/*
** Generate VDBE code that prepares for doing an operation that
** might change the database. If we are in the middle of a transaction,
** then this sets a checkpoint. If we are not in a transaction, then
** start a transaction.
*/
void sqliteBeginWriteOperation(Parse *pParse){
Vdbe *v;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( pParse->db->flags & SQLITE_InTrans ){
/* sqliteVdbeAddOp(v, OP_CheckPoint, 0, 0); */
}else{
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
}
/*
** Generate code that concludes an operation that may have changed
** the database. This is a companion function to BeginWriteOperation().
** If a transaction was started, then commit it. If a checkpoint was
** started then commit that.
*/
void sqliteEndWriteOperation(Parse *pParse){
Vdbe *v;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( pParse->db->flags & SQLITE_InTrans ){
/* Do Nothing */
}else{
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
}
/*
** Interpret the given string as a boolean value.
*/

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.25 2002/01/29 23:07:02 drh Exp $
** $Id: delete.c,v 1.26 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
@ -82,11 +82,7 @@ void sqliteDeleteFrom(
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) goto delete_from_cleanup;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
@ -156,9 +152,7 @@ void sqliteDeleteFrom(
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were deleted.

View File

@ -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.38 2002/01/30 16:17:24 drh Exp $
** $Id: insert.c,v 1.39 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
@ -79,11 +79,7 @@ void sqliteInsert(
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) goto insert_cleanup;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step has to generate
@ -270,9 +266,7 @@ void sqliteInsert(
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
}
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows inserted.
@ -312,8 +306,8 @@ insert_cleanup:
** N. The data in the last column of the entry after the update.
**
** The old recno shown as entry (1) above is omitted unless both isUpdate
** and recnoChng are both 1. isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is ture if the record number is being changed.
** and recnoChng are 1. isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is true if the record number is being changed.
**
** The code generated by this routine pushes additional entries onto
** the stack which are the keys for new index entries for the new record.
@ -323,18 +317,25 @@ insert_cleanup:
**
** This routine also generates code to check constraints. NOT NULL,
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
** then the appropriate action is performed. The default action is to
** execute OP_Halt to abort the transaction and cause sqlite_exec() to
** return SQLITE_CONSTRAINT. This is the so-called "ABORT" action.
** Other actions are REPLACE and IGNORE. The following table summarizes
** what happens.
** then the appropriate action is performed. There are five possible
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
**
** Constraint type Action What Happens
** --------------- ---------- ----------------------------------------
** any ABORT The current transaction is rolled back and
** any ROLLBACK The current transaction is rolled back and
** sqlite_exec() returns immediately with a
** return code of SQLITE_CONSTRAINT.
**
** any ABORT Back out changes from the current command
** only (do not do a complete rollback) then
** cause sqlite_exec() to return immediately
** with SQLITE_CONSTRAINT.
**
** any FAIL Sqlite_exec() returns immediately with a
** return code of SQLITE_CONSTRAINT. The
** transaction is not rolled back and any
** prior changes are retained.
**
** any IGNORE The record number and data is popped from
** the stack and there is an immediate jump
** to label ignoreDest.
@ -348,9 +349,10 @@ insert_cleanup:
**
** CHECK REPLACE Illegal. The results in an exception.
**
** The action to take is determined by the constraint itself if
** overrideError is OE_Default. Otherwise, overrideError determines
** which action to use.
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used. Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must an open read/write cursor for pTab with
** cursor number "base". All indices of pTab must also have open
@ -390,6 +392,9 @@ void sqliteGenerateConstraintChecks(
v = sqliteGetVdbe(pParse);
assert( v!=0 );
nCol = pTab->nCol;
if( overrideError==OE_Default ){
overrideError = pParse->db->onError;
}
/* Test all NOT NULL constraints.
*/
@ -402,6 +407,8 @@ void sqliteGenerateConstraintChecks(
if( onError==OE_None ) continue;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
onError = OE_Abort;
@ -409,8 +416,10 @@ void sqliteGenerateConstraintChecks(
sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
addr = sqliteVdbeAddOp(v, OP_NotNull, 0, 0);
switch( onError ){
case OE_Abort: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
break;
}
case OE_Ignore: {
@ -441,10 +450,14 @@ void sqliteGenerateConstraintChecks(
onError = pTab->keyConf;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
switch( onError ){
case OE_Abort: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
break;
}
case OE_Ignore: {
@ -479,12 +492,16 @@ void sqliteGenerateConstraintChecks(
if( onError==OE_None ) continue;
if( overrideError!=OE_Default ){
onError = overrideError;
}else 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);
switch( onError ){
case OE_Abort: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, 0);
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
break;
}
case OE_Ignore: {

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.56 2002/01/16 21:00:27 drh Exp $
** $Id: main.c,v 1.57 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -276,6 +276,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0);
sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0);
db->nextRowid = sqliteRandomInteger();
db->onError = OE_Default;
/* Open the backend database driver */
rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);

View File

@ -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.44 2002/01/30 16:17:24 drh Exp $
** @(#) $Id: parse.y,v 1.45 2002/01/31 15:54:22 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@ -56,7 +56,7 @@ explain ::= EXPLAIN. {pParse->explain = 1;}
///////////////////// Begin and end transactions. ////////////////////////////
//
cmd ::= BEGIN trans_opt. {sqliteBeginTransaction(pParse);}
cmd ::= BEGIN trans_opt onconf(R). {sqliteBeginTransaction(pParse,R);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
trans_opt ::= TRANSACTION ids.
@ -106,6 +106,7 @@ id(A) ::= KEY(X). {A = X;}
id(A) ::= ABORT(X). {A = X;}
id(A) ::= IGNORE(X). {A = X;}
id(A) ::= REPLACE(X). {A = X;}
id(A) ::= FAIL(X). {A = X;}
id(A) ::= CONFLICT(X). {A = X;}
// And "ids" is an identifer-or-string.
@ -166,15 +167,17 @@ tcons ::= CHECK expr onconf.
// default behavior when there is a constraint conflict.
//
%type onconf {int}
%type onconf_u {int}
%type confresolve {int}
onconf(A) ::= confresolve(X). { A = X; }
onconf(A) ::= onconf_u(X). { A = X; }
onconf_u(A) ::= ON CONFLICT confresolve(X). { A = X; }
onconf_u(A) ::= . { A = OE_Default; }
confresolve(A) ::= ABORT. { A = OE_Abort; }
confresolve(A) ::= IGNORE. { A = OE_Ignore; }
confresolve(A) ::= REPLACE. { A = OE_Replace; }
%type orconf {int}
%type resolvetype {int}
onconf(A) ::= . { A = OE_Default; }
onconf(A) ::= ON CONFLICT resolvetype(X). { A = X; }
orconf(A) ::= . { A = OE_Default; }
orconf(A) ::= OR resolvetype(X). { A = X; }
resolvetype(A) ::= ROLLBACK. { A = OE_Rollback; }
resolvetype(A) ::= ABORT. { A = OE_Abort; }
resolvetype(A) ::= FAIL. { A = OE_Fail; }
resolvetype(A) ::= IGNORE. { A = OE_Ignore; }
resolvetype(A) ::= REPLACE. { A = OE_Replace; }
////////////////////////// The DROP TABLE /////////////////////////////////////
//
@ -313,7 +316,7 @@ where_opt(A) ::= WHERE expr(X). {A = X;}
////////////////////////// The UPDATE command ////////////////////////////////
//
cmd ::= UPDATE onconf_u(R) ids(X) SET setlist(Y) where_opt(Z).
cmd ::= UPDATE orconf(R) ids(X) SET setlist(Y) where_opt(Z).
{sqliteUpdate(pParse,&X,Y,Z,R);}
setlist(A) ::= setlist(Z) COMMA ids(X) EQ expr(Y).
@ -322,9 +325,9 @@ setlist(A) ::= ids(X) EQ expr(Y). {A = sqliteExprListAppend(0,Y,&X);}
////////////////////////// The INSERT command /////////////////////////////////
//
cmd ::= INSERT onconf(R) INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP.
cmd ::= INSERT orconf(R) INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP.
{sqliteInsert(pParse, &X, Y, 0, F, R);}
cmd ::= INSERT onconf(R) INTO ids(X) inscollist_opt(F) select(S).
cmd ::= INSERT orconf(R) INTO ids(X) inscollist_opt(F) select(S).
{sqliteInsert(pParse, &X, 0, S, F, R);}
@ -548,9 +551,9 @@ cmd ::= DROP INDEX ids(X). {sqliteDropIndex(pParse, &X);}
///////////////////////////// The COPY command ///////////////////////////////
//
cmd ::= COPY onconf_u(R) ids(X) FROM ids(Y) USING DELIMITERS STRING(Z).
cmd ::= COPY orconf(R) ids(X) FROM ids(Y) USING DELIMITERS STRING(Z).
{sqliteCopy(pParse,&X,&Y,&Z,R);}
cmd ::= COPY onconf_u(R) ids(X) FROM ids(Y).
cmd ::= COPY orconf(R) ids(X) FROM ids(Y).
{sqliteCopy(pParse,&X,&Y,0,R);}
///////////////////////////// The VACUUM command /////////////////////////////

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.82 2002/01/30 16:17:24 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.83 2002/01/31 15:54:22 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
@ -183,6 +183,7 @@ struct sqlite {
Hash idxDrop; /* Uncommitted DROP INDEXs */
int lastRowid; /* ROWID of most recent insert */
int nextRowid; /* Next generated rowID */
int onError; /* Default conflict algorithm */
};
/*
@ -237,19 +238,31 @@ struct Table {
};
/*
** SQLite supports three different ways to resolve a UNIQUE contraint
** error. (1) It can abort the transaction return SQLITE_CONSTRAINT.
** (2) It can decide to not do the INSERT or UPDATE that was causing
** the constraint violation. (3) It can delete existing records from
** the table so that the pending INSERT or UPDATE will work without
** a constraint error. The following there symbolic values are used
** to record which type of action to take.
** SQLite supports 4 or 5 different ways to resolve a contraint
** error. (Only 4 are implemented as of this writing. The fifth method
** "ABORT" is planned.) ROLLBACK processing means that a constraint violation
** causes the operation in proces to fail and for the current transaction
** to be rolled back. ABORT processing means the operation in process
** fails and any prior changes from that one operation are backed out,
** but the transaction is not rolled back. FAIL processing means that
** the operation in progress stops and returns an error code. But prior
** changes due to the same operation are not backed out and no rollback
** occurs. IGNORE means that the particular row that caused the constraint
** error is not inserted or updated. Processing continues and no error
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
**
** The following there symbolic values are used to record which type
** of action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Abort 1 /* Abort and rollback. */
#define OE_Ignore 2 /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace 3 /* Delete existing record, then do INSERT or UPDATE */
#define OE_Default 9 /* Do whatever the default action is */
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
#define OE_Abort 2 /* Back out changes but do no rollback transaction */
#define OE_Fail 3 /* Stop the operation but leave all prior changes */
#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
#define OE_Default 9 /* Do whatever the default action is */
/*
** Each SQL index is represented in memory by an
@ -542,7 +555,7 @@ void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*);
void sqliteBeginTransaction(Parse*, int);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);
@ -551,3 +564,5 @@ void sqliteGenerateRowDelete(Vdbe*, Table*, int);
void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
void sqliteBeginWriteOperation(Parse*);
void sqliteEndWriteOperation(Parse*);

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.33 2002/01/29 18:41:25 drh Exp $
** $Id: tokenize.c,v 1.34 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -62,6 +62,7 @@ static Keyword aKeywordTable[] = {
{ "END", 0, TK_END, 0 },
{ "EXCEPT", 0, TK_EXCEPT, 0 },
{ "EXPLAIN", 0, TK_EXPLAIN, 0 },
{ "FAIL", 0, TK_FAIL, 0 },
{ "FROM", 0, TK_FROM, 0 },
{ "GLOB", 0, TK_GLOB, 0 },
{ "GROUP", 0, TK_GROUP, 0 },

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.31 2002/01/30 16:17:24 drh Exp $
** $Id: update.c,v 1.32 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
@ -161,11 +161,7 @@ void sqliteUpdate(
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) goto update_cleanup;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
sqliteBeginWriteOperation(pParse);
/* Begin the database scan
*/
@ -282,9 +278,7 @@ void sqliteUpdate(
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were changed.

View File

@ -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.112 2002/01/30 16:17:24 drh Exp $
** $Id: vdbe.c,v 1.113 2002/01/31 15:54:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1072,6 +1072,7 @@ int sqliteVdbeExec(
sqlite *db = p->db; /* The database */
char **zStack; /* Text stack */
Stack *aStack; /* Additional stack information */
int rollbackOnError = 1; /* Do a ROLLBACK if an error is encountered */
char zBuf[100]; /* Space to sprintf() an integer */
@ -1149,14 +1150,20 @@ case OP_Goto: {
break;
}
/* Opcode: Halt P1 * *
/* Opcode: Halt P1 P2 *
**
** Exit immediately. All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec(). For a normal
** halt, this should be SQLITE_OK (0). For errors, it can be some
** other value.
** other value. If P1!=0 then P2 will determine whether or not to
** rollback the current transaction. Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction. (This last case has
** not yet been implemented. OE_Abort works like OE_Rollback for
** now. In the future that may change.)
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
@ -1165,6 +1172,7 @@ case OP_Goto: {
case OP_Halt: {
if( pOp->p1!=SQLITE_OK ){
rc = pOp->p1;
rollbackOnError = pOp->p2!=OE_Fail;
goto abort_due_to_error;
}else{
pc = p->nOp-1;
@ -4458,12 +4466,13 @@ default: {
cleanup:
Cleanup(p);
if( rc!=SQLITE_OK ){
if( rc!=SQLITE_OK && rollbackOnError ){
closeAllCursors(p);
sqliteBtreeRollback(pBt);
if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
sqliteRollbackInternalChanges(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
return rc;

View File

@ -13,7 +13,7 @@
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.3 2002/01/30 16:17:25 drh Exp $
# $Id: conflict.test,v 1.4 2002/01/31 15:54:23 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -36,37 +36,37 @@ do_test conflict-1.2 {
} {1 {constraint failed}}
do_test conflict-1.3 {
catchsql {
INSERT ON CONFLICT IGNORE INTO t1 VALUES(1,2,4);
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 ON CONFLICT REPLACE INTO t1 VALUES(1,2,4);
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 ON CONFLICT ABORT INTO t1 VALUES(1,2,5);
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 IGNORE INTO t1 VALUES(1,2,5);
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 REPLACE INTO t1 VALUES(1,2,5);
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 ON CONFLICT ABORT INTO t1 VALUES(1,2,6);
INSERT OR ABORT INTO t1 VALUES(1,2,6);
SELECT c FROM t1 ORDER BY c;
}
} {1 {constraint failed}}
@ -89,13 +89,13 @@ do_test conflict-1.9 {
} 8
do_test conflict-1.10 {
catchsql {
INSERT IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
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 REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
SELECT c FROM t1 ORDER BY c;
}
} {0 {14 24}}
@ -103,7 +103,7 @@ do_test conflict-1.11 {
###### Fix me!
do_test conflict-1.12 {
catchsql {
INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
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}}
@ -121,7 +121,7 @@ do_test conflict-1.13 {
} {1 2 3 1 3 4 2 3 5}
do_test conflict-1.14 {
catchsql {
UPDATE ON CONFLICT ABORT t1 SET b=3 WHERE b=2;
UPDATE OR ABORT t1 SET b=3 WHERE b=2;
SELECT c FROM t1 ORDER BY c;
}
} {1 {constraint failed}};
@ -133,13 +133,13 @@ do_test conflict-1.15 {
} {1 {constraint failed}};
do_test conflict-1.16 {
catchsql {
UPDATE ON CONFLICT IGNORE t1 SET b=3 WHERE b=2;
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 ON CONFLICT REPLACE t1 SET b=3 WHERE b=2;
UPDATE OR REPLACE t1 SET b=3 WHERE b=2;
SELECT * FROM t1 ORDER BY c;
}
} {0 {1 3 3 2 3 5}}
@ -163,37 +163,37 @@ do_test conflict-2.2 {
} {1 {constraint failed}}
do_test conflict-2.3 {
catchsql {
INSERT ON CONFLICT IGNORE INTO t1 VALUES(1,2,4);
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 ON CONFLICT REPLACE INTO t1 VALUES(1,2,4);
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 ON CONFLICT ABORT INTO t1 VALUES(1,2,5);
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 IGNORE INTO t1 VALUES(1,2,5);
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 REPLACE INTO t1 VALUES(1,2,5);
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 ON CONFLICT ABORT INTO t1 VALUES(1,2,6);
INSERT OR ABORT INTO t1 VALUES(1,2,6);
SELECT c FROM t1 ORDER BY c;
}
} {1 {constraint failed}}
@ -216,13 +216,13 @@ do_test conflict-2.9 {
} 8
do_test conflict-2.10 {
catchsql {
INSERT IGNORE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
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 REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
INSERT OR REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c;
SELECT c FROM t1 ORDER BY c;
}
} {0 {14 24}}
@ -230,7 +230,7 @@ do_test conflict-2.11 {
###### Fix me!
do_test conflict-2.12 {
catchsql {
INSERT REPLACE INTO t1 SELECT a,b,c FROM t2 ORDER BY c DESC;
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}}
@ -248,7 +248,7 @@ do_test conflict-2.13 {
} {1 2 3 2 3 4 3 3 5}
do_test conflict-2.14 {
catchsql {
UPDATE ON CONFLICT ABORT t1 SET a=2, b=3 WHERE b=2;
UPDATE OR ABORT t1 SET a=2, b=3 WHERE b=2;
SELECT c FROM t1 ORDER BY c;
}
} {1 {constraint failed}};
@ -260,13 +260,13 @@ do_test conflict-2.15 {
} {1 {constraint failed}};
do_test conflict-2.16 {
catchsql {
UPDATE ON CONFLICT IGNORE t1 SET a=2, b=3 WHERE b=2;
UPDATE OR IGNORE t1 SET a=2, b=3 WHERE b=2;
SELECT * FROM t1 ORDER BY c;
}
} {0 {1 2 3 2 3 4 3 3 5}}
do_test conflict-2.17 {
catchsql {
UPDATE ON CONFLICT REPLACE t1 SET a=2, b=3 WHERE b=2;
UPDATE OR REPLACE t1 SET a=2, b=3 WHERE b=2;
SELECT * FROM t1 ORDER BY c;
}
} {0 {2 3 3 3 3 5}}

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the COPY statement.
#
# $Id: copy.test,v 1.7 2002/01/30 16:17:25 drh Exp $
# $Id: copy.test,v 1.8 2002/01/31 15:54:23 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -194,7 +194,7 @@ do_test copy-5.3 {
puts $fd "33|22|44"
close $fd
catchsql {
COPY ON CONFLICT IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|';
COPY OR IGNORE t1 FROM 'data6.txt' USING DELIMITERS '|';
SELECT * FROM t1;
}
} {0 {11 22 33 22 33 11}}
@ -203,7 +203,7 @@ do_test copy-5.4 {
puts $fd "33|22|44"
close $fd
catchsql {
COPY ON CONFLICT REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|';
COPY OR REPLACE t1 FROM 'data6.txt' USING DELIMITERS '|';
SELECT * FROM t1;
}
} {0 {22 33 11 33 22 44}}

View File

@ -12,7 +12,7 @@
#
# This file implements tests for the NOT NULL constraint.
#
# $Id: notnull.test,v 1.1 2002/01/30 04:32:01 drh Exp $
# $Id: notnull.test,v 1.2 2002/01/31 15:54:23 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -22,9 +22,9 @@ do_test notnull-1.0 {
CREATE TABLE t1 (
a NOT NULL,
b NOT NULL DEFAULT 5,
c NOT NULL REPLACE DEFAULT 6,
d NOT NULL IGNORE DEFAULT 7,
e NOT NULL ABORT DEFAULT 8
c NOT NULL ON CONFLICT REPLACE DEFAULT 6,
d NOT NULL ON CONFLICT IGNORE DEFAULT 7,
e NOT NULL ON CONFLICT ABORT DEFAULT 8
);
SELECT * FROM t1;
}
@ -46,21 +46,21 @@ do_test notnull-1.2 {
do_test notnull-1.3 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-1.4 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-1.5 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
@ -74,21 +74,21 @@ do_test notnull-1.6 {
do_test notnull-1.7 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
do_test notnull-1.8 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
do_test notnull-1.9 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
@ -102,14 +102,14 @@ do_test notnull-1.10 {
do_test notnull-1.11 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-1.12 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
@ -123,35 +123,35 @@ do_test notnull-1.13 {
do_test notnull-1.14 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-1.15 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 2 6 4 5}}
do_test notnull-1.16 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-1.17 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-1.18 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
SELECT * FROM t1 order by a;
}
} {0 {1 2 3 7 5}}
@ -172,7 +172,7 @@ do_test notnull-1.20 {
do_test notnull-1.21 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
SELECT * FROM t1 order by a;
}
} {0 {5 5 3 2 1}}
@ -189,7 +189,7 @@ do_test notnull-2.2 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT REPLACE t1 SET a=null;
UPDATE OR REPLACE t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {1 {constraint failed}}
@ -197,7 +197,7 @@ do_test notnull-2.3 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT IGNORE t1 SET a=null;
UPDATE OR IGNORE t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 2 3 4 5}}
@ -205,7 +205,7 @@ do_test notnull-2.4 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT ABORT t1 SET a=null;
UPDATE OR ABORT t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {1 {constraint failed}}
@ -221,7 +221,7 @@ do_test notnull-2.6 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT REPLACE t1 SET b=null, d=e, e=d;
UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 5 3 5 4}}
@ -229,7 +229,7 @@ do_test notnull-2.7 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT IGNORE t1 SET b=null, d=e, e=d;
UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 2 3 4 5}}
@ -285,21 +285,21 @@ do_test notnull-3.2 {
do_test notnull-3.3 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR IGNORE INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-3.4 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR REPLACE INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-3.5 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
INSERT OR ABORT INTO t1(b,c,d,e) VALUES(2,3,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
@ -313,21 +313,21 @@ do_test notnull-3.6 {
do_test notnull-3.7 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR IGNORE INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
do_test notnull-3.8 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR REPLACE INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
do_test notnull-3.9 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
INSERT OR ABORT INTO t1(a,c,d,e) VALUES(1,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
@ -341,14 +341,14 @@ do_test notnull-3.10 {
do_test notnull-3.11 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-3.12 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,null,3,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 5 3 4 5}}
@ -362,35 +362,35 @@ do_test notnull-3.13 {
do_test notnull-3.14 {
catchsql {
DELETE FROM t1;
INSERT IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR IGNORE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {0 {}}
do_test notnull-3.15 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR REPLACE INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {0 {1 2 6 4 5}}
do_test notnull-3.16 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,null,4,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-3.17 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
INSERT OR ABORT INTO t1(a,b,c,d,e) VALUES(1,2,3,null,5);
SELECT * FROM t1 order by a;
}
} {1 {constraint failed}}
do_test notnull-3.18 {
catchsql {
DELETE FROM t1;
INSERT ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
INSERT OR ABORT INTO t1(a,b,c,e) VALUES(1,2,3,5);
SELECT * FROM t1 order by a;
}
} {0 {1 2 3 7 5}}
@ -411,7 +411,7 @@ do_test notnull-3.20 {
do_test notnull-3.21 {
catchsql {
DELETE FROM t1;
INSERT REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
INSERT OR REPLACE INTO t1(e,d,c,b,a) VALUES(1,2,3,null,5);
SELECT * FROM t1 order by a;
}
} {0 {5 5 3 2 1}}
@ -428,7 +428,7 @@ do_test notnull-4.2 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT REPLACE t1 SET a=null;
UPDATE OR REPLACE t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {1 {constraint failed}}
@ -436,7 +436,7 @@ do_test notnull-4.3 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT IGNORE t1 SET a=null;
UPDATE OR IGNORE t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 2 3 4 5}}
@ -444,7 +444,7 @@ do_test notnull-4.4 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT ABORT t1 SET a=null;
UPDATE OR ABORT t1 SET a=null;
SELECT * FROM t1 ORDER BY a;
}
} {1 {constraint failed}}
@ -460,7 +460,7 @@ do_test notnull-4.6 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT REPLACE t1 SET b=null, d=e, e=d;
UPDATE OR REPLACE t1 SET b=null, d=e, e=d;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 5 3 5 4}}
@ -468,7 +468,7 @@ do_test notnull-4.7 {
catchsql {
DELETE FROM t1;
INSERT INTO t1 VALUES(1,2,3,4,5);
UPDATE ON CONFLICT IGNORE t1 SET b=null, d=e, e=d;
UPDATE OR IGNORE t1 SET b=null, d=e, e=d;
SELECT * FROM t1 ORDER BY a;
}
} {0 {1 2 3 4 5}}

View File

@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the download.html file.
#
set rcsid {$Id: download.tcl,v 1.2 2001/11/24 13:23:05 drh Exp $}
set rcsid {$Id: download.tcl,v 1.3 2002/01/31 15:54:23 drh Exp $}
puts {<html>
<head><title>SQLite Download Page</title></head>
@ -41,6 +41,11 @@ Product tclsqlite.so.gz {
See <a href="tclsqlite.html">the documentation</a> for details.
}
Product sqlite.so.gz {
A precompiled shared-library for Linux. This is the same as
<b>tclsqlite.so.gz</b> but without the TCL bindings.
}
puts {<h2>Precompiled Binaries For Windows</h2>}
Product sqlite.zip {
@ -52,9 +57,21 @@ Product tclsqlite.zip {
tclsh or wish to get SQLite database access from Tcl/Tk.
See <a href="tclsqlite.html">the documentation</a> for details.
}
Product sqlitedll.zip {
This is a DLL of the SQLite library without the TCL bindings.
The only external dependency is MSVCRT.DLL.
}
puts {<h2>Source Code</h2>}
Product {sqlite_source.zip} {
This ZIP archive contains pure C source code for the SQLite library.
Unlike the tarballs below, all of the preprocessing has already been
done on these C source code, so you can just hand the files directly to
your favorite C compiler. This file is provided as a service to
MS-Windows users who lack the build support infrastructure of Unix.
}
foreach name [lsort -dict -decreasing [glob -nocomplain sqlite-*.tar.gz]] {
regexp {sqlite-(.*)\.tar\.gz} $name match vers
Product $name "

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.19 2002/01/30 16:17:25 drh Exp $}
set rcsid {$Id: lang.tcl,v 1.20 2002/01/31 15:54:23 drh Exp $}
puts {<html>
<head>
@ -333,6 +333,11 @@ default algorithm specified in the CREATE TABLE statement.
See the section titled
<a href="#conflict">ON CONFLICT</a> for additional information.</p>
<p>CHECK constraints are ignored in the current implementation.
Support for CHECK constraints may be added in the future. As of
version 2.3.0, NOT NULL, PRIMARY KEY, and UNIQUE constraints all
work.</p>
<p>There are no arbitrary limits on the number
of columns or on the number of constraints in a table.
The total amount of data in a single row is limited to about