From: drh Date: Sat, 27 Feb 2016 17:16:34 +0000 (+0000) Subject: Experimental "PRAGMA onconflict=FAIL" statement to change the default X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ed7ab43885208a237867c1089d88f1461d7be0a6;p=thirdparty%2Fsqlite.git Experimental "PRAGMA onconflict=FAIL" statement to change the default ON CONFLICT algorithm to something other than ABORT. FossilOrigin-Name: 3a0c347cca58fdaefd1b3644ba1649a5b4ebe91f --- diff --git a/manifest b/manifest index 435c15b0a4..cfdf895f82 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\s".stats"\scommand\sin\ssqlite3.exe\sto\sshow\sone-time\sstats\sinformation\nif\sinvoked\swith\sone\sargument.\s\sAlso\sshow\s/proc/PID/io\sinformation\sif\srun\son\nLinux. -D 2016-02-27T17:12:36.918 +C Experimental\s"PRAGMA\sonconflict=FAIL"\sstatement\sto\schange\sthe\sdefault\nON\sCONFLICT\salgorithm\sto\ssomething\sother\sthan\sABORT. +D 2016-02-27T17:16:34.701 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -310,11 +310,11 @@ F src/global.c ded7b97efd16efda5062b65e857198e46c40e652 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef +F src/insert.c b42e0c7e81da4a56c664c3895c675662ac6469f4 F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f -F src/main.c be9309f442ec291177642d2e48e82290e0951f4b +F src/main.c 2bf81b968e8e1f9ce778eb5b61b389ab145f9497 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -342,8 +342,8 @@ F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051 -F src/pragma.c d6028d23a9495a8b55f2075e3244ec9a0485e03e -F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c +F src/pragma.c f8f9bf11e2cb362d3a81264b7795ca89a8f695d9 +F src/pragma.h 0639ea9901f8a22433a94ca8b0f35921d6ac2306 F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 @@ -354,7 +354,7 @@ F src/shell.c f30efdd675007ec6006d51193fc47aabda2984a5 F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d -F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406 +F src/sqliteInt.h eed052038018d543cd03ade7f3a69830ff302777 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -410,7 +410,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c F src/treeview.c c525282442111b3f61eb176784567cd6654db5dc F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca +F src/update.c 3c911431bcc7c6b5f996743d807ff0a9ef9e088a F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 6ed9d7bdd3b0a30742027b6d8e8e1a9e2b14f373 F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 @@ -1391,7 +1391,7 @@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e -F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41 +F tool/mkpragmatab.tcl bf99a05342afb7baf04c7b18b151d5b55ae8588f F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835 F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84 @@ -1451,7 +1451,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d1392c627934b89cdb86d82e73d56e8f76952b30 -R cc008a8c941c26feeb254cac8325586b +P 3c36948f16b58fe8042c37d0df634308b4e48217 +R 60015793d5c7a8b9994caa990b084503 +T *branch * pragma-onconflict +T *sym-pragma-onconflict * +T -sym-trunk * U drh -Z 0f34ce71f4553990685c1f98cc5c169c +Z 2a9189a9e71cee0c4156061d04e62711 diff --git a/manifest.uuid b/manifest.uuid index 31a87c6516..3c0f43e458 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c36948f16b58fe8042c37d0df634308b4e48217 \ No newline at end of file +3a0c347cca58fdaefd1b3644ba1649a5b4ebe91f \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 7ff884b8c3..82c3a5d332 100644 --- a/src/insert.c +++ b/src/insert.c @@ -988,7 +988,7 @@ void sqlite3Insert( const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); + sqlite3VdbeChangeP5(v, onError==OE_Default ? db->dfltOnError : onError); sqlite3MayAbort(pParse); }else #endif @@ -1282,10 +1282,10 @@ void sqlite3GenerateConstraintChecks( if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ - onError = OE_Abort; + onError = db->dfltOnError; } if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ - onError = OE_Abort; + onError = db->dfltOnError; } assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); @@ -1325,7 +1325,7 @@ void sqlite3GenerateConstraintChecks( if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regNewData+1; - onError = overrideError!=OE_Default ? overrideError : OE_Abort; + onError = overrideError!=OE_Default ? overrideError : db->dfltOnError; for(i=0; inExpr; i++){ int allOk; Expr *pExpr = pCheck->a[i].pExpr; @@ -1337,7 +1337,7 @@ void sqlite3GenerateConstraintChecks( }else{ char *zName = pCheck->a[i].zName; if( zName==0 ) zName = pTab->zName; - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ + if( onError==OE_Replace ) onError = db->dfltOnError; /* IMP: R-15569-63625 */ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, onError, zName, P4_TRANSIENT, P5_ConstraintCheck); @@ -1358,7 +1358,7 @@ void sqlite3GenerateConstraintChecks( if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ - onError = OE_Abort; + onError = db->dfltOnError; } if( isUpdate ){ @@ -1390,6 +1390,7 @@ void sqlite3GenerateConstraintChecks( VdbeCoverage(v); /* Generate code that deals with a rowid collision */ + if( onError==OE_Default ) onError = db->dfltOnError; switch( onError ){ default: { onError = OE_Abort; @@ -1532,7 +1533,7 @@ void sqlite3GenerateConstraintChecks( if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ - onError = OE_Abort; + onError = db->dfltOnError; } /* Check to see if the new index entry will be unique */ @@ -1910,7 +1911,7 @@ static int xferOptimization( #endif if( onError==OE_Default ){ if( pDest->iPKey>=0 ) onError = pDest->keyConf; - if( onError==OE_Default ) onError = OE_Abort; + if( onError==OE_Default ) onError = db->dfltOnError; } assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ if( pSelect->pSrc->nSrc!=1 ){ diff --git a/src/main.c b/src/main.c index 2a258da662..4490f10fe0 100644 --- a/src/main.c +++ b/src/main.c @@ -2779,6 +2779,7 @@ static int openDatabase( db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; + db->dfltOnError = OE_Abort; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); diff --git a/src/pragma.c b/src/pragma.c index 8b8f1f7bfd..84d65a2f9e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1894,6 +1894,29 @@ void sqlite3Pragma( break; } + /* + ** PRAGMA onconflict + ** PRAGMA onconflict = FAIL + ** PRAGMA onconflict = ABORT + ** PRAGMA onconflict = ROLLBACK + ** + ** Set the default conflict handling algorithm. + */ + case PragTyp_ONCONFLICT: { + const char *zRes = "ABORT"; + if( zRight ){ + if( sqlite3StrICmp(zRight,"FAIL")==0 ) db->dfltOnError = OE_Fail; + if( sqlite3StrICmp(zRight,"ABORT")==0 ) db->dfltOnError = OE_Abort; + if( sqlite3StrICmp(zRight,"ROLLBACK")==0 ) db->dfltOnError = OE_Rollback; + } + switch( db->dfltOnError ){ + case OE_Fail: zRes = "FAIL"; break; + case OE_Rollback: zRes = "ROLLBACK"; break; + } + returnSingleText(v, "onconflict", zRes); + break; + } + #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Report the current state of file logs for all databases diff --git a/src/pragma.h b/src/pragma.h index 81779e9d4a..b041e72eb5 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -28,24 +28,25 @@ #define PragTyp_LOCKING_MODE 22 #define PragTyp_PAGE_COUNT 23 #define PragTyp_MMAP_SIZE 24 -#define PragTyp_PAGE_SIZE 25 -#define PragTyp_SECURE_DELETE 26 -#define PragTyp_SHRINK_MEMORY 27 -#define PragTyp_SOFT_HEAP_LIMIT 28 -#define PragTyp_STATS 29 -#define PragTyp_SYNCHRONOUS 30 -#define PragTyp_TABLE_INFO 31 -#define PragTyp_TEMP_STORE 32 -#define PragTyp_TEMP_STORE_DIRECTORY 33 -#define PragTyp_THREADS 34 -#define PragTyp_WAL_AUTOCHECKPOINT 35 -#define PragTyp_WAL_CHECKPOINT 36 -#define PragTyp_ACTIVATE_EXTENSIONS 37 -#define PragTyp_HEXKEY 38 -#define PragTyp_KEY 39 -#define PragTyp_REKEY 40 -#define PragTyp_LOCK_STATUS 41 -#define PragTyp_PARSER_TRACE 42 +#define PragTyp_ONCONFLICT 25 +#define PragTyp_PAGE_SIZE 26 +#define PragTyp_SECURE_DELETE 27 +#define PragTyp_SHRINK_MEMORY 28 +#define PragTyp_SOFT_HEAP_LIMIT 29 +#define PragTyp_STATS 30 +#define PragTyp_SYNCHRONOUS 31 +#define PragTyp_TABLE_INFO 32 +#define PragTyp_TEMP_STORE 33 +#define PragTyp_TEMP_STORE_DIRECTORY 34 +#define PragTyp_THREADS 35 +#define PragTyp_WAL_AUTOCHECKPOINT 36 +#define PragTyp_WAL_CHECKPOINT 37 +#define PragTyp_ACTIVATE_EXTENSIONS 38 +#define PragTyp_HEXKEY 39 +#define PragTyp_KEY 40 +#define PragTyp_REKEY 41 +#define PragTyp_LOCK_STATUS 42 +#define PragTyp_PARSER_TRACE 43 #define PragFlag_NeedSchema 0x01 #define PragFlag_ReadOnly 0x02 static const struct sPragmaNames { @@ -299,6 +300,12 @@ static const struct sPragmaNames { /* ePragTyp: */ PragTyp_MMAP_SIZE, /* ePragFlag: */ 0, /* iArg: */ 0 }, +#endif + { /* zName: */ "onconflict", + /* ePragTyp: */ PragTyp_ONCONFLICT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "page_count", /* ePragTyp: */ PragTyp_PAGE_COUNT, /* ePragFlag: */ PragFlag_NeedSchema, @@ -461,4 +468,4 @@ static const struct sPragmaNames { /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; -/* Number of pragmas: 60 on by default, 73 total. */ +/* Number of pragmas: 61 on by default, 74 total. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 759d7ca5e1..0d9b8260bf 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1194,6 +1194,7 @@ struct sqlite3 { u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + u8 dfltOnError; /* Default conflict handling. OE_Abort */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ diff --git a/src/update.c b/src/update.c index 2a436b9701..ef1b1ddddb 100644 --- a/src/update.c +++ b/src/update.c @@ -794,7 +794,7 @@ static void updateVirtualTable( } sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); + sqlite3VdbeChangeP5(v, onError==OE_Default ? db->dfltOnError : onError); sqlite3MayAbort(pParse); /* End of the ephemeral table scan. Or, if using the onepass strategy, diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 145a365c54..a04c1fc48d 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -317,6 +317,8 @@ set pragma_def { NAME: soft_heap_limit NAME: threads + + NAME: onconflict } # Open the output file