aboutsummaryrefslogtreecommitdiff
path: root/ext/session/test_session.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2011-07-13 15:21:02 +0000
committerdan <dan@noemail.net>2011-07-13 15:21:02 +0000
commit40368988da8bd6125a459e98fe6af1f5ecece54c (patch)
tree99234f8eb9d008e3411f49f6e464b985c7ea0106 /ext/session/test_session.c
parente437ca5ec0af264b3f299409d18c381800414082 (diff)
downloadsqlite-40368988da8bd6125a459e98fe6af1f5ecece54c.tar.gz
sqlite-40368988da8bd6125a459e98fe6af1f5ecece54c.zip
Add the xFilter callback to the sqlite3changeset_apply() function. This callback allows the application to accept or reject changes on a per-table basis when applying a changeset.
FossilOrigin-Name: 282474c42f24f0e66c69b576b72ef8ce764d49e2
Diffstat (limited to 'ext/session/test_session.c')
-rw-r--r--ext/session/test_session.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/ext/session/test_session.c b/ext/session/test_session.c
index 099307332..9817b3c2f 100644
--- a/ext/session/test_session.c
+++ b/ext/session/test_session.c
@@ -185,7 +185,8 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){
typedef struct TestConflictHandler TestConflictHandler;
struct TestConflictHandler {
Tcl_Interp *interp;
- Tcl_Obj *pScript;
+ Tcl_Obj *pConflictScript;
+ Tcl_Obj *pFilterScript;
};
static int test_obj_eq_string(Tcl_Obj *p, const char *z){
@@ -199,6 +200,29 @@ static int test_obj_eq_string(Tcl_Obj *p, const char *z){
return (nObj==n && (n==0 || 0==memcmp(zObj, z, n)));
}
+static int test_filter_handler(
+ void *pCtx, /* Pointer to TestConflictHandler structure */
+ const char *zTab /* Table name */
+){
+ TestConflictHandler *p = (TestConflictHandler *)pCtx;
+ int res = 1;
+ Tcl_Obj *pEval;
+ Tcl_Interp *interp = p->interp;
+
+ pEval = Tcl_DuplicateObj(p->pFilterScript);
+ Tcl_IncrRefCount(pEval);
+
+ if( TCL_OK!=Tcl_ListObjAppendElement(0, pEval, Tcl_NewStringObj(zTab, -1))
+ || TCL_OK!=Tcl_EvalObjEx(interp, pEval, TCL_EVAL_GLOBAL)
+ || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &res)
+ ){
+ Tcl_BackgroundError(interp);
+ }
+
+ Tcl_DecrRefCount(pEval);
+ return res;
+}
+
static int test_conflict_handler(
void *pCtx, /* Pointer to TestConflictHandler structure */
int eConf, /* DATA, MISSING, CONFLICT, CONSTRAINT */
@@ -213,7 +237,7 @@ static int test_conflict_handler(
const char *zTab; /* Name of table conflict is on */
int nCol; /* Number of columns in table zTab */
- pEval = Tcl_DuplicateObj(p->pScript);
+ pEval = Tcl_DuplicateObj(p->pConflictScript);
Tcl_IncrRefCount(pEval);
sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
@@ -342,7 +366,7 @@ static int test_conflict_handler(
}
/*
-** sqlite3changeset_apply DB CHANGESET SCRIPT
+** sqlite3changeset_apply DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
*/
static int test_sqlite3changeset_apply(
void * clientData,
@@ -357,8 +381,10 @@ static int test_sqlite3changeset_apply(
int nChangeset; /* Size of buffer aChangeset in bytes */
TestConflictHandler ctx;
- if( objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB CHANGESET SCRIPT");
+ if( objc!=4 && objc!=5 ){
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"
+ );
return TCL_ERROR;
}
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){
@@ -367,11 +393,12 @@ static int test_sqlite3changeset_apply(
}
db = *(sqlite3 **)info.objClientData;
pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeset);
- ctx.pScript = objv[3];
+ ctx.pConflictScript = objv[3];
+ ctx.pFilterScript = objc==5 ? objv[4] : 0;
ctx.interp = interp;
- rc = sqlite3changeset_apply(
- db, nChangeset, pChangeset, test_conflict_handler, (void *)&ctx
+ rc = sqlite3changeset_apply(db, nChangeset, pChangeset,
+ (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx
);
if( rc!=SQLITE_OK ){
return test_session_error(interp, rc);