aboutsummaryrefslogtreecommitdiff
path: root/src/tclsqlite.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2005-08-02 12:21:08 +0000
committerdrh <drh@noemail.net>2005-08-02 12:21:08 +0000
commit3d21423c6570bdf98de762a62643bed243ff4b80 (patch)
tree0b5883b0c112bfaf297bfded93ad2a2ff7261f37 /src/tclsqlite.c
parent943af3cda113716b176b1b367416ddd33b1e495a (diff)
downloadsqlite-3d21423c6570bdf98de762a62643bed243ff4b80.tar.gz
sqlite-3d21423c6570bdf98de762a62643bed243ff4b80.zip
Add the "transaction" coommand to the TCL interface. Untested. (CVS 2572)
FossilOrigin-Name: a5ce6c58c3bfc0e1c9953fe4ad4991ac56a4fb87
Diffstat (limited to 'src/tclsqlite.c')
-rw-r--r--src/tclsqlite.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index bc98e348d..f07d56009 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.128 2005/07/23 02:17:03 drh Exp $
+** $Id: tclsqlite.c,v 1.129 2005/08/02 12:21:09 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -591,8 +591,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
"function", "last_insert_rowid", "nullvalue",
"onecolumn", "progress", "rekey",
"timeout", "total_changes", "trace",
- "version",
- 0
+ "transaction", "version", 0
};
enum DB_enum {
DB_AUTHORIZER, DB_BUSY, DB_CACHE,
@@ -602,7 +601,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_NULLVALUE,
DB_ONECOLUMN, DB_PROGRESS, DB_REKEY,
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
- DB_VERSION
+ DB_TRANSACTION, DB_VERSION,
};
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
@@ -1490,6 +1489,63 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
+ /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT
+ **
+ ** Start a new transaction (if we are not already in the midst of a
+ ** transaction) and execute the TCL script SCRIPT. After SCRIPT
+ ** completes, either commit the transaction or roll it back if SCRIPT
+ ** throws an exception. Or if no new transation was started, do nothing.
+ ** pass the exception on up the stack.
+ **
+ ** This command was inspired by Dave Thomas's talk on Ruby at the
+ ** 2005 O'Reilly Open Source Convention (OSCON).
+ */
+ case DB_TRANSACTION: {
+ int inTrans;
+ Tcl_Obj *pScript;
+ const char *zBegin = "BEGIN";
+ if( objc!=3 && objc!=4 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT");
+ return TCL_ERROR;
+ }
+ if( objc==3 ){
+ pScript = objv[2];
+ } else {
+ static const char *TTYPE_strs[] = {
+ "deferred", "exclusive", "immediate"
+ };
+ enum TTYPE_enum {
+ TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE
+ };
+ int ttype;
+ if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction_type",
+ 0, &ttype) ){
+ return TCL_ERROR;
+ }
+ switch( (enum TTYPE_enum)ttype ){
+ case TTYPE_DEFERRED: /* no-op */; break;
+ case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break;
+ case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break;
+ }
+ pScript = objv[3];
+ }
+ inTrans = !sqlite3_get_autocommit(pDb->db);
+ if( !inTrans ){
+ sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
+ }
+ rc = Tcl_EvalObjEx(interp, pScript, 0);
+ if( !inTrans ){
+ const char *zEnd;
+ if( rc==TCL_ERROR ){
+ zEnd = "ROLLBACK";
+ } else {
+ zEnd = "COMMIT";
+ }
+ sqlite3_exec(pDb->db, zEnd, 0, 0, 0);
+ }
+ break;
+ }
+
/* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
**
** Copy data into table from filename, optionally using SEPARATOR